Skip to content

SkinPeek Admin Guide

Giorgio edited this page Jun 4, 2024 · 13 revisions

This is a more-or-less complete overview of all the tricks, features and useful info for hosting the bot.

Which VPS should I use?

If you want the bot to run 24/7, you might want to host it on a VPS. But which one?

The truth is that the bot is quite optimised, so it doesn't use many resources if it's not used by many people. As a rule of thumb, it only needs ~30MB of RAM to start up, and then about ~125MB for every 1k servers it's in. That means that you can't really go wrong with any VPS. It comes down to which hosting company you trust the most, and has the most features.

As to which VPS provider you should use, here is the list of recommendations from both the discord.js and discord.py servers:

Discord.js - List of affordable hosting providers:
OVH Starting at $3.35/mo for 1 core, 2GB RAM, 20GB SSD
DigitalOcean Starting at $5/mo for 1 core, 1GB RAM, 25GB SSD
Linode Starting at $5/mo for 1 core, 1GB RAM, 25GB SSD
Vultr Starting at $2.50/mo for 1 core, 512MB RAM, 10GB SSD
AWS Lightsail Starting at $3.50/mo (first month free) for 1 core, 512MB RAM, 20GB SSD
Time4VPS Starting at €3.99/month for 1 core, 2GB RAM, 20GB SSD
VIRMACH Full Windows and Linux Desktop VPS starting at $7/mo and $1/mo respectively
Netcup Starting at €2.62/mo for 1 core, 2GB RAM, 20GB SSD
GitHub education Free credit and other offers for students
Microsoft students Free credit for students
Google Cloud free tier

Discord.py - Need to run your bot 24/7? Get a cheap VPS.
https://www.scaleway.com/ EU
https://www.time4vps.eu/ Lithuania.
https://www.digitalocean.com/ US
https://www.vultr.com/ US
https://www.ovh.co.uk/ EU/Canada
https://www.hetzner.com/ Germany/US
• Self-hosting: Any computer.
• Kinda free: GCP, AWS have one year free micros.

Admin commands

You can use these admin commands to manage the bot from any discord channel.

You should first set the ownerId in config.json to your discord ID, otherwise anyone can use these commands.
ownerId can be the ID of:

  • a user
  • a role (everyone with that role)
  • a guild (any message in that guild)

You can also put multiple IDs separated by a comma if you want multiple admins, for example: 123456789,987654321.
Note: Your user ID looks something like 316978243716775947. It is not your @username. Look it up if you're confused.

Admin commands are used by sending a message that starts with @bot !, for example @bot !config, in any channel that the bot can see. With Discord recently changing message content to become a privileged intent, the bot can only receive messages that it is tagged in. So even if you enabled "message content" in the dev panel, you will need to @mention your bot before every admin command.

Here is the list of admin commands:

  • !deploy: refresh/update the bot's list of commands on Discord. The bot should do this automatically, but if the command list is corrupted somehow, you can do it just in case. This is used to tell Discord what slash commands the bot has. You can either deploy to just one guild or to all guilds with !deploy guild and !deploy global.

  • !undeploy: remove all slash commands from the bot. You'll need to deploy again if you want to use the bot. Useful if you deployed both in a guild and globally, and you see every command twice.

  • !config [name] [value]: change an option in config.json. Most configs will change immediately, but config.json won't be saved and any scheduled cron tasks won't be rescheduled until you do !config reload.

  • !config reload: see above.

  • !config load: If you manually changed config.json, use this to read the config from disk again. Also useful if you changed some values with !config by mistake and want to undo your changes.

  • !config read: Reads and sends you the contents of config.json on discord.

  • !message [message]: (not recommended) send a message to all guilds the bot is in.

For each guild, the bot will look for the channel with the most alerts. If a guild has no alerts set up, it will not send a message there, since they're probably not using the bot. I don't recommend you use this, especially if the bot is in many servers. The bot will lock up while it goes through everyone's alerts and sends a message to all the guilds. Doesn't work with sharding enabled.

  • !status [status]: change the bot's status in /info.
  • !forcealerts: manually trigger checking for everyone's alerts. Useful if you disabled automatic checking, or the bot wasn't on at midnight UTC.
  • !stop skinpeek: immediately stop and shut down the bot.
  • !update: auto-update the bot to the latest version. Only works if you set it up correctly, read more about it below.

Auto updating the bot using !update

This is useful to be able to update the bot with a simple command, although it requires you to have cloned the repo using git.

First, download and install git. On Windows, it's here.

Then, open a command line in a new folder, and type the following command:

git clone https://github.com/giorgi-o/SkinPeek

It should automatically download the bot into a new folder. Transfer the config.json and data folders from where the bot used to be.

To launch the bot, either use the SkinPeek.sh/SkinPeek.bat scripts or (recommended) use pm2. This is to ensure that when the bot stops, it's automatically restarted.

Then you should be able to use !update just like any other admin command.

Note that due to how git works, if you change any of the bot's code, git will refuse to update the bot.

Which files should I keep when transferring/updating the bot?

When transferring the bot to a new version or to a different PC/VPS, these are the files you might want to copy over:

  • config.json: the bot's config
  • data/users folder: all user data, cookies, alerts, settings, etc.
  • data/stats.json: shop stats i.e. how many times each weapon appeared in the shop in the past 14 days. Can keep it for /stats command, but entirely optional.
  • data/shopCache folder: contains everyone's shop for today, no need to keep it.
  • data/skins.json: skin data (names, images prices...). No need to keep it, it will be redownloaded if it's not there (or if there's a val update).

config.json

As you might have noticed. config.json has many other fields than just the bot token. Here's what each of them does.

Cron syntax

First, I need to explain cron syntax.

Cron comes from Unix-like OSs (Linux, Mac & others). It's a way of making a task repeat regularly. So for example, if you wanted to do something every day at 2:15PM, or every 45 minutes, or every 3 hours but only on the 5th day of the month, you would use cron. Cron syntax is a simple way of describing when/how often you want your task to run.

The bot uses cron for anything it needs to do repeatly, for example:

  • check for alerts (every day 10 seconds after midnight UTC)
  • check for valorant updates (every 15mins)
  • update the user-agent to bypass Cloudflare firewall (every 15mins)
  • send the bot logs to a discord text channel (every 10s)
  • and anything else I may add later on.

If you want to change when/how often these happen, you should understand how cron syntax works.

There are many cron tutorials online, so I won't write another one here. Although you can probably just google cron every day at 2PM and use that. Then, use crontab.guru to double-check your expressions.

Now for the tricky bit. The bot uses node-cron to schedule the tasks. Any cron expression will work as intended, but it's got another trick up it's sleeve: seconds. With normal cron, you can only specify minutes. Node-cron lets you add an extra part at the front to specify seconds as well.

If a cron expression has 5 "parts", it's a normal cron expression. If it has 6 parts, it's a node-cron expression, and the first part is seconds, the second is minutes, etc. I'm pointing this out because if you paste any of the cron expressions in the default config.json into crontab.guru, it won't work because that website doesn't understand seconds.

To recap: any normal cron expression will work fine, but doesn't support seconds. If you want to use seconds, check out the node-cron documentation.

The option list

  • fetchSkinPrices: Whether to fetch and show the skin prices alongside the names.
  • fetchSkinRarities: Same as above but for rarities.

These two options were the very first two that I added to the bot, because I wasn't sure whether everybody wanted to see the skin price/rarity. Nowadays, I can't really think of a reason you might want to turn them off. You have the option to I guess.

  • localiseSkinNames: Whether to translate the skin names to the language of people using the bot.

This works because when you use a command (like /shop), Discord sends what language your application is set to. So if your Discord is set to Spanish, the bot will send you the Spanish skin names. This is toggleable because some of the gun translations might be weird in some languages, and some people might prefer the english names.
Note that this can be toggled per-user using /settings.

  • linkItemImage: Make the gun name clickable to view the skin image

On mobile, the embed image is cropped down to a square, and you can't see the whole weapon (great UI design, Discord). This option makes the skin name clickable so you can see the whole image. muckelba, thanks!

  • useEmojisFromServer: Server ID. When looking for an emoji to use (skin rarity & VP icon), look in this server first.

If you use /shop, the bot will first look for the emoji in the server where the command is used. Then, if this option is set, it will look in the server with this ID. Otherwise, it will go through all the servers it's in to find one usable emoji. If it's not available anywhere, it will try to create the emoji. And if it can't, it just won't use any emojis.
Note: Discord bots can use external emojis without having to pay for Nitro btw.

  • refreshSkins: Cron syntax describing when to check for alerts.

This one is in UTC. It's the only one though, the other cron syntaxes will work using your local timezone. By default, the bot checks at 10 seconds after midnight UTC.

  • checkGameVersion: How often to check for a Valorant update. By default, it's every 15 minutes.

  • updateUserAgent: How often to check for a new Riot Client user-agent, helps prevent Cloudflare error 1020 (see below). Every 15mins by default.

  • delayBetweenAlerts: How much time in milliseconds to wait between each person while checking alerts. Defaults to 0.5s.

  • emojiCacheExpiration: The bot fetches a server's emoji list, and keeps it in memory for this much time. Defaults to 10s.

  • loadoutCacheExpiration: Only update someone's skin collection this often at most. Defaults to 10s.

  • alertsPerPage: When using /alerts, how many to display on one page. Watch out, discord doesn't allow more than 25 embed fields.

  • useShopCache: Whether to use shop cache.

If we assume that someone's daily shop, bundles and night market will not change during the day, there's no reason to fetch their shop twice if they do /shop twice. So if the bot fetches someone's daily shop, it saves it to disk for the day, and if they do /shop again, it won't have to fetch the shop from Valorant servers since it already knows what it is.
Note: Valorant returns your daily shop, bundles and night market all in the same request. So if someone does /nightmarket then /shop, it will only have to fetch it once if shop cache is turned on. Checking for someone's alerts will also add their shop to cache.
Also fun fact, did you know that bundles expire at 9PM UTC instead of midnight? Well now you know I guess.

  • useLoginQueue, loginQueue, loginRetryTimeout: Read about these in the login queue part down below.
  • authFailureStrikes: How many times to fail to authenticate before giving up on checking alerts.

Imagine someone uses the bot only a couple of times, and then doesn't delete their account. If they change their password later on, their cookies will be invalidated, but the bot doesn't know that yet. Then once the bot tries to check for alerts for that user, it will fail. By default, the bot will only accept 2 failures before labelling the cookies as invalid and skipping alerts checking for them.

  • maxAccountsPerUser: How many different accounts a user can have. Defaults to 5, as Discord only allows 5 buttons in a row.

  • rateLimitBackoff: When rate limited without an ETA, wait for this many seconds before retrying. Defaults to 1 minute.

  • rateLimitCap: Don't wait for a rate limit to expire for longer than this. Defaults to 10 minutes.

If too many accounts try to authenticate in a short amount of time, Riot will rate limit the bot's IP address. This means that no one can authenticate for a little while.
The exact amount of requests per minute it takes to get rate limited seems to dynamically change according to the load on Riot's servers. Additionally, Riot will only sometimes tell the bot how long the rate limit lasts.
When there's no info on how long the bot is blocked for, the bot will wait 60 seconds by default. That's what rateLimitBackoff is for.
Sometimes, Riot servers will tell the bot that it's rate limited for an hour, but silently unblocks the bot sooner than that. So by default, if the bot is told to wait more than 10 minutes, it will actually only wait 10 minutes. That's what rateLimitCap is for.
If you find yourself getting rate limited a lot, try turning on the auth queue.

  • useMultiqueue: Read about this in the sharding part down below.
  • storePasswords: Store people's usernames/passwords instead of cookies.

I don't think I need to tell you that this is a bad idea. Passwords are not stored for people with 2FA on (because just their password is not enough to log in).

  • trackStoreStats: Track how many times each skin appears in someone's shop.

  • statsExpirationDays: How many days to keep the stats of a certain day. The higher the number, the more new skins will have less presence compared to other skins. Set to 0 to never clear them.

  • statsPerPage: How many skins to display per page when using /stats. Won't work with more than 9 due to the discord limit of 10 embeds per message (one is used for the title bar).

  • shardReadyTimeout: How long to wait for each shard to become ready before giving up and crashing. Read more about sharding below.

  • ownerId: The Discord ID of who's allowed to use admin commands. See the admin commands part above.

  • ownerName: What to put as the owner when using /info.

  • status: What to put as the status when using /info.

  • logToChannel: Channel ID. Send the output of the bot to a discord channel, so you can check the logs from your phone.

  • logFrequency: How often to send the logs. Defaults to every 10 seconds.

  • logUrls: For debugging. Log every URL the bot sends a request to.

Sharding

If your bot gets added to 2500 servers, discord won't let you start it without sharding. Sharding is basically a way of splitting up a discord bot into multiple processes to make it more efficient. Discord says you should enable sharding as soon as 2000 servers.

However, I recommend you leave sharding off for bots in less than 1000 severs, and definitely for those in less than 500. All it will do is use extra ram for nothing, and make any cross-shard operation take slightly longer.

To use sharding, you launch the bot using sharding.js instead of SkinPeek.js... and that's it. The bot should automatically take care of the rest.

You will see that every log message will have a number before it, this indicates the shard number that the log is coming from.

Multiqueue

(multiqueue is still in beta. at the moment it seems to not work under pressure. enable it if you're feeling confident, and keep an eye on it.)

One problem with sharding is that the auth queue doesn't work across shards. So if, on every shard, someone does /shop at the exact same time, the bot might get rate limited, and there's nothing it can do about it.

Introducing, multiqueue. Multiqueue is a system where all auth operations are done on shard 0. This way, shard 0 can handle the login queue, and prevent the bot from getting rate limited.

Login queue

The login queue is a way to try and reduce the bot getting rate limited by only fetching someone's auth every X seconds (2s by default).

This means that if you turned on the auth queue, and two people try and authenticate at the same time, it will process one, wait two seconds, and then process the other.

If your bot is a small bot used by only a handful of people, there's no point in enabling the queue, since all they will do is add an unnecessary delay. However, if you are hosting a large bot, and you get rate-limited often, I recommend you turn it on.

If you still get rate limited with the auth queue on, try increasing the seconds in loginQueue.

Cloudflare error 403/1020

Last we heard, Riot had a problem with many people trying to crack Riot accounts. These people do this by getting a list of passwords that got leaked from another website, and trying all those usernames/passwords on riotgames.com, hoping that people reused the same password on multiple websites.

So, they implemented a Cloudflare firewall to try and stop these account crackers by preventing them from logging in if Riot thinks that they are an account cracker. If Riot thinks that someone is not logging in from the official website or the Riot client, it will send them Cloudflare error 1020.

So far, the valorant third-party community has managed to somewhat escape the dreaded error 1020, but every now and then they update their firewall, and we need to find a new way of bypassing it.

So if you get 1020'd, here's what you can do:

  • Riot are known to ban IPs from some popular VPS hosting providers (e.g. Hetzner). If the bot works on your home computer but not on your VPS, the IP has probably been blacklisted.
  • Restart the bot. The bot now automatically tries to fetch the latest user-agent when starting up, and refreshes it every 15 minutes.
  • Update the bot. If you haven't updated in a while, now's the time. I probably already fixed it in the latest update.
  • Wait for an update. If everyone is affected, you can be sure that the community is hard at work trying to find another bypass.

Hope you enjoy using the bot! 😊