├── README.md ├── src ├── Regions.js ├── LocalWebsocket.js ├── LocalClient.js ├── StandaloneClient.js └── GenericClient.js ├── index.js ├── package.json ├── LICENSE └── .gitignore /README.md: -------------------------------------------------------------------------------- 1 | # valorant-api 2 | Unofficial wrapper for the Valorant in-game API. 3 | -------------------------------------------------------------------------------- /src/Regions.js: -------------------------------------------------------------------------------- 1 | const Regions = { 2 | AsiaPacific: 'ap', 3 | Europe: 'eu', 4 | Korea: 'ko', 5 | NorthAmerica: 'na' 6 | } 7 | 8 | module.exports = Regions; -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | Regions: require('./src/Regions'), 3 | LocalClient: require('./src/LocalClient'), 4 | StandaloneClient: require('./src/StandaloneClient') 5 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "valorant-api", 3 | "version": "1.0.0", 4 | "description": "Unofficial wrapper for the Valorant in-game API.", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Burak ", 10 | "license": "UNLICENSED", 11 | "dependencies": { 12 | "axios": "^0.21.1", 13 | "axios-cookiejar-support": "^1.0.1", 14 | "axios-socks5-agent": "^1.0.1", 15 | "http-proxy-agent": "^7.0.0", 16 | "https-proxy-agent": "^7.0.2", 17 | "tough-cookie": "^4.0.0", 18 | "ws": "^7.4.6" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/LocalWebsocket.js: -------------------------------------------------------------------------------- 1 | const WebSocket = require('ws'); 2 | const EventEmitter = require('events'); 3 | 4 | class LocalWebsocket extends EventEmitter { 5 | constructor(lockfile) { 6 | super(); 7 | this._lockfile = lockfile; 8 | this._eventsQueue = []; 9 | } 10 | 11 | subscribeToEvents(events = []) { 12 | this._eventsQueue = this._eventsQueue.concat(events); 13 | } 14 | 15 | subscribeToEvent(event) { 16 | this._eventsQueue.push(event); 17 | } 18 | 19 | connect() { 20 | this.ws = new WebSocket(`wss://riot:${this._lockfile.password}@127.0.0.1:${this._lockfile.port}`, { 21 | rejectUnauthorized: false 22 | }); 23 | 24 | this.ws.on('open', () => { 25 | this._eventsQueue.forEach(eventName => { 26 | this.ws.send(JSON.stringify([5, eventName])); 27 | }); 28 | }); 29 | 30 | this.ws.on('message', data => { 31 | try { 32 | let json = JSON.parse(data); 33 | 34 | this.emit(json[1], json[2]); 35 | } catch { 36 | } 37 | }); 38 | } 39 | } 40 | 41 | module.exports = LocalWebsocket; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | -------------------------------------------------------------------------------- /src/LocalClient.js: -------------------------------------------------------------------------------- 1 | const GenericClient = require('./GenericClient'); 2 | const LocalWebsocket = require('./LocalWebsocket'); 3 | 4 | const fs = require('fs'); 5 | const path = require('path'); 6 | const axios = require('axios'); 7 | const https = require('https'); 8 | 9 | class LocalClient extends GenericClient { 10 | constructor(lockfilePath = path.join(process.env['LOCALAPPDATA'], 'Riot Games\\Riot Client\\Config\\lockfile')) { 11 | super(); 12 | 13 | this._lockfilePath = lockfilePath; 14 | } 15 | 16 | async init(region = 'eu') { 17 | if (region == 'latam' || region == 'br' || region == 'na') { 18 | this._shard = 'na'; 19 | } else { 20 | this._shard = region; 21 | } 22 | 23 | this._region = region; 24 | this._lockfile = await this._getLockfileData(); 25 | await this._buildHeaders(); 26 | } 27 | 28 | async _getLockfileData() { 29 | const contents = await fs.promises.readFile(this._lockfilePath, 'utf8'); 30 | 31 | let d = {}; 32 | [d.name, d.pid, d.port, d.password, d.protocol] = contents.split(':'); 33 | 34 | return d; 35 | } 36 | 37 | async _getValorantClientVersion() { 38 | let version = (await fs.promises.readFile(path.join(process.env.LOCALAPPDATA, '/VALORANT/Saved/Logs/ShooterGame.log'), 'utf8')).match(/CI server version: (.+)/)[1].split('-'); 39 | version.splice(2, 0, 'shipping'); 40 | 41 | return version.join('-'); 42 | } 43 | 44 | async _buildHeaders() { 45 | this.localHeaders = { 46 | 'Authorization': 'Basic ' + Buffer.from(`riot:${this._lockfile.password}`, 'utf8').toString('base64'), 47 | 'X-Riot-ClientVersion': await this._getValorantClientVersion(), 48 | 'Content-Type': 'application/json', 49 | 'rchat-blocking': true 50 | }; 51 | 52 | let response = await axios.get(`${this._lockfile.protocol}://127.0.0.1:${this._lockfile.port}/entitlements/v1/token`, { 53 | headers: this.localHeaders, 54 | httpsAgent: new https.Agent({ 55 | rejectUnauthorized: false 56 | }) 57 | }); 58 | 59 | this.puuid = response.data.subject; 60 | 61 | this.remoteHeaders = { 62 | 'Authorization': 'Bearer ' + response.data.accessToken, 63 | 'X-Riot-Entitlements-JWT': response.data.token, 64 | 'X-Riot-ClientPlatform': 'ew0KCSJwbGF0Zm9ybVR5cGUiOiAiUEMiLA0KCSJwbGF0Zm9ybU9TIjogIldpbmRvd3MiLA0KCSJwbGF0Zm9ybU9TVmVyc2lvbiI6ICIxMC4wLjE5MDQyLjEuMjU2LjY0Yml0IiwNCgkicGxhdGZvcm1DaGlwc2V0IjogIlVua25vd24iDQp9', 65 | 'X-Riot-ClientVersion': await this._getValorantClientVersion() 66 | }; 67 | } 68 | 69 | async initializeWebsocket() { 70 | return new LocalWebsocket(this._lockfile); 71 | } 72 | 73 | async logout() { 74 | return await this.fetch('/rso-auth/v1/session', 'local', 'delete'); 75 | } 76 | 77 | async login(username, password, persistLogin = false) { 78 | return await this.fetch('/rso-auth/v1/session/credentials', { 79 | 'username': username, 80 | 'password': password, 81 | 'persistLogin': persistLogin 82 | }); 83 | } 84 | 85 | async getHelp() { 86 | return await this.fetch('/help', 'local'); 87 | } 88 | 89 | async getPresences() { 90 | let presences = await this.fetch('/chat/v4/presences', 'local'); 91 | 92 | return presences.presences.filter(presence => presence.product == 'valorant').map(presence => { 93 | presence.private = JSON.parse(Buffer.from(presence.private, 'base64').toString()); 94 | 95 | return presence; 96 | }); 97 | } 98 | 99 | async getPresence(puuid) { 100 | let presences = await this.getPresences(); 101 | 102 | return presences.find(presence => presence.puuid == (puuid ? puuid : this.puuid)); 103 | } 104 | 105 | async getFriends() { 106 | let friends = await this.fetch('/chat/v4/friends', 'local'); 107 | 108 | return friends.friends; 109 | } 110 | 111 | async getFriendRequests() { 112 | return await this.fetch('/chat/v4/friendrequests', 'local'); 113 | } 114 | 115 | async removeFriendRequest(puuid) { 116 | return await this.fetch('/chat/v4/friendrequests', 'local', 'delete', { 117 | 'puuid': puuid 118 | }); 119 | } 120 | 121 | async addFriend(gameName, gameTag) { 122 | return await this.fetch('/chat/v4/friendrequests', 'local', 'post', { 123 | 'game_name': gameName, 124 | 'game_tag': gameTag 125 | }); 126 | } 127 | 128 | async removeFriend(puuid) { 129 | return await this.fetch('/chat/v4/friends', 'local', 'delete', { 130 | 'puuid': puuid 131 | }); 132 | } 133 | 134 | async sendMessage(message, cid) { 135 | return await this.fetch('/chat/v5/messages', 'local', 'post', { 136 | 'message': message, 137 | 'cid': cid 138 | }); 139 | } 140 | } 141 | 142 | module.exports = LocalClient; -------------------------------------------------------------------------------- /src/StandaloneClient.js: -------------------------------------------------------------------------------- 1 | const GenericClient = require('./GenericClient'); 2 | const axios = require('axios').default; 3 | const axiosCookieJarSupport = require('axios-cookiejar-support').default; 4 | const tough = require('tough-cookie'); 5 | const https = require('https'); 6 | 7 | const ciphers = [ 8 | 'TLS_CHACHA20_POLY1305_SHA256', 9 | 'TLS_AES_128_GCM_SHA256', 10 | 'TLS_AES_256_GCM_SHA384', 11 | 'TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256' 12 | ]; 13 | 14 | const httpsAgent = new https.Agent({ 15 | ciphers: ciphers.join(':'), 16 | honorCipherOrder: true, 17 | minVersion: 'TLSv1.2' 18 | }); 19 | 20 | axiosCookieJarSupport(axios); 21 | 22 | function makeid(length) { 23 | let result = ''; 24 | const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; 25 | const charactersLength = characters.length; 26 | let counter = 0; 27 | while (counter < length) { 28 | result += characters.charAt(Math.floor(Math.random() * charactersLength)); 29 | counter += 1; 30 | } 31 | return result; 32 | } 33 | 34 | class StandaloneClient extends GenericClient { 35 | constructor(username, password) { 36 | super(); 37 | 38 | this._username = username; 39 | this._password =password; 40 | } 41 | 42 | async init(region = 'eu') { 43 | if (region == 'latam' || region == 'br' || region == 'na') { 44 | this._shard = 'na'; 45 | } else { 46 | this._shard = region; 47 | } 48 | 49 | this._region = region; 50 | await this._buildHeaders(); 51 | } 52 | 53 | async _getValorantClientVersion() { 54 | return (await axios.get('https://valorant-api.com/v1/version')).data.data.riotClientVersion; 55 | } 56 | 57 | async _buildHeaders() { 58 | const cookieJar = new tough.CookieJar(); 59 | 60 | const randomUserAgent = makeid(30); 61 | 62 | let data = { 63 | 'client_id': 'play-valorant-web-prod', 64 | 'nonce': '1', 65 | 'redirect_uri': 'https://playvalorant.com/opt_in', 66 | 'response_type': 'token id_token', 67 | }; 68 | 69 | let response = await axios.post('https://auth.riotgames.com/api/v1/authorization', data, { 70 | jar: cookieJar, 71 | withCredentials: true, 72 | headers: { 73 | "User-Agent": randomUserAgent, 74 | "Cache-Control": "no-cache", 75 | "Accept": "application/json", 76 | "Content-Type": "application/json" 77 | }, 78 | httpsAgent: httpsAgent 79 | }); 80 | 81 | 82 | data = { 83 | "language": "en_US", 84 | 'password': this._password, 85 | 'remember': true, 86 | 'type': 'auth', 87 | 'username': this._username, 88 | }; 89 | 90 | response = await axios.put('https://auth.riotgames.com/api/v1/authorization', data, { 91 | jar: cookieJar, 92 | withCredentials: true, 93 | headers: { 94 | "User-Agent": randomUserAgent, 95 | "Cache-Control": "no-cache", 96 | "Accept": "application/json", 97 | "Content-Type": "application/json" 98 | }, 99 | httpsAgent: httpsAgent 100 | }); 101 | 102 | let uri = response.data.response.parameters.uri; 103 | let strTokens = uri.replace('https://playvalorant.com/opt_in#', '').split('&'); 104 | 105 | let arrayTokens = {}; 106 | 107 | strTokens.forEach(token => { 108 | arrayTokens[token.split('=')[0]] = token.split('=')[1]; 109 | }); 110 | 111 | var accessToken = arrayTokens.access_token; 112 | 113 | let headers = { 114 | 'Authorization': `Bearer ${arrayTokens.access_token}`, 115 | "User-Agent": randomUserAgent, 116 | "Cache-Control": "no-cache", 117 | "Accept": "application/json", 118 | "Content-Type": "application/json" 119 | }; 120 | 121 | response = await axios.post('https://entitlements.auth.riotgames.com/api/token/v1', {}, { 122 | jar: cookieJar, 123 | withCredentials: true, 124 | headers, 125 | httpsAgent: httpsAgent 126 | }); 127 | 128 | var entitlementsToken = response.data.entitlements_token; 129 | 130 | response = await axios.post('https://auth.riotgames.com/userinfo', {}, { 131 | jar: cookieJar, 132 | withCredentials: true, 133 | headers, 134 | httpsAgent: httpsAgent 135 | }); 136 | 137 | this.puuid = response.data.sub; 138 | 139 | this.remoteHeaders = { 140 | 'Authorization': 'Bearer ' + accessToken, 141 | 'X-Riot-Entitlements-JWT': entitlementsToken, 142 | 'X-Riot-ClientPlatform': 'ew0KCSJwbGF0Zm9ybVR5cGUiOiAiUEMiLA0KCSJwbGF0Zm9ybU9TIjogIldpbmRvd3MiLA0KCSJwbGF0Zm9ybU9TVmVyc2lvbiI6ICIxMC4wLjE5MDQyLjEuMjU2LjY0Yml0IiwNCgkicGxhdGZvcm1DaGlwc2V0IjogIlVua25vd24iDQp9', 143 | 'X-Riot-ClientVersion': await this._getValorantClientVersion() 144 | }; 145 | } 146 | } 147 | 148 | module.exports = StandaloneClient; -------------------------------------------------------------------------------- /src/GenericClient.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios'); 2 | const https = require('https'); 3 | const SocksAgent = require('axios-socks5-agent'); 4 | const HttpsProxyAgent = require('https-proxy-agent').HttpsProxyAgent; 5 | const HttpProxyAgent = require('http-proxy-agent').HttpProxyAgent; 6 | 7 | const ciphers = [ 8 | 'TLS_CHACHA20_POLY1305_SHA256', 9 | 'TLS_AES_128_GCM_SHA256', 10 | 'TLS_AES_256_GCM_SHA384', 11 | 'TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256' 12 | ]; 13 | 14 | class GenericClient { 15 | async fetch(endpoint, endpointType, method = 'GET', data = null) { 16 | try { 17 | var response, axiosEndpoint, axiosOptions; 18 | 19 | if (endpointType == 'local') { 20 | axiosEndpoint = `${this._lockfile.protocol}://127.0.0.1:${this._lockfile.port}${endpoint}`; 21 | axiosHeaders = this.localHeaders; 22 | axiosOptions = { 23 | method: method.toUpperCase(), 24 | headers: this.localHeaders, 25 | httpsAgent: new https.Agent({ 26 | rejectUnauthorized: false, 27 | ciphers: ciphers.join(':'), 28 | honorCipherOrder: true, 29 | minVersion: 'TLSv1.2' 30 | }), 31 | data: data 32 | }; 33 | } else if (endpointType == 'glz') { 34 | axiosEndpoint = `https://glz-${this._region}-1.${this._shard}.a.pvp.net${endpoint}`; 35 | axiosOptions = { 36 | method: method.toUpperCase(), 37 | headers: this.remoteHeaders, 38 | data: data, 39 | httpsAgent: new https.Agent({ 40 | ciphers: ciphers.join(':'), 41 | honorCipherOrder: true, 42 | minVersion: 'TLSv1.2' 43 | }) 44 | }; 45 | } else if (endpointType == 'pd') { 46 | axiosEndpoint = `https://pd.${this._shard}.a.pvp.net${endpoint}`; 47 | axiosOptions = { 48 | method: method.toUpperCase(), 49 | headers: this.remoteHeaders, 50 | data: data, 51 | httpsAgent: new https.Agent({ 52 | ciphers: ciphers.join(':'), 53 | honorCipherOrder: true, 54 | minVersion: 'TLSv1.2' 55 | }) 56 | }; 57 | } else if (endpointType == 'raw') { 58 | axiosEndpoint = endpoint; 59 | axiosOptions = { 60 | method: method.toUpperCase(), 61 | headers: this.remoteHeaders, 62 | data: data, 63 | httpsAgent: new https.Agent({ 64 | ciphers: ciphers.join(':'), 65 | honorCipherOrder: true, 66 | minVersion: 'TLSv1.2' 67 | }) 68 | }; 69 | } 70 | 71 | if (this.proxyEnabled && endpointType != 'local') { 72 | axiosOptions.httpAgent = this.proxyAgents.httpAgent; 73 | axiosOptions.httpsAgent = this.proxyAgents.httpsAgent; 74 | } 75 | 76 | if (this.timeout) { 77 | axiosOptions.timeout = this.timeout; 78 | } 79 | 80 | response = await axios.request(axiosEndpoint, axiosOptions); 81 | 82 | return response.data; 83 | } catch (e) { 84 | throw e; 85 | } 86 | } 87 | 88 | setTimeout(timeout) { 89 | this.timeout = timeout; 90 | } 91 | 92 | setProxy(proxyHost, proxyPort, proxyType) { 93 | this.proxyEnabled = true; 94 | 95 | if (proxyType == 'http') { 96 | this.proxyAgents = { 97 | httpAgent: new HttpProxyAgent(`http://${proxyHost}:${proxyPort}`, { keepAlive: false }), 98 | httpsAgent: new HttpsProxyAgent(`http://${proxyHost}:${proxyPort}`, { keepAlive: false, rejectUnauthorized: false }) 99 | } 100 | } else if (proxyType == 'socks') { 101 | this.proxyAgents = new SocksAgent({ 102 | host: proxyHost, 103 | port: proxyPort, 104 | agentOptions: { keepAlive: false, rejectUnauthorized: false } 105 | }); 106 | } else { 107 | throw new Error('not supported proxy type'); 108 | } 109 | } 110 | 111 | async fetchAccountXP() { 112 | return await this.fetch(`/account-xp/v1/players/${this.puuid}`, 'pd'); 113 | } 114 | 115 | async fetchContracts() { 116 | return await this.fetch(`/contracts/v1/contracts/${this.puuid}`, 'pd'); 117 | } 118 | 119 | async fetchContractDefinitions() { 120 | return await this.fetch('/contract-definitions/v2/definitions', 'pd'); 121 | } 122 | 123 | async fetchContractDefinitionsItemUpgrades() { 124 | return await this.fetch('/contract-definitions/v3/item-upgrades', 'pd'); 125 | } 126 | 127 | async activateContract(contractId) { 128 | return await this.fetch(`/contracts/v1/contracts/${this.puuid}/special/${contractId}`, 'pd'); 129 | } 130 | 131 | async fetchActiveBattlePass() { 132 | return await this.fetch('/contract-definitions/v2/definitions/story', 'pd'); 133 | } 134 | 135 | async coregameFetchPlayer() { 136 | return await this.fetch(`/core-game/v1/players/${this.puuid}`, 'glz'); 137 | } 138 | 139 | async coregameFetchMatch(matchId) { 140 | return await this.fetch(`/core-game/v1/matches/${matchId}`, 'glz'); 141 | } 142 | 143 | async coregameFetchMatchLoadouts(matchId) { 144 | return await this.fetch(`/core-game/v1/matches/${matchId}/loadouts`, 'glz'); 145 | } 146 | 147 | async coregameDisassociatePlayer(matchId) { 148 | return await this.fetch(`/core-game/v1/players/${this.puuid}/disassociate/${matchId}`, 'glz'); 149 | } 150 | 151 | async fetchMatchDetails(matchId) { 152 | return await this.fetch(`/match-details/v1/matches/${matchId}`, 'pd'); 153 | } 154 | 155 | async fetchMatchHistory(puuid, startIndex = 0, endIndex = 15, queueId) { 156 | puuid = puuid ? puuid : this.puuid; 157 | 158 | return await this.fetch(`/match-history/v1/history/${puuid}?startIndex=${startIndex}&endIndex=${endIndex}` + (queueId ? `&queue=${queueId}` : ''), 'pd'); 159 | } 160 | 161 | async fetchMMR(puuid) { 162 | puuid = puuid ? puuid : this.puuid; 163 | 164 | return await this.fetch(`/mmr/v1/players/${puuid}`, 'pd'); 165 | } 166 | 167 | async fetchCompetitiveUpdates(puuid, startIndex = 0, endIndex = 15, queueId) { 168 | puuid = puuid ? puuid : this.puuid; 169 | 170 | return await this.fetch(`/mmr/v1/players/${puuid}/competitiveupdates?startIndex=${startIndex}&endIndex=${endIndex}` + (queueId ? `&queue=${queueId}` : ''), 'pd'); 171 | } 172 | 173 | async fetchLeaderboard(seasonId, startIndex = 0, size = 1000) { 174 | return await this.fetch(`/mmr/v1/leaderboards/affinity/${this._region}/queue/competitive/season/${seasonId}?startIndex=${startIndex}&size=${size}`, 'pd'); 175 | } 176 | 177 | async fetchPlayerLoadout(puuid) { 178 | puuid = puuid ? puuid : this.puuid; 179 | 180 | return await this.fetch(`/personalization/v2/players/${puuid}/playerloadout`, 'pd'); 181 | } 182 | 183 | async fetchPartyFromPuuid(puuid) { 184 | puuid = puuid ? puuid : this.puuid; 185 | 186 | return await this.fetch(`/parties/v1/players/${puuid}`, 'glz'); 187 | } 188 | 189 | async fetchPartyFromPartyId(partyId) { 190 | return await this.fetch(`/parties/v1/parties/${partyId}`, 'glz'); 191 | } 192 | 193 | async fetchPartyCustomGameConfigs() { 194 | return await this.fetch(`/parties/v1/parties/customgameconfigs`, 'glz'); 195 | } 196 | 197 | async enterMatchmakingQueue(partyId) { 198 | return await this.fetch(`/parties/v1/parties/${partyId}/matchmaking/join`, 'glz', 'post'); 199 | } 200 | 201 | async setPartyAccessibility(partyId, state = 'OPEN') { 202 | return await this.fetch(`/parties/v1/parties/${partyId}/accessibility`, 'glz', 'post', { 203 | 'Accessibility': state.toUpperCase() 204 | }) 205 | } 206 | 207 | async setPartyQueue(partyId, queueId = 'unrated') { 208 | return await this.fetch(`/parties/v1/parties/${partyId}/makedefault?queueID=${queueId}`, 'glz', 'post'); 209 | } 210 | 211 | async makeCustomGame(partyId) { 212 | return await this.fetch(`/parties/v1/parties/${partyId}/makecustomgame`, 'glz', 'post'); 213 | } 214 | 215 | async setCustomGameSettings(partyId, map = 'Ascent', mode = '/Game/GameModes/Bomb/BombGameMode.BombGameMode_C', server = 'aresriot.aws-rclusterprod-use1-1.na-gp-ashburn-1') { 216 | return await this.fetch(`/parties/v1/parties/${partyId}/customgamesettings`, 'glz', 'post', { 217 | 'map': `/Game/Maps/${map}/${map}`, 218 | 'Mode': mode, 219 | 'GamePod': server 220 | }); 221 | } 222 | 223 | async joinParty(partyId) { 224 | return await this.fetch(`/parties/v1/players/${this.puuid}/joinparty/${partyId}`, 'glz', 'post'); 225 | } 226 | 227 | async leaveParty(partyId) { 228 | return await this.fetch(`/parties/v1/players/${this.puuid}/leaveparty/${partyId}`, 'glz', 'post'); 229 | } 230 | 231 | async pregameFetchPlayer(puuid) { 232 | puuid = puuid ? puuid : this.puuid; 233 | 234 | return await this.fetch(`/pregame/v1/players/${puuid}`, 'glz'); 235 | } 236 | 237 | async pregameFetchMatch(matchId) { 238 | return await this.fetch(`/pregame/v1/matches/${matchId}`, 'glz'); 239 | } 240 | 241 | async pregameFetchLoadouts(matchId) { 242 | return await this.fetch(`/pregame/v1/matches/${matchId}/loadouts`, 'glz'); 243 | } 244 | 245 | async selectCharacter(matchId, characterId) { 246 | return await this.fetch(`/pregame/v1/matches/${matchId}/select/${characterId}`, 'glz', 'post'); 247 | } 248 | 249 | async lockCharacter(matchId, characterId) { 250 | return await this.fetch(`/pregame/v1/matches/${matchId}/lock/${characterId}`, 'glz', 'post'); 251 | } 252 | 253 | async fetchPenalties() { 254 | return await this.fetch('/restrictions/v2/penalties', 'pd'); 255 | } 256 | 257 | async fetchSession(puuid) { 258 | puuid = puuid ? puuid : this.puuid; 259 | 260 | return await this.fetch(`/session/v1/sessions/${puuid}`, 'glz'); 261 | } 262 | 263 | async fetchStoreEntitlements(puuid, itemType = 'e7c63390-eda7-46e0-bb7a-a6abdacd2433') { 264 | puuid = puuid ? puuid : this.puuid; 265 | 266 | return await this.fetch(`/store/v1/entitlements/${puuid}/${itemType}`, 'pd'); 267 | } 268 | 269 | async fetchStoreOffers() { 270 | return await this.fetch(`/store/v1/offers/`, 'pd'); 271 | } 272 | 273 | async fetchWallet() { 274 | return await this.fetch(`/store/v1/wallet/${this.puuid}`, 'pd'); 275 | } 276 | 277 | async fetchStoreFront() { 278 | return await this.fetch(`/store/v2/storefront/${this.puuid}`, 'pd'); 279 | } 280 | 281 | async fetchUsernamesFromPuuids(ids = []) { 282 | return await this.fetch('/name-service/v2/players', 'pd', 'put', ids); 283 | } 284 | } 285 | 286 | module.exports = GenericClient; --------------------------------------------------------------------------------