levin-bot
v1.0.0
Published
Levin Bot
Readme
Levin Discord Bot
Spanish version: README.es.md
Levin is a bot that lets you define a level system for users using Discord roles. Users move up or down levels based on their activity. Levels determine which channels those users can access.
Prerequisites
Creating the Discord bot
Before you start using this project, you need to create a new application in Discord and add a bot to it. This is done at https://discordapp.com/developers/applications

Once the application is created, you will get a CLIENT_ID, which can be used to add the bot to any Discord server where you want to install it.
Then you need to add a bot inside that application. You will need to copy and securely store the bot token. This token is extremely important because it allows the bot to connect to Discord.

The token must never be committed to any file in the repository and must remain secret.
Database persistence
Levin uses a very basic key-value database persisted as JSON. Due to hardware and cost constraints, that database is persisted to a file in git using the official GitHub API through Octokit. To use that API, you need two things:
- A new repository, ideally dedicated exclusively to this purpose, although that is not required. That repository must contain three files:
dev-db.json,stage-db.json,prod-db.json. You can find an example in dev-db.json.example.

- A user token that has access to that repository. This is created from the user settings interface. This token must never be shared, must never be committed to the repository, and should be handled with the same care as any other password.

Installation
You only need Node.js v24.15.0 LTS. If you use nvm, the repository already includes .nvmrc:
nvm install
nvm use
npm installOnce published to npm, Levin can also be run directly without cloning the repository:
npx levin-botDiscord server setup
Before trying to run the bot, you need to add it to the Discord server where it will run. To do that, an administrator must approve the bot request. Because of that, the bot you create must be marked as "Public". Otherwise, nobody will be able to add it to their Discord server; private bots can only be added by their creator, and only to servers they own.

Then share this link with the administrator of the server you want the bot to join:
https://discordapp.com/oauth2/authorize?&client_id=CLIENT_ID_HERE&scope=bot&permissions=268438528The CLIENT_ID was generated during app creation (see Prerequisites). The number used in the permissions parameter matches the permissions the bot needs to work correctly.
The permissions list is available on the bot administration page:

Roles
In the server settings, make sure the bot has the highest authority possible for role management. Above all, it is important that the bot sits above the roles it is supposed to assign.
For example, this configuration will not work because [Test Levin App] will not be able to remove or assign the NVL1, NVL2, and NVL3 roles.

The configuration needs to look more like this:

Read permissions
It is also essential that the bot has read access to as many channels as possible. It does not need access to every channel, but the automatic level-up logic is based on the messages the bot can read from users. If a user is only active in a specific channel and the bot cannot read messages there, the bot will eventually lower that member's level.
The configuration for any channel Levin should be able to read should look something like this:

Channel for level updates
You should create a channel where Levin can post user level updates. Levin uses this channel to notify anyone with read access there about the level changes it is making.

Starting the bot
From this repository
LEVIN_TOKEN=<bot-token> DB_BACKUP_INTERVAL_IN_MINUTES=2 LEVEL_CHECK_INTERVAL_IN_MINUTES=1440 DB_REPOSITORY=<db_repository> ENV=<dev|stage|prod> GITHUB_TOKEN=<github-token> UPDATES_CHANNEL=<channel-name> npm run devFrom npm with npx
LEVIN_TOKEN=<bot-token> DB_BACKUP_INTERVAL_IN_MINUTES=2 LEVEL_CHECK_INTERVAL_IN_MINUTES=1440 DB_REPOSITORY=<db_repository> ENV=<dev|stage|prod> GITHUB_TOKEN=<github-token> UPDATES_CHANNEL=<channel-name> npx levin-botIf everything is installed correctly, you will see a message indicating that Levin connected to Discord.
Publishing to npm
levin-bot is configured as a public unscoped package, so publishing uses the default npm registry flow:
npm whoami
npm pack --dry-run
npm publishEnvironment variables
| Variable | Required | Description | Example / Notes |
| --- | --- | --- | --- |
| LEVIN_TOKEN | Yes | Discord bot token used to log in. | Get it from the Discord developer portal. Keep it secret. |
| GITHUB_TOKEN | Yes | GitHub token for a user with access to the repository that stores the DB files. | Treated like a password. |
| DB_REPOSITORY | Yes | Repository where dev-db.json, stage-db.json, and prod-db.json live. | Format: owner/repo |
| ENV | Yes | Selects which DB file Levin will use. | Valid values: dev, stage, prod |
| DB_BACKUP_INTERVAL_IN_MINUTES | Yes | Interval used to persist the DB back to GitHub. | Must be greater than 0 and less than or equal to 1440 |
| LEVEL_CHECK_INTERVAL_IN_MINUTES | Yes | Interval used to run automatic level checks. | Must be greater than 0 and less than or equal to 1440 |
| UPDATES_CHANNEL | No | Channel name where Levin posts level changes. | Must match the Discord channel name exactly |
These are the only runtime environment variables currently read by the application code.
Deployment
Any server capable of running Node.js can run Levin. You can run it from this repository with npm run dev, or run the published package directly with npx levin-bot.
Resources
- List of available events: https://gist.github.com/koad/316b265a91d933fd1b62dddfcc3ff584
- Same idea: https://github.com/onepiecehung/discordjs-logger
- General DiscordJS documentation (the API used to communicate with Discord): https://discordjs.guide/#before-you-begin
- DiscordJS API: https://discord.js.org/#/docs/main/stable/general/welcome
- Octokit (GitHub API): https://octokit.github.io/rest.js/v18
- General TypeScript guide: https://www.typescriptlang.org/docs/home.html
