https://github.com/mrjackyliang/discord-stonker-bot
An advanced business-ready bot built for finance-related Discord servers
https://github.com/mrjackyliang/discord-stonker-bot
cryptocurrency discord discord-anti-scam discord-antiraid discord-automod discord-bots discord-event discord-invite-generator discord-roles discord-threads etherscan-api finnhub-api message-copier remove-ads rss-feed-parser stock-market stocktwits-api toggle-permissions twitter-feed webhook-receiver
Last synced: 12 months ago
JSON representation
An advanced business-ready bot built for finance-related Discord servers
- Host: GitHub
- URL: https://github.com/mrjackyliang/discord-stonker-bot
- Owner: mrjackyliang
- License: mit
- Created: 2021-03-07T20:13:29.000Z (over 5 years ago)
- Default Branch: main
- Last Pushed: 2024-09-06T11:37:28.000Z (almost 2 years ago)
- Last Synced: 2025-03-26T03:51:15.250Z (about 1 year ago)
- Topics: cryptocurrency, discord, discord-anti-scam, discord-antiraid, discord-automod, discord-bots, discord-event, discord-invite-generator, discord-roles, discord-threads, etherscan-api, finnhub-api, message-copier, remove-ads, rss-feed-parser, stock-market, stocktwits-api, toggle-permissions, twitter-feed, webhook-receiver
- Language: TypeScript
- Homepage:
- Size: 452 KB
- Stars: 11
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
Discord Stonker Bot
====================
[](https://github.com/mrjackyliang/discord-stonker-bot/releases)
[](https://github.com/mrjackyliang/discord-stonker-bot)
[](https://github.com/mrjackyliang/discord-stonker-bot/blob/main/LICENSE)
[](https://github.com/sponsors/mrjackyliang)
[](https://liang.nyc/paypal)
An advanced business-ready bot built for finance-related Discord servers. This bot adds a suite of features designed to enhance the experience of your server such as content organization, impersonator detection, bumping threads, and more.
To use this Discord bot, you would need to:
1. Install the [dependencies](#install-dependencies)
2. Configure the [Discord application](#configure-discord-application)
3. Configure the [Twitter application](#configure-twitter-application) (optional)
4. Configure the [Stonker Bot](#bot-configuration)
5. Start the bot using `npm start`
## Install Dependencies
Before configuring and starting the bot, make sure to install the dependencies and required packages.
1. Install [Homebrew](https://brew.sh) and run `brew install node`
2. Tap into the bot directory with `cd discord-stonker-bot`
3. Install dependencies by running `npm install`
## Configure Discord Application
Here are the instructions on how you can create an application and connect this bot to your Discord server. Simply follow the directions below:
1. First go to the [Discord Developer Portal](https://discord.com/developers/applications)
2. In the top right corner, click __New Application__
3. Under the __Name__ field, type "Stonker Bot"
- If applicable, select a team under the __Team__ dropdown
4. Click __Create__ to create the application
5. Once the application is created, click the __Bot__ menu item on the left
6. Click __Add Bot__ in the top right corner and then click __Yes, do it!__
7. Under __Privileged Gateway Intents__, turn on these options:
- __PRESENCE INTENT__
- __SERVER MEMBERS INTENT__
- __MESSAGE CONTENT INTENT__
8. Click the __General Information__ menu item
9. Under __Application ID__, click __Copy__
10. Replace the `APP_ID_HERE` below with the application ID you just copied then visit that link to add the bot into your server:
- `https://discord.com/oauth2/authorize?client_id=APP_ID_HERE&scope=bot&permissions=292348488773`
## Configure Twitter Application
Here are the instructions on how you can create an application and enable Twitter features on this bot. Simply follow the directions below:
1. First go to [Twitter Developers](https://developer.twitter.com/portal/dashboard)
2. In the middle, click __+ Create Project__
3. Under the __Project name__ field, type "Stonker", then click __Next__
4. Under the __Select a use case__ field, select "Build customized solutions in-house", then click __Next__
5. Under the __Project description__ field, type "For use with Stonker projects", then click __Next__
6. Under the __App name__ field, type "Stonker Bot", then click __Next__
7. Click __App settings__
8. Under __User authentication settings__, click __Set up__
9. Enable the __OAuth 1.0a__ section
10. Under __OAUTH 1.0A SETTINGS__ > __App permissions__, select __Read and write__
11. Under __Callback URI / Redirect URL__, type "http://localhost"
12. Under __Website URL__, type in "http://www.example.com"
13. Click __Save__ and then click __Yes__
## Bot Configuration
In the project folder, you will find a `config-sample.json` file. Each section enables a feature and must be configured correctly. If you wish to disable a feature, you may omit the section from the configuration.
__Note:__ It is recommended that you configure the bot with a freshly made `config.json` file instead of copying directly from `config-sample.json`.
1. [Base Settings](#1-base-settings)
2. [Snitch Notifications](#2-snitch-notifications)
3. [Server Tools](#3-server-tools)
4. [Web Applications](#4-web-applications)
5. [API Fetch](#5-api-fetch)
6. [Anti-Raid](#6-anti-raid)
7. [Schedule Posts](#7-schedule-posts)
8. [RSS Feeds](#8-rss-feeds)
9. [Regex Rules](#9-regex-rules)
10. [Detect Suspicious Words](#10-detect-suspicious-words)
11. [Sync Roles](#11-sync-roles)
12. [Role Messages](#12-role-messages)
13. [Auto Replies](#13-auto-replies)
14. [Message Copiers](#14-message-copiers)
15. [Message Proxies](#15-message-proxies)
16. [Remove Affiliates](#16-remove-affiliates)
17. [Toggle Permissions](#17-toggle-permissions)
18. [Bump Threads](#18-bump-threads)
19. [Impersonator Alerts](#19-impersonator-alerts)
20. [Scammer Alerts](#20-scammer-alerts)
21. [Twitter Feeds](#21-twitter-feeds)
22. [Broadcast Alerts](#22-broadcast-alerts)
### 1. Base Settings
For Stonker Bot to start, the required settings should be filled.
| __Key__ | __Type__ | __Description__ | __Required__ | __Accepted Values__ |
|----------------------------------------|----------|---------------------------------------------------------|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `settings` | `object` | | yes | |
| `settings.discord` | `object` | | yes | |
| `settings.discord.token` | `string` | Token used to login to the Discord application | yes | Token found in [Discord Developer Portal](https://discord.com/developers/applications) after [configuring the Discord application](#configure-discord-application) |
| `settings.discord.guild` | `object` | | yes | |
| `settings.discord.guild.description` | `string` | Description of the guild | no | |
| `settings.discord.guild.guild-id` | `string` | Guild | yes | Discord guild ID |
| `settings.twitter` | `object` | | no | |
| `settings.twitter.api-key` | `string` | API key used to login to the Twitter application | yes | API key found in [Twitter Developers](https://developer.twitter.com/portal/dashboard) after [configuring the Twitter application](#configure-twitter-application) |
| `settings.twitter.api-key-secret` | `string` | API key secret used to login to the Twitter application | yes | API key secret found in [Twitter Developers](https://developer.twitter.com/portal/dashboard) after [configuring the Twitter application](#configure-twitter-application) |
| `settings.twitter.access-token` | `string` | Access token used to login to the Twitter user | yes | Access token found in [Twitter Developers](https://developer.twitter.com/portal/dashboard) after [configuring the Twitter application](#configure-twitter-application) |
| `settings.twitter.access-token-secret` | `string` | Access token secret used to login to the Twitter user | yes | Access token secret found in [Twitter Developers](https://developer.twitter.com/portal/dashboard) after [configuring the Twitter application](#configure-twitter-application) |
| `settings.time-zone` | `string` | Preferred time zone | yes | Time zones found in the [tz database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) |
| `settings.log-level` | `number` | Verbosity level for logged messages | yes | `10` (error), `20` (warning), `30` (information), or `40` (debug) |
```json
{
"settings": {
"discord": {
"token": "",
"guild": {
"description": "",
"guild-id": ""
}
},
"twitter": {
"api-key": "",
"api-key-secret": "",
"access-token": "",
"access-token-secret": ""
},
"time-zone": "Etc/UTC",
"log-level": 30
}
}
```
### 2. Snitch Notifications
Get notifications from user actions surrounding your server. You can pick between receiving notifications related to user changes, when a message status changes, or when a message includes a link or attachment.
__Note:__ Only messages cached (during the current session or last edited within 30 days) will be tracked. To preserve cached events, you may create multiple configurable bot instances.
| __Key__ | __Type__ | __Description__ | __Required__ | __Accepted Values__ |
|------------------------------------------------------------|------------|---------------------------------------------------------------------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `snitch` | `object` | | no | |
| `snitch.change-nickname` | `object` | | no | |
| `snitch.change-nickname.channel` | `object` | | yes | |
| `snitch.change-nickname.channel.description` | `string` | Description of the channel used to report nickname changes | no | |
| `snitch.change-nickname.channel.channel-id` | `string` | Channel used to report nickname changes | yes | Discord channel ID |
| `snitch.change-username` | `object` | | no | |
| `snitch.change-username.channel` | `object` | | yes | |
| `snitch.change-username.channel.description` | `string` | Description of the channel used to report username changes | no | |
| `snitch.change-username.channel.channel-id` | `string` | Channel used to report username changes | yes | Discord channel ID |
| `snitch.delete-message` | `object` | | no | |
| `snitch.delete-message.channel` | `object` | | yes | |
| `snitch.delete-message.channel.description` | `string` | Description of the channel used to report deleted messages | no | |
| `snitch.delete-message.channel.channel-id` | `string` | Channel used to report deleted messages | yes | Discord channel ID |
| `snitch.guild-join` | `object` | | no | |
| `snitch.guild-join.channel` | `object` | | yes | |
| `snitch.guild-join.channel.description` | `string` | Description of the channel used to report guild member join | no | |
| `snitch.guild-join.channel.channel-id` | `string` | Channel used to report guild member join | yes | Discord channel ID |
| `snitch.guild-leave` | `object` | | no | |
| `snitch.guild-leave.channel` | `object` | | yes | |
| `snitch.guild-leave.channel.description` | `string` | Description of the channel used to report guild member leave | no | |
| `snitch.guild-leave.channel.channel-id` | `string` | Channel used to report guild member leave | yes | Discord channel ID |
| `snitch.includes-link` | `object` | | no | |
| `snitch.includes-link.channel` | `object` | | yes | |
| `snitch.includes-link.channel.description` | `string` | Description of the channel used to report messages with links | no | |
| `snitch.includes-link.channel.channel-id` | `string` | Channel used to report messages with links | yes | Discord channel ID |
| `snitch.includes-link.excluded-links` | `object[]` | | no | |
| `snitch.includes-link.excluded-links[x].name` | `string` | Name of the excluded link | no | |
| `snitch.includes-link.excluded-links[x].regex` | `object` | | yes | |
| `snitch.includes-link.excluded-links[x].regex.description` | `string` | Description of the excluded link regex | no | |
| `snitch.includes-link.excluded-links[x].regex.pattern` | `string` | Regex pattern | yes | Read [Writing a regular expression pattern](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#writing_a_regular_expression_pattern) |
| `snitch.includes-link.excluded-links[x].regex.flags` | `string` | Regex flags | no | Read [Advanced searching with flags](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#advanced_searching_with_flags) |
| `snitch.role-change` | `object` | | no | |
| `snitch.role-change.channel` | `object` | | yes | |
| `snitch.role-change.channel.description` | `string` | Description of the channel used to report guild member role change | no | |
| `snitch.role-change.channel.channel-id` | `string` | Channel used to report guild member role change | yes | Discord channel ID |
| `snitch.update-message` | `object` | | no | |
| `snitch.update-message.channel` | `object` | | yes | |
| `snitch.update-message.channel.description` | `string` | Description of the channel used to report edited messages | no | |
| `snitch.update-message.channel.channel-id` | `string` | Channel used to report edited messages | yes | Discord channel ID |
| `snitch.upload-attachment` | `object` | | no | |
| `snitch.upload-attachment.channel` | `object` | | yes | |
| `snitch.upload-attachment.channel.description` | `string` | Description of the channel used to report messages with attachments | no | |
| `snitch.upload-attachment.channel.channel-id` | `string` | Channel used to report messages with attachments | yes | Discord channel ID |
```json
{
"snitch": {
"change-nickname": {
"channel": {
"description": "Sample channel",
"channel-id": "000000000000000000"
}
},
"change-username": {
"channel": {
"description": "Sample channel",
"channel-id": "000000000000000000"
}
},
"delete-message": {
"channel": {
"description": "Sample channel",
"channel-id": "000000000000000000"
}
},
"guild-join": {
"channel": {
"description": "Sample channel",
"channel-id": "000000000000000000"
}
},
"guild-leave": {
"channel": {
"description": "Sample channel",
"channel-id": "000000000000000000"
}
},
"includes-link": {
"channel": {
"description": "Sample channel",
"channel-id": "000000000000000000"
},
"excluded-links": [
{
"name": "Sample",
"regex": {
"description": "Sample regex",
"pattern": "(.+)",
"flags": "g"
}
}
]
},
"role-change": {
"channel": {
"description": "Sample channel",
"channel-id": "000000000000000000"
}
},
"update-message": {
"channel": {
"description": "Sample channel",
"channel-id": "000000000000000000"
}
},
"upload-attachment": {
"channel": {
"description": "Sample channel",
"channel-id": "000000000000000000"
}
}
}
}
```
### 3. Server Tools
Easily manage your Discord server with these tools. Fetch information, manage roles, voice and stage channel controls, and ban multiple users with one command.
| __Key__ | __Type__ | __Description__ | __Required__ | __Accepted Values__ |
|--------------------------------------------------------------|------------|----------------------------------|--------------|-------------------------------------------------------------|
| `server-tools` | `object` | | no | |
| `server-tools.bulk-ban` | `object` | | no | |
| `server-tools.bulk-ban.base-commands` | `string[]` | Keywords to initiate command | yes | If there are prefixes, it is recommended to keep them exact |
| `server-tools.bulk-ban.delete-message` | `boolean` | Delete message when command runs | no | `true` or `false` |
| `server-tools.bulk-ban.allowed-roles` | `object[]` | | no | |
| `server-tools.bulk-ban.allowed-roles[x].description` | `string` | Description of the allowed role | no | |
| `server-tools.bulk-ban.allowed-roles[x].role-id` | `string` | Allowed role | yes | Discord role ID |
| `server-tools.fetch-duplicates` | `object` | | no | |
| `server-tools.fetch-duplicates.base-commands` | `string[]` | Keywords to initiate command | yes | If there are prefixes, it is recommended to keep them exact |
| `server-tools.fetch-duplicates.delete-message` | `boolean` | Delete message when command runs | no | `true` or `false` |
| `server-tools.fetch-duplicates.allowed-roles` | `object[]` | | no | |
| `server-tools.fetch-duplicates.allowed-roles[x].description` | `string` | Description of the allowed role | no | |
| `server-tools.fetch-duplicates.allowed-roles[x].role-id` | `string` | Allowed role | yes | Discord role ID |
| `server-tools.fetch-emojis` | `object` | | no | |
| `server-tools.fetch emojis.base-commands` | `string[]` | Keywords to initiate command | yes | If there are prefixes, it is recommended to keep them exact |
| `server-tools.fetch-emojis.delete-message` | `boolean` | Delete message when command runs | no | `true` or `false` |
| `server-tools.fetch-emojis.allowed-roles` | `object[]` | | no | |
| `server-tools.fetch-emojis.allowed-roles[x].description` | `string` | Description of the allowed role | no | |
| `server-tools.fetch-emojis.allowed-roles[x].role-id` | `string` | Allowed role | yes | Discord role ID |
| `server-tools.fetch-members` | `object` | | no | |
| `server-tools.fetch-members.base-commands` | `string[]` | Keywords to initiate command | yes | If there are prefixes, it is recommended to keep them exact |
| `server-tools.fetch-members.delete-message` | `boolean` | Delete message when command runs | no | `true` or `false` |
| `server-tools.fetch-members.allowed-roles` | `object[]` | | no | |
| `server-tools.fetch-members.allowed-roles[x].description` | `string` | Description of the allowed role | no | |
| `server-tools.fetch-members.allowed-roles[x].role-id` | `string` | Allowed role | yes | Discord role ID |
| `server-tools.role-manager` | `object` | | no | |
| `server-tools.role-manager.base-commands` | `string[]` | Keywords to initiate command | yes | If there are prefixes, it is recommended to keep them exact |
| `server-tools.role-manager.delete-message` | `boolean` | Delete message when command runs | no | `true` or `false` |
| `server-tools.role-manager.allowed-roles` | `object[]` | | no | |
| `server-tools.role-manager.allowed-roles[x].description` | `string` | Description of the allowed role | no | |
| `server-tools.role-manager.allowed-roles[x].role-id` | `string` | Allowed role | yes | Discord role ID |
| `server-tools.voice-tools` | `object` | | no | |
| `server-tools.voice-tools.base-commands` | `string[]` | Keywords to initiate command | yes | If there are prefixes, it is recommended to keep them exact |
| `server-tools.voice-tools.delete-message` | `boolean` | Delete message when command runs | no | `true` or `false` |
| `server-tools.voice-tools.allowed-roles` | `object[]` | | no | |
| `server-tools.voice-tools.allowed-roles[x].description` | `string` | Description of the allowed role | no | |
| `server-tools.voice-tools.allowed-roles[x].role-id` | `string` | Allowed role | yes | Discord role ID |
```json
{
"server-tools": {
"bulk-ban": {
"base-commands": [
"!ban"
],
"delete-message": true,
"allowed-roles": [
{
"description": "Sample role",
"role-id": "000000000000000000"
}
]
},
"fetch-duplicates": {
"base-commands": [
"!duplicates"
],
"delete-message": true,
"allowed-roles": [
{
"description": "Sample role",
"role-id": "000000000000000000"
}
]
},
"fetch-emojis": {
"base-commands": [
"!emojis"
],
"delete-message": true,
"allowed-roles": [
{
"description": "Sample role",
"role-id": "000000000000000000"
}
]
},
"fetch-members": {
"base-commands": [
"!members"
],
"delete-message": true,
"allowed-roles": [
{
"description": "Sample role",
"role-id": "000000000000000000"
}
]
},
"role-manager": {
"base-commands": [
"!role"
],
"delete-message": true,
"allowed-roles": [
{
"description": "Sample role",
"role-id": "000000000000000000"
}
]
},
"voice-tools": {
"base-commands": [
"!voice"
],
"delete-message": true,
"allowed-roles": [
{
"description": "Sample role",
"role-id": "000000000000000000"
}
]
}
}
}
```
### 4. Web Applications
Connect external applications and traffic into your Discord server. To enable web applications, at least one server (HTTP or HTTPS) must be configured.
1. [Invite Generator](#41-invite-generator)
2. [Map Webhooks](#42-map-webhooks)
__Note:__ During reboots, all web applications will be taken offline. To increase uptime, you may create multiple configurable bot instances.
| __Key__ | __Type__ | __Description__ | __Required__ | __Accepted Values__ |
|--------------------------------------|----------|----------------------------------------|--------------|----------------------------------------------------------------|
| `web-applications` | `object` | | no | |
| `web-applications.http-server` | `object` | | no | |
| `web-applications.http-server.port` | `number` | Web server HTTP port | yes | From `1` to `65535` |
| `web-applications.https-server` | `object` | | no | |
| `web-applications.https-server.port` | `number` | Web server HTTPS port | yes | From `1` to `65535` |
| `web-applications.https-server.key` | `string` | Path to the private key file | yes | Absolute file path for the private key in PEM format |
| `web-applications.https-server.cert` | `string` | Path to the certificate chain file | yes | Absolute file path for the certificate chain in PEM format |
| `web-applications.https-server.ca` | `string` | Path to the certificate authority file | yes | Absolute file path for the certificate authority in PEM format |
```json
{
"web-applications": {
"http-server": {
"port": 8080
},
"https-server": {
"port": 8443,
"key": "",
"cert": "",
"ca": ""
}
}
}
```
#### 4.1. Invite Generator
A membership invite gate to protect your Discord server from being raided and spammed on. Authentication is made from Google's reCAPTCHA service. To customize the invite generator webpage, rename the `invites-sample.ejs` file to `invites.ejs` and begin editing.
| __Key__ | __Type__ | __Description__ | __Required__ | __Accepted Values__ |
|----------------------------------------------------------|----------|-----------------------------------------|--------------|-------------------------------------------------------------------------------------------------------------|
| `web-applications.invite-generator` | `object` | | no | |
| `web-applications.invite-generator.options` | `object` | | yes | |
| `web-applications.invite-generator.options.path` | `string` | Path for accessing invite generator | yes | Paths begin with `/`. For example, a URL of `https://www.example.com/invite` would have a path of `/invite` |
| `web-applications.invite-generator.options.max-age` | `number` | Invite maximum age | no | Time in seconds (e.g. 1 minute equals `60`) |
| `web-applications.invite-generator.options.max-uses` | `number` | Invite maximum uses | no | Whole numbers |
| `web-applications.invite-generator.recaptcha` | `object` | | yes | |
| `web-applications.invite-generator.recaptcha.site-key` | `string` | Google reCAPTCHA v2 checkbox site key | yes | [Sign-up](https://www.google.com/recaptcha/admin/create) for a reCAPTCHA v2 checkbox |
| `web-applications.invite-generator.recaptcha.secret-key` | `string` | Google reCAPTCHA v2 checkbox secret key | yes | [Sign-up](https://www.google.com/recaptcha/admin/create) for a reCAPTCHA v2 checkbox |
```json
{
"web-applications": {
"invite-generator": {
"options": {
"path": "/invite",
"max-age": 120,
"max-uses": 1
},
"recaptcha": {
"site-key": "",
"secret-key": ""
}
}
}
}
```
#### 4.2. Map Webhooks
Convert external webhooks (JSON-based) and send them as Discord messages. Use Discord as a back-office and stick to one platform!
| __Key__ | __Type__ | __Description__ | __Required__ | __Accepted Values__ |
|-----------------------------------------------------------------|------------|---------------------------------------------------------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `web-applications.map-webhooks` | `object[]` | | no | |
| `web-applications.map-webhooks[x].name` | `string` | Name of the event | no | |
| `web-applications.map-webhooks[x].path` | `string` | Path for sending webhooks to | yes | Paths begin with `/`. For example, a URL of `https://www.example.com/webhooks/sample` would have a path of `/webhooks/sample` |
| `web-applications.map-webhooks[x].variables` | `object[]` | | yes | |
| `web-applications.map-webhooks[x].variables[x].id` | `string` | Variable identifier | yes | Capital letters and underscores. Underscores are not allowed in the beginning or end of the identifier |
| `web-applications.map-webhooks[x].variables[x].type` | `string` | Variable type | yes | `string`, `boolean`, `ts-seconds`, `ts-millis`, `usd-dollars`, or `usd-cents` |
| `web-applications.map-webhooks[x].variables[x].path` | `string` | Variable path | yes | Access the value from the `path` of the object. If the value is not supported, it will return a string value |
| `web-applications.map-webhooks[x].payload` | `object` | Message content to send for each webhook request | yes | `BaseMessageOptions` in [discord.js Documentation](https://discord.js.org/#/docs/main/stable/typedef/BaseMessageOptions). Variables include `%YEAR%`. To access incoming variables, define them like `@SAMPLE@`. `SAMPLE` is the value of `web-applications.map-webhooks[x].variables[x].id` |
| `web-applications.map-webhooks[x].channel` | `object` | | yes | |
| `web-applications.map-webhooks[x].channel.description` | `string` | Description of the channel used to send message content | no | |
| `web-applications.map-webhooks[x].channel.channel-id` | `string` | Channel used to send message content | yes | Discord channel ID |
```json
{
"web-applications": {
"map-webhooks": [
{
"name": "Sample",
"path": "/webhooks/sample",
"variables": [
{
"id": "SAMPLE_TEXT",
"type": "string",
"path": "path.to[0].sample-text"
},
{
"id": "SAMPLE_TOGGLE",
"type": "boolean",
"path": "path.to[1].sample-toggle"
},
{
"id": "SAMPLE_SECONDS",
"type": "ts-seconds",
"path": "path.to[2].sample-seconds"
},
{
"id": "SAMPLE_MILLIS",
"type": "ts-millis",
"path": "path.to[3].sample-millis"
},
{
"id": "SAMPLE_USD_DOLLARS",
"type": "usd-dollars",
"path": "path.to[4].sample-dollars"
},
{
"id": "SAMPLE_USD_CENTS",
"type": "usd-cents",
"path": "path.to[5].sample-cents"
}
],
"payload": {
"content": "@SAMPLE_TEXT@ - @SAMPLE_TOGGLE@ - @SAMPLE_SECONDS@ - @SAMPLE_MILLIS@ - @SAMPLE_USD_DOLLARS@ - @SAMPLE_USD_CENTS@",
"footer": {
"text": "Copyright © %YEAR% Your Company"
}
},
"channel": {
"description": "Sample channel",
"channel-id": "000000000000000000"
}
}
]
}
}
```
### 5. API Fetch
Retrieve updated information through a live feed and via a customizable keyword (like a command). Current APIs available are Etherscan, Finnhub, and Stocktwits.
| __Key__ | __Type__ | __Description__ | __Required__ | __Accepted Values__ |
|-----------------------------------------------------------------------|------------|-----------------------------------------------------------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------|
| `api-fetch` | `object` | | no | |
| `api-fetch.etherscan-gas-oracle` | `object` | | no | |
| `api-fetch.etherscan-gas-oracle.settings` | `object` | | no | |
| `api-fetch.etherscan-gas-oracle.settings.api-key` | `string` | API key to access the Etherscan API | no | [Sign up for an Etherscan API Key](https://etherscan.io/register) |
| `api-fetch.etherscan-gas-oracle.channel` | `object` | | no | |
| `api-fetch.etherscan-gas-oracle.channel.description` | `string` | Description of the channel used to send API updates | no | |
| `api-fetch.etherscan-gas-oracle.channel.channel-id` | `string` | Channel used to send API updates | yes | Discord channel ID |
| `api-fetch.etherscan-gas-oracle.command` | `object` | | no | |
| `api-fetch.etherscan-gas-oracle.command.base-commands` | `string[]` | Keywords to initiate command | yes | If there are prefixes, it is recommended to keep them exact |
| `api-fetch.etherscan-gas-oracle.command.allowed-roles` | `object[]` | | no | |
| `api-fetch.etherscan-gas-oracle.command.allowed-roles[x].description` | `string` | Description of the allowed role | no | |
| `api-fetch.etherscan-gas-oracle.command.allowed-roles[x].role-id` | `string` | Allowed role | yes | Discord role ID |
| `api-fetch.etherscan-gas-oracle.command.no-perms-payload` | `object` | Message content to send if user does not have permissions | no | `BaseMessageOptions` in [discord.js Documentation](https://discord.js.org/#/docs/main/stable/typedef/BaseMessageOptions). Variables include `%YEAR%` |
| `api-fetch.finnhub-earnings` | `object` | | no | |
| `api-fetch.finnhub-earnings.settings` | `object` | | yes | |
| `api-fetch.finnhub-earnings.settings.api-key` | `string` | API key to access the Finnhub API | yes | [Sign up for a Finnhub API Key](https://finnhub.io/register) |
| `api-fetch.finnhub-earnings.channel` | `object` | | no | |
| `api-fetch.finnhub-earnings.channel.description` | `string` | Description of the channel used to send API updates | no | |
| `api-fetch.finnhub-earnings.channel.channel-id` | `string` | Channel used to send API updates | yes | Discord channel ID |
| `api-fetch.finnhub-earnings.command` | `object` | | no | |
| `api-fetch.finnhub-earnings.command.base-commands` | `string[]` | Keywords to initiate command | yes | If there are prefixes, it is recommended to keep them exact |
| `api-fetch.finnhub-earnings.command.allowed-roles` | `object[]` | | no | |
| `api-fetch.finnhub-earnings.command.allowed-roles[x].description` | `string` | Description of the allowed role | no | |
| `api-fetch.finnhub-earnings.command.allowed-roles[x].role-id` | `string` | Allowed role | yes | Discord role ID |
| `api-fetch.finnhub-earnings.command.no-perms-payload` | `object` | Message content to send if user does not have permissions | no | `BaseMessageOptions` in [discord.js Documentation](https://discord.js.org/#/docs/main/stable/typedef/BaseMessageOptions). Variables include `%YEAR%` |
| `api-fetch.stocktwits-trending` | `object` | | no | |
| `api-fetch.stocktwits-trending.settings` | `object` | | no | |
| `api-fetch.stocktwits-trending.settings.limit` | `number` | Symbols to retrieve for each retrieval | no | From `1` to `30` |
| `api-fetch.stocktwits-trending.channel` | `object` | | no | |
| `api-fetch.stocktwits-trending.channel.description` | `string` | Description of the channel used to send API updates | no | |
| `api-fetch.stocktwits-trending.channel.channel-id` | `string` | Channel used to send API updates | yes | Discord channel ID |
| `api-fetch.stocktwits-trending.command` | `object` | | no | |
| `api-fetch.stocktwits-trending.command.base-commands` | `string[]` | Keywords to initiate command | yes | If there are prefixes, it is recommended to keep them exact |
| `api-fetch.stocktwits-trending.command.allowed-roles` | `object[]` | | no | |
| `api-fetch.stocktwits-trending.command.allowed-roles[x].description` | `string` | Description of the allowed role | no | |
| `api-fetch.stocktwits-trending.command.allowed-roles[x].role-id` | `string` | Allowed role | yes | Discord role ID |
| `api-fetch.stocktwits-trending.command.no-perms-payload` | `object` | Message content to send if user does not have permissions | no | `BaseMessageOptions` in [discord.js Documentation](https://discord.js.org/#/docs/main/stable/typedef/BaseMessageOptions). Variables include `%YEAR%` |
```json
{
"api-fetch": {
"etherscan-gas-oracle": {
"settings": {
"api-key": ""
},
"channel": {
"description": "Sample channel",
"channel-id": "000000000000000000"
},
"command": {
"base-commands": [
"!gas"
],
"allowed-roles": [
{
"description": "Sample role",
"role-id": "000000000000000000"
}
],
"no-perms-payload": {
"content": "You do not have sufficient permissions.",
"footer": {
"text": "Copyright © %YEAR% Your Company"
}
}
}
},
"finnhub-earnings": {
"settings": {
"api-key": ""
},
"channel": {
"description": "Sample channel",
"channel-id": "000000000000000000"
},
"command": {
"base-commands": [
"!earnings"
],
"allowed-roles": [
{
"description": "Sample role",
"role-id": "000000000000000000"
}
],
"no-perms-payload": {
"content": "You do not have sufficient permissions.",
"footer": {
"text": "Copyright © %YEAR% Your Company"
}
}
}
},
"stocktwits-trending": {
"settings": {
"limit": 30
},
"channel": {
"description": "Sample channel",
"channel-id": "000000000000000000"
},
"command": {
"base-commands": [
"!trending"
],
"allowed-roles": [
{
"description": "Sample role",
"role-id": "000000000000000000"
}
],
"no-perms-payload": {
"content": "You do not have sufficient permissions.",
"footer": {
"text": "Copyright © %YEAR% Your Company"
}
}
}
}
}
}
```
### 6. Anti-Raid
A set of tools to ban members (based on their avatar or username), and helps automate the membership gate for those that just joined the server.
__Note:__ Anti-raid will not auto ban or assign roles during restarts. To increase uptime, you may create multiple configurable bot instances.
| __Key__ | __Type__ | __Description__ | __Required__ | __Accepted Values__ |
|--------------------------------------------------|------------|--------------------------------------------------------------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `anti-raid` | `object` | | no | |
| `anti-raid.auto-ban` | `object` | | no | |
| `anti-raid.auto-ban.avatars` | `object[]` | | no | |
| `anti-raid.auto-ban.avatars[x].description` | `string` | Description of the banned avatar | no | |
| `anti-raid.auto-ban.avatars[x].avatar` | `string` | Banned avatar | yes | File name of avatar (without the file extension) |
| `anti-raid.auto-ban.usernames` | `object[]` | | no | |
| `anti-raid.auto-ban.usernames[x].description` | `string` | Description of the banned username | no | |
| `anti-raid.auto-ban.usernames[x].username` | `string` | Banned username | yes | Username (do not include the discriminator) |
| `anti-raid.membership-gate` | `object` | | no | |
| `anti-raid.membership-gate.roles` | `object` | | no | |
| `anti-raid.membership-gate.roles[x].description` | `string` | Description of the role assigned to verified member | no | |
| `anti-raid.membership-gate.roles[x].role-id` | `string` | Role assigned to verified member | yes | Discord role ID |
| `anti-raid.membership-gate.payload` | `object` | Message content to send when user passes the membership gate | no | `BaseMessageOptions` in [discord.js Documentation](https://discord.js.org/#/docs/main/stable/typedef/BaseMessageOptions). Variables include `%GUILD_NAME%`, `%MEMBER_MENTION%`, and `%YEAR%` |
| `anti-raid.membership-gate.channel` | `object` | | no | |
| `anti-raid.membership-gate.channel.description` | `string` | Description of the channel used to send message content | no | |
| `anti-raid.membership-gate.channel.channel-id` | `string` | Channel used to send message content | yes | Discord channel ID |
```json
{
"anti-raid": {
"auto-ban": {
"avatars": [
{
"description": "Sample avatar",
"avatar": "00000000000000000000000000000000"
}
],
"usernames": [
{
"description": "Sample username",
"username": "Bad User"
}
]
},
"membership-gate": {
"roles": [
{
"description": "Sample role",
"role-id": "000000000000000000"
}
],
"payload": {
"content": "Welcome to %GUILD_NAME%! Thank you for verifying, %MEMBER_MENTION%.",
"footer": {
"text": "Copyright © %YEAR% Your Company"
}
},
"channel": {
"description": "Sample channel",
"channel-id": "000000000000000000"
}
}
}
}
```
### 7. Schedule Posts
You can schedule messages to be sent out to a specific text-based channel. No more inconsistently timed messages! You are also able to skip specific dates from posting (like a holiday, for instance) and even send on a specific day.
| __Key__ | __Type__ | __Description__ | __Required__ | __Accepted Values__ |
|------------------------------------------|------------|---------------------------------------------------------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------|
| `schedule-posts` | `object[]` | | no | |
| `schedule-posts[x].name` | `string` | Name of the event | no | |
| `schedule-posts[x].payload` | `object` | Message content to send when time ticks | yes | `BaseMessageOptions` in [discord.js Documentation](https://discord.js.org/#/docs/main/stable/typedef/BaseMessageOptions). Variables include `%YEAR%` |
| `schedule-posts[x].reactions` | `string[]` | Message reactions | no | Unicode emojis or a custom emoji identifier string (`<:sample:000000000000000000>` for static, `` for animated) |
| `schedule-posts[x].channel` | `object` | | no | |
| `schedule-posts[x].channel.description` | `string` | Description of the channel used to send message content | no | |
| `schedule-posts[x].channel.channel-id` | `string` | Channel used to send message content | yes | Discord channel ID |
| `schedule-posts[x].send-on` | `object` | | no | |
| `schedule-posts[x].send-on.time-zone` | `string` | Send on time zone | no | Time zones found in the [tz database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) |
| `schedule-posts[x].send-on.days-of-week` | `number[]` | Send on day of week | no | `0` (Sunday), `1` (Monday), `2` (Tuesday), `3` (Wednesday), `4` (Thursday), `5` (Friday), and `6` (Saturday) |
| `schedule-posts[x].send-on.months` | `number[]` | Send on month | no | From `1` to `12` |
| `schedule-posts[x].send-on.dates` | `number[]` | Send on date | no | From `1` to `31` |
| `schedule-posts[x].send-on.hours` | `number[]` | Send on hour of day | no | From `0` to `23` |
| `schedule-posts[x].send-on.minutes` | `number[]` | Send on minute of hour | no | From `0` to `59` |
| `schedule-posts[x].send-on.seconds` | `number[]` | Send on second of minute | no | From `0` to `59` |
| `schedule-posts[x].skip-dates` | `string[]` | Skip on specified dates | no | Date format is `YYYY-MM-DD` |
```json
{
"schedule-posts": [
{
"name": "Sample",
"payload": {
"content": "This is a sample scheduled post",
"footer": {
"text": "Copyright © %YEAR% Your Company"
}
},
"reactions": [
"🟢",
"🟡",
"🔴"
],
"channel": {
"description": "Sample channel",
"channel-id": "000000000000000000"
},
"send-on": {
"time-zone": "Etc/UTC",
"days-of-week": [
0,
1,
2,
3,
4,
5,
6
],
"months": [
1
],
"dates": [
1
],
"hours": [
0
],
"minutes": [
0
],
"seconds": [
0
]
},
"skip-dates": [
"2021-01-01",
"2021-02-01"
]
}
]
}
```
### 8. RSS Feeds
Sends out messages when an update from external RSS feeds are detected. Control how often you want the bot to fetch updates. You may also choose to have links resolved to their final destination and have parameters removed as well.
__Note:__ For Google News RSS Feeds, the source will be stripped from the title automatically.
| __Key__ | __Type__ | __Description__ | __Required__ | __Accepted Values__ |
|--------------------------------------|------------|---------------------------------------------------------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `rss-feeds` | `object[]` | | no | |
| `rss-feeds[x].name` | `string` | Name of the event | no | |
| `rss-feeds[x].url` | `string` | Link to RSS feed | yes | Fully qualified URL |
| `rss-feeds[x].user-agent` | `string` | User agent to use when retrieving RSS feed | no | Most popular user agents found in [Tech Blog (wh)](https://techblog.willshouse.com/2012/01/03/most-common-user-agents/) |
| `rss-feeds[x].follow-redirects` | `boolean` | Follow redirects for each RSS update | no | `true` or `false` |
| `rss-feeds[x].remove-parameters` | `boolean` | Remove all parameters for each RSS update | no | `true` or `false` |
| `rss-feeds[x].allowed-urls` | `string[]` | Allow only URLs you specify to be sent | no | Partial URL beginning with. For example, `https://www.example.com/news/example.html` is allowed if `https://www.example.com/news/` is specified |
| `rss-feeds[x].payload` | `object` | Message content to send for each RSS update | yes | `BaseMessageOptions` in [discord.js Documentation](https://discord.js.org/#/docs/main/stable/typedef/BaseMessageOptions). Variables include `%ITEM_LINK%` and `%ITEM_TITLE%` |
| `rss-feeds[x].channel` | `object` | | yes | |
| `rss-feeds[x].channel.description` | `string` | Description of the channel used to send message content | no | |
| `rss-feeds[x].channel.channel-id` | `string` | Channel used to send message content | yes | Discord channel ID |
| `rss-feeds[x].fetch-on` | `object` | | no | |
| `rss-feeds[x].fetch-on.time-zone` | `string` | Fetch on time zone | no | Time zones found in the [tz database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) |
| `rss-feeds[x].fetch-on.days-of-week` | `number[]` | Fetch on day of week | no | `0` (Sunday), `1` (Monday), `2` (Tuesday), `3` (Wednesday), `4` (Thursday), `5` (Friday), and `6` (Saturday) |
| `rss-feeds[x].fetch-on.months` | `number[]` | Fetch on month | no | From `1` to `12` |
| `rss-feeds[x].fetch-on.dates` | `number[]` | Fetch on date | no | From `1` to `31` |
| `rss-feeds[x].fetch-on.hours` | `number[]` | Fetch on hour of day | no | From `0` to `23` |
| `rss-feeds[x].fetch-on.minutes` | `number[]` | Fetch on minute of hour | no | From `0` to `59` |
| `rss-feeds[x].fetch-on.seconds` | `number[]` | Fetch on second of minute | no | From `0` to `59` |
```json
{
"rss-feeds": [
{
"name": "Sample",
"url": "https://www.example.com/feed",
"user-agent": "stonker-bot",
"follow-redirects": true,
"remove-parameters": true,
"allowed-urls": [
"https://www.example.com/news/"
],
"payload": {
"content": "Sample: %ITEM_TITLE% - %ITEM_LINK%"
},
"channel": {
"description": "Sample channel",
"channel-id": "000000000000000000"
},
"fetch-on": {
"time-zone": "Etc/UTC",
"days-of-week": [
0,
1,
2,
3,
4,
5,
6
],
"months": [
1
],
"dates": [
1
],
"hours": [
0
],
"minutes": [
0
],
"seconds": [
0
]
}
}
]
}
```
### 9. Regex Rules
Restrict a specific format and disallow specific text in a channel or the entire server. If the message matches or does not match the regular expression, the message will be deleted (unless member is a server owner, administrator, or listed under excluded roles).
_This feature can be extended with the [delete message](#2-snitch-notifications) notification._
__Note:__ Please prioritize channel restrictions before server-wide restrictions because only the first match will be considered.
| __Key__ | __Type__ | __Description__ | __Required__ | __Accepted Values__ |
|------------------------------------------------|------------|----------------------------------------------------------------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `regex-rules` | `object[]` | | no | |
| `regex-rules[x].name` | `string` | Name of the event | no | |
| `regex-rules[x].channel` | `object` | | no | |
| `regex-rules[x].channel.description` | `string` | Description of the channel used to apply regex restrictions on | no | |
| `regex-rules[x].channel.channel-id` | `string` | Channel used to apply regex restrictions on | yes | Discord channel ID |
| `regex-rules[x].match` | `boolean` | When text matches or does not match the regex | yes | `true` or `false` |
| `regex-rules[x].regex` | `object` | | yes | |
| `regex-rules[x].regex.description` | `string` | Description of the match regex | no | |
| `regex-rules[x].regex.pattern` | `string` | Regex pattern | yes | Read [Writing a regular expression pattern](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#writing_a_regular_expression_pattern) |
| `regex-rules[x].regex.flags` | `string` | Regex flags | no | Read [Advanced searching with flags](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#advanced_searching_with_flags) |
| `regex-rules[x].excluded-roles` | `object[]` | | no | |
| `regex-rules[x].excluded-roles[x].description` | `string` | Description of the excluded role | no | |
| `regex-rules[x].excluded-roles[x].role-id` | `string` | Excluded role | yes | Discord role ID |
| `regex-rules[x].direct-message-payload` | `object` | Message content to send when user does not follow regex rule | no | `BaseMessageOptions` in [discord.js Documentation](https://discord.js.org/#/docs/main/stable/typedef/BaseMessageOptions) |
```json
{
"regex-rules": [
{
"name": "Sample",
"channel": {
"description": "Sample channel",
"channel-id": "000000000000000000"
},
"match": false,
"regex": {
"description": "Sample regex",
"pattern": "(.+)",
"flags": "g"
},
"excluded-roles": [
{
"description": "Sample role",
"role-id": "000000000000000000"
}
],
"direct-message-payload": {
"content": "This type of text is not allowed in this channel!"
}
}
]
}
```
### 10. Detect Suspicious Words
Detect words in a message that may require attention. Useful when a member mentions a person of interest (without tagging them) or detection of vulgar language that often do not require warnings or deletion.
| __Key__ | __Type__ | __Description__ | __Required__ | __Accepted Values__ |
|--------------------------------------------------|------------|------------------------------------------------------------|--------------|------------------------------------------------------------------------------------------------------------------------------|
| `detect-suspicious-words` | `object` | | no | |
| `detect-suspicious-words.categories` | `object[]` | | yes | |
| `detect-suspicious-words.categories[x].category` | `string` | Name of the category | no | |
| `detect-suspicious-words.categories[x].words` | `string[]` | List of suspicious words | yes | Alphabetical variants only. Non-alphabetical conversion will be attempted. For example, "he110" will be converted to "hello" |
| `detect-suspicious-words.channel` | `object` | | yes | |
| `detect-suspicious-words.channel.description` | `string` | Description of the channel used to report suspicious words | no | |
| `detect-suspicious-words.channel.channel-id` | `string` | Channel used to report suspicious words | yes | Discord channel ID |
```json
{
"detect-suspicious-words": {
"categories": [
{
"category": "Sample",
"words": [
"suspicious",
"really suspicious"
]
}
],
"channel": {
"description": "Sample channel",
"channel-id": "000000000000000000"
}
}
}
```
### 11. Sync Roles
Add or remove selected roles from members automatically if a user has or does not have "some" roles. Useful for many scenarios, for example, when members lose a premium role (e.g. _removing_ premium add-on roles) or when members get muted (e.g. _removing_ roles purposely designed to enable sending of messages, speaking in voice channels, or creating new reactions).
__Note:__ Please prioritize role removals before role additions due to how Discord processes role changes.
| __Key__ | __Type__ | __Description__ | __Required__ | __Accepted Values__ |
|-------------------------------------------------------|------------|--------------------------------------------------|--------------|---------------------------------------------|
| `sync-roles` | `object` | | no | |
| `sync-roles.timeout` | `number` | Time to wait after the last role change | yes | Time in seconds (e.g. 1 minute equals `60`) |
| `sync-roles.events` | `object[]` | | yes | |
| `sync-roles.events[x].name` | `string` | Name of the event | no | |
| `sync-roles.events[x].some-roles` | `object[]` | | yes | |
| `sync-roles.events[x].some-roles[x].description` | `string` | Description of the role | no | |
| `sync-roles.events[x].some-roles[x].role-id` | `string` | Role | yes | Discord role ID |
| `sync-roles.events[x].has-some-roles` | `boolean` | When user has or does not have some of the roles | yes | `true` or `false` |
| `sync-roles.events[x].to-add-roles` | `object[]` | | no | |
| `sync-roles.events[x].to-add-roles[x].description` | `string` | Description of the role to add | no | |
| `sync-roles.events[x].to-add-roles[x].role-id` | `string` | Role to add | yes | Discord role ID |
| `sync-roles.events[x].to-remove-roles` | `object[]` | | no | |
| `sync-roles.events[x].to-remove-roles[x].description` | `string` | Description of the role to remove | no | |
| `sync-roles.events[x].to-remove-roles[x].role-id` | `string` | Role to remove | yes | Discord role ID |
```json
{
"sync-roles": {
"timeout": 1,
"events": [
{
"name": "Sample",
"some-roles": [
{
"description": "A role",
"role-id": "000000000000000000"
}
],
"has-some-roles": true,
"to-remove-roles": [
{
"description": "B role",
"role-id": "000000000000000000"
}
]
},
{
"name": "Sample",
"some-roles": [
{
"description": "A role",
"role-id": "000000000000000000"
}
],
"has-some-roles": false,
"to-add-roles": [
{
"description": "B role",
"role-id": "000000000000000000"
}
]
}
]
}
}
```
### 12. Role Messages
Sends out messages when a role is added to or removed from a user. Perfect for social proof, welcoming new members, and internal analytics!
| __Key__ | __Type__ | __Description__ | __Required__ | __Accepted Values__ |
|----------------------------------------|------------|------------------------------------------------------------------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `role-messages` | `object[]` | | no | |
| `role-messages[x].name` | `string` | Name of the event | no | |
| `role-messages[x].role` | `object` | | yes | |
| `role-messages[x].role.description` | `string` | Description of the role | no | |
| `role-messages[x].role.role-id` | `string` | Role | yes | Discord role ID |
| `role-messages[x].direction` | `string` | When user obtains a role or relinquishes a role | yes | `add` or `remove` |
| `role-messages[x].payload` | `object` | Message content to send when user obtains or relinquishes a role | yes | `BaseMessageOptions` in [disco