├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE │ ├── config.yml │ ├── 2-feature_request.yml │ └── 1-bug_report.yml ├── .env.example ├── src ├── config.json ├── events │ ├── error.js │ ├── ready.js │ └── disconnected.js ├── utils │ ├── reconnectRpc.js │ ├── handlers.js │ ├── updateNotifier.js │ ├── logger.js │ └── verifyConfig.js ├── index.js └── rpc │ └── rpc.js ├── LICENSE ├── package.json ├── .gitignore ├── README.md └── pnpm-lock.yaml /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: noowz -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | NODE_ENV="production" 2 | DISCORD_CLIENT_ID="839894528953810944" 3 | BRAWL_STARS_API_KEY= 4 | BRAWL_STARS_PLAYER_TAG= -------------------------------------------------------------------------------- /src/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "apis": { 3 | "brawlstars": { 4 | "base_url": "https://api.brawlstars.com" 5 | }, 6 | "brawlAPINutella": { 7 | "base_url": "https://api.rnt.dev" 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: 💬 Discord 4 | url: https://discord.com/users/163656084714815491 5 | about: If you are experiencing issues, send me a DM in Discord. 6 | -------------------------------------------------------------------------------- /src/events/error.js: -------------------------------------------------------------------------------- 1 | const { logger } = require("../utils/logger.js"); 2 | 3 | const error = { 4 | name: "error", 5 | once: false, 6 | 7 | execute() { 8 | logger.error(error); 9 | } 10 | }; 11 | 12 | module.exports = error; -------------------------------------------------------------------------------- /src/events/ready.js: -------------------------------------------------------------------------------- 1 | const { logger } = require("../utils/logger.js"); 2 | const { rpc } = require("../rpc/rpc.js"); 3 | const { greenBright } = require("chalk"); 4 | 5 | const ready = { 6 | name: "ready", 7 | once: true, 8 | 9 | execute(client) { 10 | rpc(client); 11 | 12 | setInterval(() => { 13 | rpc(client); 14 | }, 6 * 1000); 15 | 16 | logger.info(`Rich Presence ${greenBright("connected")} to Discord!`); 17 | } 18 | }; 19 | 20 | module.exports = ready; -------------------------------------------------------------------------------- /src/events/disconnected.js: -------------------------------------------------------------------------------- 1 | const { logger } = require("../utils/logger.js"); 2 | const { reconnectRpc } = require("../utils/reconnectRpc.js"); 3 | const { redBright, greenBright } = require("chalk"); 4 | 5 | const disconnected = { 6 | name: "disconnected", 7 | once: false, 8 | 9 | async execute(oldClient) { 10 | logger.warn(`Rich Presence ${redBright("disconnected")} from Discord!`); 11 | 12 | oldClient.destroy(); 13 | 14 | logger.warn(`${greenBright("Reconnecting")} to Discord...`); 15 | 16 | await reconnectRpc(); 17 | } 18 | }; 19 | 20 | module.exports = disconnected; -------------------------------------------------------------------------------- /src/utils/reconnectRpc.js: -------------------------------------------------------------------------------- 1 | const { logger } = require("../utils/logger.js"); 2 | const { rpc } = require("../rpc/rpc.js"); 3 | const { Client } = require("discord-rpc"); 4 | const { greenBright } = require("chalk"); 5 | 6 | async function reconnectRpc() { 7 | try { 8 | const newClient = new Client({ 9 | transport: "ipc" 10 | }); 11 | 12 | newClient.once("ready", () => { 13 | logger.info(`Rich Presence ${greenBright("reconnected")} to Discord!`); 14 | 15 | rpc(newClient); 16 | }); 17 | 18 | await newClient.login({ 19 | clientId: process.env.DISCORD_CLIENT_ID 20 | }); 21 | } catch (error) { 22 | setTimeout(() => reconnectRpc(), 5 * 1000); 23 | }; 24 | }; 25 | 26 | module.exports = { reconnectRpc }; -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/2-feature_request.yml: -------------------------------------------------------------------------------- 1 | name: "✨ Feature Request" 2 | description: Suggest a new feature or an improvement. 3 | assignees: 4 | - noowz 5 | labels: 6 | - enhancement 7 | title: "✨ [Feature]: " 8 | body: 9 | - type: textarea 10 | id: description 11 | attributes: 12 | label: Description 13 | description: Explain how this feature would work and why it is useful. 14 | validations: 15 | required: true 16 | - type: dropdown 17 | id: priority 18 | attributes: 19 | label: Priority 20 | description: How important is this feature to you? 21 | options: 22 | - Low 23 | - Medium 24 | - High 25 | validations: 26 | required: true 27 | - type: input 28 | id: additional_context 29 | attributes: 30 | label: Additional context 31 | description: Any other information, links, or references that might help. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Noowz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | require("dotenv").config(); 2 | const { logger } = require("./utils/logger.js"); 3 | const { updateNotifier } = require("./utils/updateNotifier.js"); 4 | const { verifyConfig } = require("./utils/verifyConfig.js"); 5 | const { eventsHandler } = require("./utils/handlers.js"); 6 | const { yellowBright } = require("chalk"); 7 | const { Client } = require("discord-rpc"); 8 | 9 | const currentEnv = process.env.NODE_ENV; 10 | 11 | logger.application(`The current development environment is set to ${yellowBright(currentEnv)}!`); 12 | 13 | async function initializeClient() { 14 | try { 15 | await verifyConfig(); 16 | await updateNotifier(); 17 | 18 | const client = new Client({ 19 | transport: "ipc" 20 | }); 21 | 22 | await eventsHandler(client); 23 | 24 | await client.login({ 25 | clientId: process.env.DISCORD_CLIENT_ID 26 | }); 27 | } catch (error) { 28 | logger.error(error); 29 | }; 30 | }; 31 | 32 | initializeClient(); 33 | 34 | process.on("unhandledRejection", (error) => { 35 | if (error?.message?.includes("connection closed")) { 36 | return; 37 | }; 38 | 39 | console.error("Unhandled promise rejection:", error); 40 | }); -------------------------------------------------------------------------------- /src/utils/handlers.js: -------------------------------------------------------------------------------- 1 | const { logger } = require("../utils/logger.js"); 2 | const { join } = require("node:path"); 3 | const { readdirSync } = require("node:fs"); 4 | const { yellowBright, bold } = require("chalk"); 5 | 6 | async function eventsHandler(client) { 7 | const eventsPath = join(__dirname, "../events"); 8 | const eventFiles = readdirSync(eventsPath).filter(file => file.endsWith(".js")); 9 | 10 | let eventsLoaded = 0; 11 | 12 | for (const file of eventFiles) { 13 | const filePath = join(eventsPath, file); 14 | const event = require(filePath); 15 | 16 | if (event.once) { 17 | client.once(event.name, (...args) => { 18 | event.execute(client, ...args); 19 | }); 20 | 21 | eventsLoaded++; 22 | 23 | logger.info(`Loaded ${yellowBright(file.slice(0, -3))} event ${bold.greenBright(`(${eventsLoaded}/${eventFiles.length})`)}!`); 24 | } else { 25 | client.on(event.name, (...args) => { 26 | event.execute(client, ...args) 27 | }); 28 | 29 | eventsLoaded++; 30 | 31 | logger.info(`Loaded ${yellowBright(file.slice(0, -3))} event ${bold.greenBright(`(${eventsLoaded}/${eventFiles.length})`)}!`); 32 | }; 33 | }; 34 | }; 35 | 36 | module.exports = { eventsHandler }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "brawl-stars-discord-rich-presence", 3 | "version": "1.1.1", 4 | "private": true, 5 | "description": "Discord Rich Presence that shows on your profile your Brawl Stars statistics.", 6 | "main": "src/index.js", 7 | "scripts": { 8 | "start": "node .", 9 | "dev": "nodemon ." 10 | }, 11 | "author": { 12 | "name": "Noowz", 13 | "email": "danieeel.dev@gmail.com", 14 | "url": "https://github.com/noowz" 15 | }, 16 | "contributors": [], 17 | "license": "MIT", 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/noowz/brawl-stars-discord-rich-presence" 21 | }, 22 | "bugs": { 23 | "url": "https://github.com/noowz/brawl-stars-discord-rich-presence/issues" 24 | }, 25 | "homepage": "https://github.com/noowz/brawl-stars-discord-rich-presence#readme", 26 | "keywords": [ 27 | "discord", 28 | "discordapp", 29 | "rpc", 30 | "discord-js", 31 | "djs", 32 | "supercell", 33 | "rich-presence", 34 | "brawl-stars", 35 | "brawl-stars-api", 36 | "supercell-brawl-stars" 37 | ], 38 | "funding": [ 39 | { 40 | "type": "github", 41 | "url": "https://github.com/sponsors/noowz" 42 | } 43 | ], 44 | "dependencies": { 45 | "axios": "^1.13.2", 46 | "boxen": "^8.0.1", 47 | "chalk": "4.1.2", 48 | "discord-rpc": "^4.0.1", 49 | "dotenv": "^17.2.3", 50 | "google-play-scraper": "9.2.0" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/utils/updateNotifier.js: -------------------------------------------------------------------------------- 1 | const { name, version, author } = require("../../package.json"); 2 | const { logger } = require("./logger.js"); 3 | const { greenBright, yellowBright, redBright, blueBright } = require("chalk"); 4 | const boxen = require("boxen").default; 5 | const axios = require("axios"); 6 | 7 | async function updateNotifier() { 8 | const response = await axios({ 9 | method: "GET", 10 | url: `https://api.github.com/repos/${author.name}/${name}/releases/latest`, 11 | headers: { 12 | "Content-Type": "application/json", 13 | "User-Agent": `${name}/${version}` 14 | } 15 | }).catch((error) => { 16 | logger.error(error); 17 | 18 | return; 19 | }); 20 | 21 | const release = await response.data; 22 | 23 | const currentVersion = version; 24 | const latestVersion = release.tag_name.replace("v", ""); 25 | 26 | if (currentVersion < latestVersion) { 27 | const text = [ 28 | `${greenBright("🚀 A new version of")} ${yellowBright(name)} ${greenBright("is available!")}`, 29 | ``, 30 | `${redBright(`• Current version: ${currentVersion}`)}`, 31 | `${greenBright(`• Latest version: ${latestVersion}`)}`, 32 | ``, 33 | `${blueBright(release.html_url)}` 34 | ].join("\n"); 35 | 36 | console.log(boxen(text, { 37 | borderStyle: "round", 38 | title: `${greenBright("New Update Available")}`, 39 | padding: 1, 40 | margin: 1 41 | })); 42 | }; 43 | }; 44 | 45 | module.exports = { updateNotifier }; -------------------------------------------------------------------------------- /src/utils/logger.js: -------------------------------------------------------------------------------- 1 | const { magentaBright, cyanBright, yellowBright, redBright, bold, gray } = require("chalk"); 2 | 3 | const levels = { 4 | debug: magentaBright, 5 | info: cyanBright, 6 | warn: yellowBright, 7 | error: redBright, 8 | fatal: bold.redBright, 9 | application: bold.blueBright 10 | }; 11 | 12 | const levelPriority = { 13 | debug: 0, 14 | info: 1, 15 | warn: 2, 16 | error: 3, 17 | fatal: 4, 18 | application: 5 19 | }; 20 | 21 | const envLogLevels = { 22 | development: "debug", 23 | production: "info", 24 | test: "error" 25 | }; 26 | 27 | const currentEnv = process.env.NODE_ENV; 28 | const minLogLevel = envLogLevels[currentEnv]; 29 | const minLogLevelPriority = levelPriority[minLogLevel]; 30 | 31 | function logMessage(level, message) { 32 | if (levelPriority[level] < minLogLevelPriority) { 33 | return; 34 | }; 35 | 36 | const logColor = levels[level]; 37 | const logDate = gray(`[${new Date().toLocaleDateString()} - ${new Date().toLocaleTimeString()}]`); 38 | const logLevel = `[${level.toUpperCase()}]`; 39 | 40 | const prefix = logColor(`${logDate} ${logLevel}`); 41 | 42 | if (level === "debug") { 43 | return console.debug(prefix, message); 44 | } else if (level === "info") { 45 | return console.info(prefix, message); 46 | } else if (level === "warn") { 47 | return console.warn(prefix, message); 48 | } else if (level === "error" || level === "fatal") { 49 | return console.error(prefix, message); 50 | } else if (level === "application") { 51 | return console.log(prefix, message); 52 | }; 53 | }; 54 | 55 | const logger = { 56 | debug: (message) => logMessage("debug", message), 57 | info: (message) => logMessage("info", message), 58 | warn: (message) => logMessage("warn", message), 59 | error: (message) => logMessage("error", message), 60 | fatal: (message) => logMessage("fatal", message), 61 | application: (message) => logMessage("application", message) 62 | }; 63 | 64 | module.exports = { logger }; -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/1-bug_report.yml: -------------------------------------------------------------------------------- 1 | name: "🐞 Bug Report" 2 | description: Report a bug or an unexpected behavior. 3 | assignees: 4 | - noowz 5 | labels: 6 | - bug 7 | title: "🐞 [Bug]: " 8 | body: 9 | - type: textarea 10 | id: reproduction_steps 11 | attributes: 12 | label: Reproduction steps 13 | description: "How do you trigger this bug? Please walk us through it step by step." 14 | value: | 15 | 1. 16 | 2. 17 | 3. 18 | ... 19 | validations: 20 | required: true 21 | - type: textarea 22 | id: actual_behavior 23 | attributes: 24 | label: Actual behavior 25 | description: What actually happens when you follow the reproduction steps? 26 | validations: 27 | required: true 28 | - type: textarea 29 | id: expected_behavior 30 | attributes: 31 | label: Expected behavior 32 | description: What should have happened instead? 33 | validations: 34 | required: true 35 | - type: textarea 36 | id: logs 37 | attributes: 38 | label: Logs 39 | description: Copy and paste any relevant log output. 40 | render: shell 41 | - type: textarea 42 | id: screenshots 43 | attributes: 44 | label: Screenshots 45 | description: Provide screenshots to help illustrate the issue. 46 | - type: dropdown 47 | id: platform 48 | attributes: 49 | label: Platform 50 | description: Which operating system are you using? 51 | options: 52 | - Windows 53 | - Linux 54 | - macOS 55 | validations: 56 | required: true 57 | - type: input 58 | id: project_version 59 | attributes: 60 | label: Project version 61 | description: Which version of the project are you using? 62 | placeholder: v1.0.0 63 | validations: 64 | required: true 65 | - type: input 66 | id: additional_comments 67 | attributes: 68 | label: Additional comments 69 | description: Any other information you would like to provide. -------------------------------------------------------------------------------- /src/utils/verifyConfig.js: -------------------------------------------------------------------------------- 1 | const { logger } = require("./logger.js"); 2 | 3 | const VALID_ENVIRONMENTS = [ 4 | "development", 5 | "production", 6 | "test" 7 | ]; 8 | 9 | const REQUIRED_CLIENT_ID = "839894528953810944"; 10 | 11 | const GAME = "Brawl Stars"; 12 | 13 | async function verifyConfig() { 14 | if (!process.env.NODE_ENV) { 15 | logger.error(`No development environment provided. Please update the 'NODE_ENV' field in the environment variable file to ${VALID_ENVIRONMENTS.map(env => `'${env}'`).join(", ")}.`); 16 | 17 | process.exit(1); 18 | } else if (!VALID_ENVIRONMENTS.includes(process.env.NODE_ENV.toLowerCase())) { 19 | logger.error(`The provided development environment is not recognized. Please update the 'NODE_ENV' field in the environment variable file to ${VALID_ENVIRONMENTS.map(env => `'${env}'`).join(", ")}.`); 20 | 21 | process.exit(1); 22 | }; 23 | 24 | if (!process.env.DISCORD_CLIENT_ID) { 25 | logger.error("No Discord Rich Presence client ID provided. Please update the 'DISCORD_CLIENT_ID' field in the environment variable file with your Discord Rich Presence client ID."); 26 | 27 | process.exit(1); 28 | } else if (!/^\d+$/.test(process.env.DISCORD_CLIENT_ID)) { 29 | logger.error("The provided Discord Rich Presence client ID is invalid. Ensure the 'DISCORD_CLIENT_ID' field in the environment variable file contains a valid numeric ID."); 30 | 31 | process.exit(1); 32 | } else if (process.env.DISCORD_CLIENT_ID !== REQUIRED_CLIENT_ID) { 33 | logger.error(`The provided Discord Rich Presence client ID does not match the required client ID. Update the 'DISCORD_CLIENT_ID' field in the environment variable file to '${REQUIRED_CLIENT_ID}'.`); 34 | 35 | process.exit(1); 36 | }; 37 | 38 | if (!process.env.BRAWL_STARS_API_KEY) { 39 | logger.error(`No ${GAME} API key provided. Please update the 'CLASH_OF_CLANS_API_KEY' field in the environment variable file with your ${GAME} API key.`); 40 | 41 | process.exit(1); 42 | } else if (typeof process.env.BRAWL_STARS_API_KEY !== "string") { 43 | logger.error(`The provided ${GAME} API key is invalid. Ensure the 'CLASH_OF_CLANS_API_KEY' field in the environment variable file contains a valid string.`); 44 | 45 | process.exit(1); 46 | }; 47 | 48 | if (!process.env.BRAWL_STARS_PLAYER_TAG) { 49 | logger.error(`No ${GAME} player tag provided. Please update the 'CLASH_OF_CLANS_PLAYER_TAG' field in the environment variable file with your ${GAME} player tag.`); 50 | 51 | process.exit(1); 52 | } else if (typeof process.env.BRAWL_STARS_PLAYER_TAG !== "string") { 53 | logger.error(`The provided ${GAME} player tag is invalid. Ensure the 'CLASH_OF_CLANS_PLAYER_TAG' field in the environment variable file contains a valid string.`); 54 | 55 | process.exit(1); 56 | }; 57 | }; 58 | 59 | module.exports = { verifyConfig }; -------------------------------------------------------------------------------- /.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 | # Snowpack dependency directory (https://snowpack.dev/) 45 | web_modules/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Optional stylelint cache 57 | .stylelintcache 58 | 59 | # Optional REPL history 60 | .node_repl_history 61 | 62 | # Output of 'npm pack' 63 | *.tgz 64 | 65 | # Yarn Integrity file 66 | .yarn-integrity 67 | 68 | # dotenv environment variable files 69 | .env 70 | .env.* 71 | !.env.example 72 | 73 | # parcel-bundler cache (https://parceljs.org/) 74 | .cache 75 | .parcel-cache 76 | 77 | # Next.js build output 78 | .next 79 | out 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 | # vuepress v2.x temp and cache directory 95 | .temp 96 | .cache 97 | 98 | # Sveltekit cache directory 99 | .svelte-kit/ 100 | 101 | # vitepress build output 102 | **/.vitepress/dist 103 | 104 | # vitepress cache directory 105 | **/.vitepress/cache 106 | 107 | # Docusaurus cache and generated files 108 | .docusaurus 109 | 110 | # Serverless directories 111 | .serverless/ 112 | 113 | # FuseBox cache 114 | .fusebox/ 115 | 116 | # DynamoDB Local files 117 | .dynamodb/ 118 | 119 | # Firebase cache directory 120 | .firebase/ 121 | 122 | # TernJS port file 123 | .tern-port 124 | 125 | # Stores VSCode versions used for testing VSCode extensions 126 | .vscode-test 127 | 128 | # yarn v3 129 | .pnp.* 130 | .yarn/* 131 | !.yarn/patches 132 | !.yarn/plugins 133 | !.yarn/releases 134 | !.yarn/sdks 135 | !.yarn/versions 136 | 137 | # Vite logs files 138 | vite.config.js.timestamp-* 139 | vite.config.ts.timestamp-* -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![brawl-stars-discord-rich-presence](https://socialify.git.ci/noowz/brawl-stars-discord-rich-presence/image?description=1&forks=1&issues=1&language=1&name=1&owner=1&pattern=Solid&pulls=1&stargazers=1&theme=Auto) 2 | 3 | --- 4 | 5 |

6 | About | 7 | Preview | 8 | Installation | 9 | How to use | 10 | Contribute | 11 | License | 12 | Disclaimer | 13 |

14 | 15 | --- 16 | 17 | ## **📙 About** 18 | 19 | **brawl-stars-discord-rich-presence** is a Discord Rich Presence that shows on your profile your Brawl Stars statistics. 20 | 21 | --- 22 | 23 | ## **🖼️ Preview** 24 | 25 | ![Discord Rich Presence](https://i.imgur.com/F7uSi9y.png) 26 | 27 | --- 28 | 29 | ## **⚒️ Installation** 30 | 31 | 1. Download [Node.js](https://nodejs.org/en/download). 32 | 2. Download [brawl-stars-discord-rich-presence](https://github.com/noowz/brawl-stars-discord-rich-presence/releases/latest). 33 | 34 | --- 35 | 36 | ## **🚀 How to use** 37 | 38 | 1. Open **Brawl Stars** and follow the steps to get your player tag: 39 | 40 | ![Brawl Stars Player Tag](https://i.imgur.com/F5OFwv8.gif) 41 | 42 | 2. Rename the `.env.example` file into `.env`. 43 | 3. Go to the `.env` file and replace **BRAWL_STARS_PLAYER_TAG** with your Brawl Stars player tag. 44 | 4. Go to the [Brawl Stars API Dashboard](https://developer.brawlstars.com) and create an account or log in to your account. 45 | 5. Create a [new API key](https://developer.brawlstars.com/#/new-key). You will need to allow your IP Address. To find out your IP Address, [click here](https://nordvpn.com/what-is-my-ip). 46 | 6. Go to the `.env` file and replace **BRAWL_STARS_API_KEY** with your API key. 47 | 7. Open the Terminal and go to the folder where you saved the files with the `cd` command. 48 | 8. Install all the required dependencies: 49 | 50 | ```cmd 51 | npm install 52 | ``` 53 | 54 | 9. Run the Rich Presence: 55 | 56 | ```cmd 57 | npm run start 58 | ``` 59 | 60 | > [!NOTE] 61 | > For the Rich Presence to work, you need to have Discord open in your computer. Also, make sure to turn on your Activity Status by going to **User Settings > Activity Privacy > Share my activity**. 62 | 63 | --- 64 | 65 | ## 🐛 **Contribute** 66 | 67 | If you found a bug or want to request a feature, browse the open [issues](https://github.com/noowz/brawl-stars-discord-rich-presence/issues) before opening a new one. 68 | 69 | If you know how to fix an [issue](https://github.com/noowz/brawl-stars-discord-rich-presence/issues), consider opening a [pull request](https://github.com/noowz/brawl-stars-discord-rich-presence/pulls) for it. 70 | 71 | --- 72 | 73 | ## 📝 **License** 74 | 75 | This project is licensed under the [MIT](./LICENSE) license. 76 | 77 | --- 78 | 79 | ## 📌 **Disclaimer** 80 | 81 | > This material is unofficial and is not endorsed by Supercell. For more information see Supercell's Fan Content Policy: [Supercell’s Fan Content Policy](https://supercell.com/fan-content-policy). 82 | -------------------------------------------------------------------------------- /src/rpc/rpc.js: -------------------------------------------------------------------------------- 1 | const { name, version, repository } = require("../../package.json"); 2 | const { apis } = require("../config.json"); 3 | const { logger } = require("../utils/logger"); 4 | const axios = require("axios"); 5 | const { app } = require("google-play-scraper"); 6 | 7 | let firstTimeRunningRichPresence = true; 8 | 9 | let startDate = firstTimeRunningRichPresence 10 | ? Date.now() 11 | : startDate; 12 | 13 | const rpc = async function setActivity(client) { 14 | let brawlAPINutellaResponseNull = false; 15 | 16 | const brawlstarsResponse = await axios({ 17 | method: "GET", 18 | url: `${apis.brawlstars.base_url}/v1/players/%23${process.env.BRAWL_STARS_PLAYER_TAG.replace("#", "")}`, 19 | headers: { 20 | Authorization: `Bearer ${process.env.BRAWL_STARS_API_KEY}`, 21 | "Content-Type": "application/json", 22 | "User-Agent": `${name}/${version}` 23 | } 24 | }).catch((error) => { 25 | logger.error(error); 26 | 27 | return; 28 | }); 29 | 30 | const brawlAPINutellaResponse = await axios({ 31 | method: "GET", 32 | url: `${apis.brawlAPINutella.base_url}/profile`, 33 | params: { 34 | tag: process.env.BRAWL_STARS_PLAYER_TAG.replace("#", "") 35 | }, 36 | headers: { 37 | "Content-Type": "application/json", 38 | "User-Agent": `${name}/${version}` 39 | }, 40 | }).catch((error) => { 41 | logger.error(error); 42 | 43 | return; 44 | }); 45 | 46 | if (!brawlAPINutellaResponseNull && brawlAPINutellaResponse.data.result === null) { 47 | brawlAPINutellaResponseNull = true; 48 | 49 | logger.warn("BrawlAPINutella returned an empty response. Ignoring BrawlAPINutella data."); 50 | }; 51 | 52 | const player = brawlAPINutellaResponseNull 53 | ? { 54 | ...brawlstarsResponse.data 55 | } 56 | : { 57 | ...brawlstarsResponse.data, 58 | ...brawlAPINutellaResponse.data.result 59 | }; 60 | 61 | const rankedRanks = [ 62 | "Bronze I", 63 | "Bronze II", 64 | "Bronze III", 65 | "Silver I", 66 | "Silver II", 67 | "Silver III", 68 | "Gold I", 69 | "Gold II", 70 | "Gold III", 71 | "Diamond I", 72 | "Diamond II", 73 | "Diamond III", 74 | "Mythic I", 75 | "Mythic II", 76 | "Mythic III", 77 | "Legendary I", 78 | "Legendary II", 79 | "Legendary III", 80 | "Masters I", 81 | "Masters II", 82 | "Masters III", 83 | "Pro" 84 | ]; 85 | 86 | const gameApp = await app({ 87 | appId: "com.supercell.brawlstars" 88 | }); 89 | 90 | client.request("SET_ACTIVITY", { 91 | pid: process.pid, 92 | activity: { 93 | details: brawlAPINutellaResponseNull 94 | ? `🏆 Trophies: ${player.trophies}/${player.highestTrophies}` 95 | : `🏆 Trophies: ${player.trophies}/${player.highestTrophies} • 🏅 Rank: ${rankedRanks[player.stats.find(stat => stat.id === 23).value - 1]}/${player.stats.find(stat => stat.id === 22).value === 0 ? rankedRanks[player.stats.find(stat => stat.id === 22).value] : rankedRanks[player.stats.find(stat => stat.id === 22).value - 1]} (${player.stats.find(stat => stat.id === 24).value}/${player.stats.find(stat => stat.id === 25).value})`, 96 | state: brawlAPINutellaResponseNull ? `🥊 3 vs 3 Victories: ${player["3vs3Victories"]} • 💀 Victories: ${player.soloVictories + player.duoVictories}` : `🥊 3 vs 3 Victories: ${player["3vs3Victories"]} • 💀 Victories: ${player.soloVictories + player.duoVictories} • 🔥 Max Win Streak: ${player.max_winstreak} • 👁️ Record Points: ${player.stats.find(stat => stat.id === 31).value} (Level ${player.stats.find(stat => stat.id === 32).value})`, 97 | timestamps: { 98 | start: startDate 99 | }, 100 | assets: { 101 | large_image: gameApp.icon, 102 | large_text: gameApp.title, 103 | small_image: `https://cdn.brawlify.com/profile-icons/regular/${player.icon.id}.png`, 104 | small_text: `${player.name} (${player.tag})` 105 | }, 106 | buttons: [ 107 | { 108 | label: "🚀 Download", 109 | url: repository.url 110 | } 111 | ] 112 | } 113 | }); 114 | }; 115 | 116 | firstTimeRunningRichPresence = false; 117 | 118 | module.exports = { rpc }; -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: 10 | dependencies: 11 | axios: 12 | specifier: ^1.13.2 13 | version: 1.13.2 14 | boxen: 15 | specifier: ^8.0.1 16 | version: 8.0.1 17 | chalk: 18 | specifier: 4.1.2 19 | version: 4.1.2 20 | discord-rpc: 21 | specifier: ^4.0.1 22 | version: 4.0.1 23 | dotenv: 24 | specifier: ^17.2.3 25 | version: 17.2.3 26 | google-play-scraper: 27 | specifier: 9.2.0 28 | version: 9.2.0 29 | 30 | packages: 31 | 32 | '@sindresorhus/is@4.6.0': 33 | resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} 34 | engines: {node: '>=10'} 35 | 36 | '@szmarczak/http-timer@4.0.6': 37 | resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==} 38 | engines: {node: '>=10'} 39 | 40 | '@types/cacheable-request@6.0.3': 41 | resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} 42 | 43 | '@types/http-cache-semantics@4.0.4': 44 | resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} 45 | 46 | '@types/keyv@3.1.4': 47 | resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} 48 | 49 | '@types/node@24.10.0': 50 | resolution: {integrity: sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A==} 51 | 52 | '@types/responselike@1.0.3': 53 | resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} 54 | 55 | ansi-align@3.0.1: 56 | resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} 57 | 58 | ansi-regex@5.0.1: 59 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 60 | engines: {node: '>=8'} 61 | 62 | ansi-regex@6.2.2: 63 | resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} 64 | engines: {node: '>=12'} 65 | 66 | ansi-styles@4.3.0: 67 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 68 | engines: {node: '>=8'} 69 | 70 | ansi-styles@6.2.3: 71 | resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} 72 | engines: {node: '>=12'} 73 | 74 | asynckit@0.4.0: 75 | resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} 76 | 77 | axios@1.13.2: 78 | resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==} 79 | 80 | bindings@1.5.0: 81 | resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} 82 | 83 | boolbase@1.0.0: 84 | resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} 85 | 86 | boxen@8.0.1: 87 | resolution: {integrity: sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==} 88 | engines: {node: '>=18'} 89 | 90 | cacheable-lookup@5.0.4: 91 | resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==} 92 | engines: {node: '>=10.6.0'} 93 | 94 | cacheable-request@7.0.4: 95 | resolution: {integrity: sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==} 96 | engines: {node: '>=8'} 97 | 98 | call-bind-apply-helpers@1.0.2: 99 | resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} 100 | engines: {node: '>= 0.4'} 101 | 102 | camelcase@8.0.0: 103 | resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} 104 | engines: {node: '>=16'} 105 | 106 | chalk@4.1.2: 107 | resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} 108 | engines: {node: '>=10'} 109 | 110 | chalk@5.6.2: 111 | resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} 112 | engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} 113 | 114 | cheerio-select@2.1.0: 115 | resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} 116 | 117 | cheerio@1.1.2: 118 | resolution: {integrity: sha512-IkxPpb5rS/d1IiLbHMgfPuS0FgiWTtFIm/Nj+2woXDLTZ7fOT2eqzgYbdMlLweqlHbsZjxEChoVK+7iph7jyQg==} 119 | engines: {node: '>=20.18.1'} 120 | 121 | cli-boxes@3.0.0: 122 | resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} 123 | engines: {node: '>=10'} 124 | 125 | clone-response@1.0.3: 126 | resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==} 127 | 128 | color-convert@2.0.1: 129 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 130 | engines: {node: '>=7.0.0'} 131 | 132 | color-name@1.1.4: 133 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 134 | 135 | combined-stream@1.0.8: 136 | resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} 137 | engines: {node: '>= 0.8'} 138 | 139 | css-select@5.2.2: 140 | resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} 141 | 142 | css-what@6.2.2: 143 | resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} 144 | engines: {node: '>= 6'} 145 | 146 | d@1.0.2: 147 | resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==} 148 | engines: {node: '>=0.12'} 149 | 150 | debug@3.2.7: 151 | resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} 152 | peerDependencies: 153 | supports-color: '*' 154 | peerDependenciesMeta: 155 | supports-color: 156 | optional: true 157 | 158 | decompress-response@6.0.0: 159 | resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} 160 | engines: {node: '>=10'} 161 | 162 | defer-to-connect@2.0.1: 163 | resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} 164 | engines: {node: '>=10'} 165 | 166 | delayed-stream@1.0.0: 167 | resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} 168 | engines: {node: '>=0.4.0'} 169 | 170 | discord-rpc@4.0.1: 171 | resolution: {integrity: sha512-HOvHpbq5STRZJjQIBzwoKnQ0jHplbEWFWlPDwXXKm/bILh4nzjcg7mNqll0UY7RsjFoaXA7e/oYb/4lvpda2zA==} 172 | 173 | dom-serializer@2.0.0: 174 | resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} 175 | 176 | domelementtype@2.3.0: 177 | resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} 178 | 179 | domhandler@5.0.3: 180 | resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} 181 | engines: {node: '>= 4'} 182 | 183 | domutils@3.2.2: 184 | resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} 185 | 186 | dotenv@17.2.3: 187 | resolution: {integrity: sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==} 188 | engines: {node: '>=12'} 189 | 190 | dunder-proto@1.0.1: 191 | resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} 192 | engines: {node: '>= 0.4'} 193 | 194 | emoji-regex@10.6.0: 195 | resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} 196 | 197 | emoji-regex@8.0.0: 198 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} 199 | 200 | encoding-sniffer@0.2.1: 201 | resolution: {integrity: sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==} 202 | 203 | end-of-stream@1.4.5: 204 | resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} 205 | 206 | entities@4.5.0: 207 | resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} 208 | engines: {node: '>=0.12'} 209 | 210 | entities@6.0.1: 211 | resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} 212 | engines: {node: '>=0.12'} 213 | 214 | es-define-property@1.0.1: 215 | resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} 216 | engines: {node: '>= 0.4'} 217 | 218 | es-errors@1.3.0: 219 | resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} 220 | engines: {node: '>= 0.4'} 221 | 222 | es-object-atoms@1.1.1: 223 | resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} 224 | engines: {node: '>= 0.4'} 225 | 226 | es-set-tostringtag@2.1.0: 227 | resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} 228 | engines: {node: '>= 0.4'} 229 | 230 | es5-ext@0.10.64: 231 | resolution: {integrity: sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==} 232 | engines: {node: '>=0.10'} 233 | 234 | es6-iterator@2.0.3: 235 | resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==} 236 | 237 | es6-symbol@3.1.4: 238 | resolution: {integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==} 239 | engines: {node: '>=0.12'} 240 | 241 | es6-weak-map@2.0.3: 242 | resolution: {integrity: sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==} 243 | 244 | esniff@2.0.1: 245 | resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==} 246 | engines: {node: '>=0.10'} 247 | 248 | event-emitter@0.3.5: 249 | resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==} 250 | 251 | ext@1.7.0: 252 | resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} 253 | 254 | file-uri-to-path@1.0.0: 255 | resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} 256 | 257 | follow-redirects@1.15.11: 258 | resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} 259 | engines: {node: '>=4.0'} 260 | peerDependencies: 261 | debug: '*' 262 | peerDependenciesMeta: 263 | debug: 264 | optional: true 265 | 266 | form-data@4.0.4: 267 | resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==} 268 | engines: {node: '>= 6'} 269 | 270 | function-bind@1.1.2: 271 | resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} 272 | 273 | get-east-asian-width@1.4.0: 274 | resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==} 275 | engines: {node: '>=18'} 276 | 277 | get-intrinsic@1.3.0: 278 | resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} 279 | engines: {node: '>= 0.4'} 280 | 281 | get-proto@1.0.1: 282 | resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} 283 | engines: {node: '>= 0.4'} 284 | 285 | get-stream@5.2.0: 286 | resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} 287 | engines: {node: '>=8'} 288 | 289 | google-play-scraper@9.2.0: 290 | resolution: {integrity: sha512-LpXaaSxwmWBqvmfYVIXCkD97BLAmWhxP9QBriVwtz7ypgCizKv01HKLbmhFcUpjPpET1WQZekoYi4gxmDg0cXw==} 291 | 292 | gopd@1.2.0: 293 | resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} 294 | engines: {node: '>= 0.4'} 295 | 296 | got@11.8.6: 297 | resolution: {integrity: sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==} 298 | engines: {node: '>=10.19.0'} 299 | 300 | has-flag@4.0.0: 301 | resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 302 | engines: {node: '>=8'} 303 | 304 | has-symbols@1.1.0: 305 | resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} 306 | engines: {node: '>= 0.4'} 307 | 308 | has-tostringtag@1.0.2: 309 | resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} 310 | engines: {node: '>= 0.4'} 311 | 312 | hasown@2.0.2: 313 | resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} 314 | engines: {node: '>= 0.4'} 315 | 316 | htmlparser2@10.0.0: 317 | resolution: {integrity: sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==} 318 | 319 | http-cache-semantics@4.2.0: 320 | resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==} 321 | 322 | http2-wrapper@1.0.3: 323 | resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==} 324 | engines: {node: '>=10.19.0'} 325 | 326 | iconv-lite@0.6.3: 327 | resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} 328 | engines: {node: '>=0.10.0'} 329 | 330 | is-fullwidth-code-point@3.0.0: 331 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} 332 | engines: {node: '>=8'} 333 | 334 | is-promise@2.2.2: 335 | resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} 336 | 337 | json-buffer@3.0.1: 338 | resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} 339 | 340 | keyv@4.5.4: 341 | resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} 342 | 343 | lowercase-keys@2.0.0: 344 | resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} 345 | engines: {node: '>=8'} 346 | 347 | lru-queue@0.1.0: 348 | resolution: {integrity: sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==} 349 | 350 | math-intrinsics@1.1.0: 351 | resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} 352 | engines: {node: '>= 0.4'} 353 | 354 | memoizee@0.4.17: 355 | resolution: {integrity: sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==} 356 | engines: {node: '>=0.12'} 357 | 358 | mime-db@1.52.0: 359 | resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} 360 | engines: {node: '>= 0.6'} 361 | 362 | mime-types@2.1.35: 363 | resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} 364 | engines: {node: '>= 0.6'} 365 | 366 | mimic-response@1.0.1: 367 | resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} 368 | engines: {node: '>=4'} 369 | 370 | mimic-response@3.1.0: 371 | resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} 372 | engines: {node: '>=10'} 373 | 374 | ms@2.1.3: 375 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 376 | 377 | next-tick@1.1.0: 378 | resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} 379 | 380 | node-addon-api@1.7.2: 381 | resolution: {integrity: sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==} 382 | 383 | node-fetch@2.7.0: 384 | resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} 385 | engines: {node: 4.x || >=6.0.0} 386 | peerDependencies: 387 | encoding: ^0.1.0 388 | peerDependenciesMeta: 389 | encoding: 390 | optional: true 391 | 392 | normalize-url@6.1.0: 393 | resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} 394 | engines: {node: '>=10'} 395 | 396 | nth-check@2.1.1: 397 | resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} 398 | 399 | once@1.4.0: 400 | resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} 401 | 402 | p-cancelable@2.1.1: 403 | resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} 404 | engines: {node: '>=8'} 405 | 406 | parse5-htmlparser2-tree-adapter@7.1.0: 407 | resolution: {integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==} 408 | 409 | parse5-parser-stream@7.1.2: 410 | resolution: {integrity: sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==} 411 | 412 | parse5@7.3.0: 413 | resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} 414 | 415 | proxy-from-env@1.1.0: 416 | resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} 417 | 418 | pump@3.0.3: 419 | resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==} 420 | 421 | quick-lru@5.1.1: 422 | resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} 423 | engines: {node: '>=10'} 424 | 425 | ramda@0.21.0: 426 | resolution: {integrity: sha512-HGd5aczYKQXGILB+abY290V7Xz62eFajpa6AtMdwEmQSakJmgSO7ks4eI3HdR34j+X2Vz4Thp9VAJbrCAMbO2w==} 427 | 428 | register-scheme@https://codeload.github.com/devsnek/node-register-scheme/tar.gz/e7cc9a63a1f512565da44cb57316d9fb10750e17: 429 | resolution: {tarball: https://codeload.github.com/devsnek/node-register-scheme/tar.gz/e7cc9a63a1f512565da44cb57316d9fb10750e17} 430 | version: 0.0.2 431 | 432 | resolve-alpn@1.2.1: 433 | resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} 434 | 435 | responselike@2.0.1: 436 | resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} 437 | 438 | safer-buffer@2.1.2: 439 | resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} 440 | 441 | string-width@4.2.3: 442 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} 443 | engines: {node: '>=8'} 444 | 445 | string-width@7.2.0: 446 | resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} 447 | engines: {node: '>=18'} 448 | 449 | strip-ansi@6.0.1: 450 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 451 | engines: {node: '>=8'} 452 | 453 | strip-ansi@7.1.2: 454 | resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} 455 | engines: {node: '>=12'} 456 | 457 | supports-color@7.2.0: 458 | resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} 459 | engines: {node: '>=8'} 460 | 461 | timers-ext@0.1.8: 462 | resolution: {integrity: sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==} 463 | engines: {node: '>=0.12'} 464 | 465 | tr46@0.0.3: 466 | resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} 467 | 468 | type-fest@4.41.0: 469 | resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} 470 | engines: {node: '>=16'} 471 | 472 | type@2.7.3: 473 | resolution: {integrity: sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==} 474 | 475 | undici-types@7.16.0: 476 | resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} 477 | 478 | undici@7.16.0: 479 | resolution: {integrity: sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==} 480 | engines: {node: '>=20.18.1'} 481 | 482 | webidl-conversions@3.0.1: 483 | resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} 484 | 485 | whatwg-encoding@3.1.1: 486 | resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} 487 | engines: {node: '>=18'} 488 | 489 | whatwg-mimetype@4.0.0: 490 | resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} 491 | engines: {node: '>=18'} 492 | 493 | whatwg-url@5.0.0: 494 | resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} 495 | 496 | widest-line@5.0.0: 497 | resolution: {integrity: sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==} 498 | engines: {node: '>=18'} 499 | 500 | wrap-ansi@9.0.2: 501 | resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} 502 | engines: {node: '>=18'} 503 | 504 | wrappy@1.0.2: 505 | resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} 506 | 507 | ws@7.5.10: 508 | resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} 509 | engines: {node: '>=8.3.0'} 510 | peerDependencies: 511 | bufferutil: ^4.0.1 512 | utf-8-validate: ^5.0.2 513 | peerDependenciesMeta: 514 | bufferutil: 515 | optional: true 516 | utf-8-validate: 517 | optional: true 518 | 519 | snapshots: 520 | 521 | '@sindresorhus/is@4.6.0': {} 522 | 523 | '@szmarczak/http-timer@4.0.6': 524 | dependencies: 525 | defer-to-connect: 2.0.1 526 | 527 | '@types/cacheable-request@6.0.3': 528 | dependencies: 529 | '@types/http-cache-semantics': 4.0.4 530 | '@types/keyv': 3.1.4 531 | '@types/node': 24.10.0 532 | '@types/responselike': 1.0.3 533 | 534 | '@types/http-cache-semantics@4.0.4': {} 535 | 536 | '@types/keyv@3.1.4': 537 | dependencies: 538 | '@types/node': 24.10.0 539 | 540 | '@types/node@24.10.0': 541 | dependencies: 542 | undici-types: 7.16.0 543 | 544 | '@types/responselike@1.0.3': 545 | dependencies: 546 | '@types/node': 24.10.0 547 | 548 | ansi-align@3.0.1: 549 | dependencies: 550 | string-width: 4.2.3 551 | 552 | ansi-regex@5.0.1: {} 553 | 554 | ansi-regex@6.2.2: {} 555 | 556 | ansi-styles@4.3.0: 557 | dependencies: 558 | color-convert: 2.0.1 559 | 560 | ansi-styles@6.2.3: {} 561 | 562 | asynckit@0.4.0: {} 563 | 564 | axios@1.13.2: 565 | dependencies: 566 | follow-redirects: 1.15.11 567 | form-data: 4.0.4 568 | proxy-from-env: 1.1.0 569 | transitivePeerDependencies: 570 | - debug 571 | 572 | bindings@1.5.0: 573 | dependencies: 574 | file-uri-to-path: 1.0.0 575 | optional: true 576 | 577 | boolbase@1.0.0: {} 578 | 579 | boxen@8.0.1: 580 | dependencies: 581 | ansi-align: 3.0.1 582 | camelcase: 8.0.0 583 | chalk: 5.6.2 584 | cli-boxes: 3.0.0 585 | string-width: 7.2.0 586 | type-fest: 4.41.0 587 | widest-line: 5.0.0 588 | wrap-ansi: 9.0.2 589 | 590 | cacheable-lookup@5.0.4: {} 591 | 592 | cacheable-request@7.0.4: 593 | dependencies: 594 | clone-response: 1.0.3 595 | get-stream: 5.2.0 596 | http-cache-semantics: 4.2.0 597 | keyv: 4.5.4 598 | lowercase-keys: 2.0.0 599 | normalize-url: 6.1.0 600 | responselike: 2.0.1 601 | 602 | call-bind-apply-helpers@1.0.2: 603 | dependencies: 604 | es-errors: 1.3.0 605 | function-bind: 1.1.2 606 | 607 | camelcase@8.0.0: {} 608 | 609 | chalk@4.1.2: 610 | dependencies: 611 | ansi-styles: 4.3.0 612 | supports-color: 7.2.0 613 | 614 | chalk@5.6.2: {} 615 | 616 | cheerio-select@2.1.0: 617 | dependencies: 618 | boolbase: 1.0.0 619 | css-select: 5.2.2 620 | css-what: 6.2.2 621 | domelementtype: 2.3.0 622 | domhandler: 5.0.3 623 | domutils: 3.2.2 624 | 625 | cheerio@1.1.2: 626 | dependencies: 627 | cheerio-select: 2.1.0 628 | dom-serializer: 2.0.0 629 | domhandler: 5.0.3 630 | domutils: 3.2.2 631 | encoding-sniffer: 0.2.1 632 | htmlparser2: 10.0.0 633 | parse5: 7.3.0 634 | parse5-htmlparser2-tree-adapter: 7.1.0 635 | parse5-parser-stream: 7.1.2 636 | undici: 7.16.0 637 | whatwg-mimetype: 4.0.0 638 | 639 | cli-boxes@3.0.0: {} 640 | 641 | clone-response@1.0.3: 642 | dependencies: 643 | mimic-response: 1.0.1 644 | 645 | color-convert@2.0.1: 646 | dependencies: 647 | color-name: 1.1.4 648 | 649 | color-name@1.1.4: {} 650 | 651 | combined-stream@1.0.8: 652 | dependencies: 653 | delayed-stream: 1.0.0 654 | 655 | css-select@5.2.2: 656 | dependencies: 657 | boolbase: 1.0.0 658 | css-what: 6.2.2 659 | domhandler: 5.0.3 660 | domutils: 3.2.2 661 | nth-check: 2.1.1 662 | 663 | css-what@6.2.2: {} 664 | 665 | d@1.0.2: 666 | dependencies: 667 | es5-ext: 0.10.64 668 | type: 2.7.3 669 | 670 | debug@3.2.7: 671 | dependencies: 672 | ms: 2.1.3 673 | 674 | decompress-response@6.0.0: 675 | dependencies: 676 | mimic-response: 3.1.0 677 | 678 | defer-to-connect@2.0.1: {} 679 | 680 | delayed-stream@1.0.0: {} 681 | 682 | discord-rpc@4.0.1: 683 | dependencies: 684 | node-fetch: 2.7.0 685 | ws: 7.5.10 686 | optionalDependencies: 687 | register-scheme: https://codeload.github.com/devsnek/node-register-scheme/tar.gz/e7cc9a63a1f512565da44cb57316d9fb10750e17 688 | transitivePeerDependencies: 689 | - bufferutil 690 | - encoding 691 | - utf-8-validate 692 | 693 | dom-serializer@2.0.0: 694 | dependencies: 695 | domelementtype: 2.3.0 696 | domhandler: 5.0.3 697 | entities: 4.5.0 698 | 699 | domelementtype@2.3.0: {} 700 | 701 | domhandler@5.0.3: 702 | dependencies: 703 | domelementtype: 2.3.0 704 | 705 | domutils@3.2.2: 706 | dependencies: 707 | dom-serializer: 2.0.0 708 | domelementtype: 2.3.0 709 | domhandler: 5.0.3 710 | 711 | dotenv@17.2.3: {} 712 | 713 | dunder-proto@1.0.1: 714 | dependencies: 715 | call-bind-apply-helpers: 1.0.2 716 | es-errors: 1.3.0 717 | gopd: 1.2.0 718 | 719 | emoji-regex@10.6.0: {} 720 | 721 | emoji-regex@8.0.0: {} 722 | 723 | encoding-sniffer@0.2.1: 724 | dependencies: 725 | iconv-lite: 0.6.3 726 | whatwg-encoding: 3.1.1 727 | 728 | end-of-stream@1.4.5: 729 | dependencies: 730 | once: 1.4.0 731 | 732 | entities@4.5.0: {} 733 | 734 | entities@6.0.1: {} 735 | 736 | es-define-property@1.0.1: {} 737 | 738 | es-errors@1.3.0: {} 739 | 740 | es-object-atoms@1.1.1: 741 | dependencies: 742 | es-errors: 1.3.0 743 | 744 | es-set-tostringtag@2.1.0: 745 | dependencies: 746 | es-errors: 1.3.0 747 | get-intrinsic: 1.3.0 748 | has-tostringtag: 1.0.2 749 | hasown: 2.0.2 750 | 751 | es5-ext@0.10.64: 752 | dependencies: 753 | es6-iterator: 2.0.3 754 | es6-symbol: 3.1.4 755 | esniff: 2.0.1 756 | next-tick: 1.1.0 757 | 758 | es6-iterator@2.0.3: 759 | dependencies: 760 | d: 1.0.2 761 | es5-ext: 0.10.64 762 | es6-symbol: 3.1.4 763 | 764 | es6-symbol@3.1.4: 765 | dependencies: 766 | d: 1.0.2 767 | ext: 1.7.0 768 | 769 | es6-weak-map@2.0.3: 770 | dependencies: 771 | d: 1.0.2 772 | es5-ext: 0.10.64 773 | es6-iterator: 2.0.3 774 | es6-symbol: 3.1.4 775 | 776 | esniff@2.0.1: 777 | dependencies: 778 | d: 1.0.2 779 | es5-ext: 0.10.64 780 | event-emitter: 0.3.5 781 | type: 2.7.3 782 | 783 | event-emitter@0.3.5: 784 | dependencies: 785 | d: 1.0.2 786 | es5-ext: 0.10.64 787 | 788 | ext@1.7.0: 789 | dependencies: 790 | type: 2.7.3 791 | 792 | file-uri-to-path@1.0.0: 793 | optional: true 794 | 795 | follow-redirects@1.15.11: {} 796 | 797 | form-data@4.0.4: 798 | dependencies: 799 | asynckit: 0.4.0 800 | combined-stream: 1.0.8 801 | es-set-tostringtag: 2.1.0 802 | hasown: 2.0.2 803 | mime-types: 2.1.35 804 | 805 | function-bind@1.1.2: {} 806 | 807 | get-east-asian-width@1.4.0: {} 808 | 809 | get-intrinsic@1.3.0: 810 | dependencies: 811 | call-bind-apply-helpers: 1.0.2 812 | es-define-property: 1.0.1 813 | es-errors: 1.3.0 814 | es-object-atoms: 1.1.1 815 | function-bind: 1.1.2 816 | get-proto: 1.0.1 817 | gopd: 1.2.0 818 | has-symbols: 1.1.0 819 | hasown: 2.0.2 820 | math-intrinsics: 1.1.0 821 | 822 | get-proto@1.0.1: 823 | dependencies: 824 | dunder-proto: 1.0.1 825 | es-object-atoms: 1.1.1 826 | 827 | get-stream@5.2.0: 828 | dependencies: 829 | pump: 3.0.3 830 | 831 | google-play-scraper@9.2.0: 832 | dependencies: 833 | cheerio: 1.1.2 834 | debug: 3.2.7 835 | got: 11.8.6 836 | memoizee: 0.4.17 837 | ramda: 0.21.0 838 | transitivePeerDependencies: 839 | - supports-color 840 | 841 | gopd@1.2.0: {} 842 | 843 | got@11.8.6: 844 | dependencies: 845 | '@sindresorhus/is': 4.6.0 846 | '@szmarczak/http-timer': 4.0.6 847 | '@types/cacheable-request': 6.0.3 848 | '@types/responselike': 1.0.3 849 | cacheable-lookup: 5.0.4 850 | cacheable-request: 7.0.4 851 | decompress-response: 6.0.0 852 | http2-wrapper: 1.0.3 853 | lowercase-keys: 2.0.0 854 | p-cancelable: 2.1.1 855 | responselike: 2.0.1 856 | 857 | has-flag@4.0.0: {} 858 | 859 | has-symbols@1.1.0: {} 860 | 861 | has-tostringtag@1.0.2: 862 | dependencies: 863 | has-symbols: 1.1.0 864 | 865 | hasown@2.0.2: 866 | dependencies: 867 | function-bind: 1.1.2 868 | 869 | htmlparser2@10.0.0: 870 | dependencies: 871 | domelementtype: 2.3.0 872 | domhandler: 5.0.3 873 | domutils: 3.2.2 874 | entities: 6.0.1 875 | 876 | http-cache-semantics@4.2.0: {} 877 | 878 | http2-wrapper@1.0.3: 879 | dependencies: 880 | quick-lru: 5.1.1 881 | resolve-alpn: 1.2.1 882 | 883 | iconv-lite@0.6.3: 884 | dependencies: 885 | safer-buffer: 2.1.2 886 | 887 | is-fullwidth-code-point@3.0.0: {} 888 | 889 | is-promise@2.2.2: {} 890 | 891 | json-buffer@3.0.1: {} 892 | 893 | keyv@4.5.4: 894 | dependencies: 895 | json-buffer: 3.0.1 896 | 897 | lowercase-keys@2.0.0: {} 898 | 899 | lru-queue@0.1.0: 900 | dependencies: 901 | es5-ext: 0.10.64 902 | 903 | math-intrinsics@1.1.0: {} 904 | 905 | memoizee@0.4.17: 906 | dependencies: 907 | d: 1.0.2 908 | es5-ext: 0.10.64 909 | es6-weak-map: 2.0.3 910 | event-emitter: 0.3.5 911 | is-promise: 2.2.2 912 | lru-queue: 0.1.0 913 | next-tick: 1.1.0 914 | timers-ext: 0.1.8 915 | 916 | mime-db@1.52.0: {} 917 | 918 | mime-types@2.1.35: 919 | dependencies: 920 | mime-db: 1.52.0 921 | 922 | mimic-response@1.0.1: {} 923 | 924 | mimic-response@3.1.0: {} 925 | 926 | ms@2.1.3: {} 927 | 928 | next-tick@1.1.0: {} 929 | 930 | node-addon-api@1.7.2: 931 | optional: true 932 | 933 | node-fetch@2.7.0: 934 | dependencies: 935 | whatwg-url: 5.0.0 936 | 937 | normalize-url@6.1.0: {} 938 | 939 | nth-check@2.1.1: 940 | dependencies: 941 | boolbase: 1.0.0 942 | 943 | once@1.4.0: 944 | dependencies: 945 | wrappy: 1.0.2 946 | 947 | p-cancelable@2.1.1: {} 948 | 949 | parse5-htmlparser2-tree-adapter@7.1.0: 950 | dependencies: 951 | domhandler: 5.0.3 952 | parse5: 7.3.0 953 | 954 | parse5-parser-stream@7.1.2: 955 | dependencies: 956 | parse5: 7.3.0 957 | 958 | parse5@7.3.0: 959 | dependencies: 960 | entities: 6.0.1 961 | 962 | proxy-from-env@1.1.0: {} 963 | 964 | pump@3.0.3: 965 | dependencies: 966 | end-of-stream: 1.4.5 967 | once: 1.4.0 968 | 969 | quick-lru@5.1.1: {} 970 | 971 | ramda@0.21.0: {} 972 | 973 | register-scheme@https://codeload.github.com/devsnek/node-register-scheme/tar.gz/e7cc9a63a1f512565da44cb57316d9fb10750e17: 974 | dependencies: 975 | bindings: 1.5.0 976 | node-addon-api: 1.7.2 977 | optional: true 978 | 979 | resolve-alpn@1.2.1: {} 980 | 981 | responselike@2.0.1: 982 | dependencies: 983 | lowercase-keys: 2.0.0 984 | 985 | safer-buffer@2.1.2: {} 986 | 987 | string-width@4.2.3: 988 | dependencies: 989 | emoji-regex: 8.0.0 990 | is-fullwidth-code-point: 3.0.0 991 | strip-ansi: 6.0.1 992 | 993 | string-width@7.2.0: 994 | dependencies: 995 | emoji-regex: 10.6.0 996 | get-east-asian-width: 1.4.0 997 | strip-ansi: 7.1.2 998 | 999 | strip-ansi@6.0.1: 1000 | dependencies: 1001 | ansi-regex: 5.0.1 1002 | 1003 | strip-ansi@7.1.2: 1004 | dependencies: 1005 | ansi-regex: 6.2.2 1006 | 1007 | supports-color@7.2.0: 1008 | dependencies: 1009 | has-flag: 4.0.0 1010 | 1011 | timers-ext@0.1.8: 1012 | dependencies: 1013 | es5-ext: 0.10.64 1014 | next-tick: 1.1.0 1015 | 1016 | tr46@0.0.3: {} 1017 | 1018 | type-fest@4.41.0: {} 1019 | 1020 | type@2.7.3: {} 1021 | 1022 | undici-types@7.16.0: {} 1023 | 1024 | undici@7.16.0: {} 1025 | 1026 | webidl-conversions@3.0.1: {} 1027 | 1028 | whatwg-encoding@3.1.1: 1029 | dependencies: 1030 | iconv-lite: 0.6.3 1031 | 1032 | whatwg-mimetype@4.0.0: {} 1033 | 1034 | whatwg-url@5.0.0: 1035 | dependencies: 1036 | tr46: 0.0.3 1037 | webidl-conversions: 3.0.1 1038 | 1039 | widest-line@5.0.0: 1040 | dependencies: 1041 | string-width: 7.2.0 1042 | 1043 | wrap-ansi@9.0.2: 1044 | dependencies: 1045 | ansi-styles: 6.2.3 1046 | string-width: 7.2.0 1047 | strip-ansi: 7.1.2 1048 | 1049 | wrappy@1.0.2: {} 1050 | 1051 | ws@7.5.10: {} 1052 | --------------------------------------------------------------------------------