mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-15 19:13:31 +01:00
feat(guide): port legacy guide (#10938)
* feat: initial attempt at porting legacy guide * feat: completion of legacy guide backport * chore: lockfile shenanigans * fix: handle svgs * fix: replace svg with mermaid integration * chore: format * chore: remove unnecssary bullet * chore: cleanup code highlights * chore: explicit return * chore: move display components after interactive components in sidebar * chore: voice * top link should be installation * add docs link to sidebar * feat: subguide-based accent styles * chore: don't list faq twice * chore: mention display components in interactive components * fix: remove unoccs/order rule from guide * chore: redirect to legacy guide instead of /guide root * refactor: use `<kbd>` * refactor: more kbd use * Update apps/guide/content/docs/legacy/app-creation/handling-events.mdx Co-authored-by: Naiyar <137700126+imnaiyar@users.noreply.github.com> * chore: fix typos Co-authored-by: Qjuh <76154676+Qjuh@users.noreply.github.com> * chore: fix typos * chore: fix links regarding secret stores across coding platforms * chore: fix typo * chore: link node method directly Co-authored-by: Qjuh <76154676+Qjuh@users.noreply.github.com> * chore: typos Co-authored-by: Vlad Frangu <me@vladfrangu.dev> * chore: typo Co-authored-by: Vlad Frangu <me@vladfrangu.dev> * fix: prevent v14 changes from being listed twice * chore: prefer relative links * chore: missed link conversion * chore: missed link conversion * chore: fix link * chore: remove legacy code highlight markers * chore: rephrase and extend contributing guidelines * feat(setup): suggest cli flag over dotenv package * chore: move introduction in sidebar better navigation experience if the 'next page' in intro refers to getting started vs. updating/faq * fix: replace outdated link * fix: update voice dependencies * chore: update node install instructions * fix: list in missing access callout * chore: match bun env file format * chore: restore ffmpeg disclaimer * fix: lockfile conflict * chore: action row typo Co-authored-by: Vlad Frangu <me@vladfrangu.dev> * chore: no longer use at-next for pino --------- Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com> Co-authored-by: Qjuh <76154676+Qjuh@users.noreply.github.com> Co-authored-by: Naiyar <137700126+imnaiyar@users.noreply.github.com> Co-authored-by: Vlad Frangu <me@vladfrangu.dev>
This commit is contained in:
194
apps/guide/content/docs/legacy/keyv/keyv.mdx
Normal file
194
apps/guide/content/docs/legacy/keyv/keyv.mdx
Normal file
@@ -0,0 +1,194 @@
|
||||
---
|
||||
title: Keyv
|
||||
---
|
||||
|
||||
[Keyv](https://www.npmjs.com/package/keyv) is a simple key-value store that works with multiple backends. It's fully scalable for [sharding](../sharding/) and supports JSON storage.
|
||||
|
||||
## Installation
|
||||
|
||||
```sh tab="npm"
|
||||
npm install keyv
|
||||
```
|
||||
|
||||
```sh tab="yarn"
|
||||
yarn add keyv
|
||||
```
|
||||
|
||||
```sh tab="pnpm"
|
||||
pnpm add keyv
|
||||
```
|
||||
|
||||
```sh tab="bun"
|
||||
bun add keyv
|
||||
```
|
||||
|
||||
Keyv requires an additional package depending on which persistent backend you would prefer to use. If you want to keep everything in memory, you can skip this part. Otherwise, install one of the below.
|
||||
|
||||
```sh tab="npm"
|
||||
npm install @keyv/redis
|
||||
npm install @keyv/mongo
|
||||
npm install @keyv/sqlite
|
||||
npm install @keyv/postgres
|
||||
npm install @keyv/mysql
|
||||
```
|
||||
|
||||
```sh tab="yarn"
|
||||
yarn add @keyv/redis
|
||||
yarn add @keyv/mongo
|
||||
yarn add @keyv/sqlite
|
||||
yarn add @keyv/postgres
|
||||
yarn add @keyv/mysql
|
||||
```
|
||||
|
||||
```sh tab="pnpm"
|
||||
pnpm add @keyv/redis
|
||||
pnpm add @keyv/mongo
|
||||
pnpm add @keyv/sqlite
|
||||
pnpm add @keyv/postgres
|
||||
pnpm add @keyv/mysql
|
||||
```
|
||||
|
||||
```sh tab="bun"
|
||||
bun add @keyv/redis
|
||||
bun add @keyv/mongo
|
||||
bun add @keyv/sqlite
|
||||
bun add @keyv/postgres
|
||||
bun add @keyv/mysql
|
||||
```
|
||||
|
||||
Create an instance of Keyv once you've installed Keyv and any necessary drivers.
|
||||
|
||||
```js
|
||||
const { Keyv } = require('keyv');
|
||||
|
||||
// One of the following
|
||||
const keyv = new Keyv(); // for in-memory storage
|
||||
const keyv = new Keyv('redis://user:pass@localhost:6379');
|
||||
const keyv = new Keyv('mongodb://user:pass@localhost:27017/dbname');
|
||||
const keyv = new Keyv('sqlite://path/to/database.sqlite');
|
||||
const keyv = new Keyv('postgresql://user:pass@localhost:5432/dbname');
|
||||
const keyv = new Keyv('mysql://user:pass@localhost:3306/dbname');
|
||||
```
|
||||
|
||||
Make sure to handle connection errors.
|
||||
|
||||
```js
|
||||
keyv.on('error', (err) => console.error('Keyv connection error:', err));
|
||||
```
|
||||
|
||||
For a more detailed setup, check out the [Keyv readme](https://github.com/jaredwray/keyv/tree/main/packages/keyv).
|
||||
|
||||
## Usage
|
||||
|
||||
Keyv exposes a familiar [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)-like API. However, it only has `set`, `get`, `delete`, and `clear` methods. Additionally, instead of immediately returning data, these methods return [Promises](../additional-info/async-await) that resolve with the data.
|
||||
|
||||
```js
|
||||
(async () => {
|
||||
// true
|
||||
await keyv.set('foo', 'bar');
|
||||
|
||||
// bar
|
||||
await keyv.get('foo');
|
||||
|
||||
// undefined
|
||||
await keyv.clear();
|
||||
|
||||
// undefined
|
||||
await keyv.get('foo');
|
||||
})();
|
||||
```
|
||||
|
||||
## Application
|
||||
|
||||
Although Keyv can assist in any scenario where you need key-value data, we will focus on setting up a per-guild prefix configuration using [Sqlite](https://www.sqlite.org/).
|
||||
|
||||
<Callout>
|
||||
This section will still work with any provider supported by Keyv. We recommend PostgreSQL for larger applications.
|
||||
|
||||
Do note that "large" here should be interpreted as absolutely massive. Sqlite is used at scale by many companies and products you use every single day. The slight overhead should not be noticable for the application of a Discord bot at all unless you are dealing with super complicated queries or are using specific features that do not exist in sqlite.
|
||||
|
||||
You can find out if sqlite might be a good choice for your project (it very likely is) by reading [their own article](https://www.sqlite.org/whentouse.html) on the topic.
|
||||
|
||||
</Callout>
|
||||
|
||||
### Setup
|
||||
|
||||
```js
|
||||
const { Keyv } = require('keyv');
|
||||
const { Client, Events, GatewayIntentBits } = require('discord.js');
|
||||
const { globalPrefix, token } = require('./config.json');
|
||||
|
||||
const client = new Client({
|
||||
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent],
|
||||
});
|
||||
const prefixes = new Keyv('sqlite://path/to.sqlite');
|
||||
```
|
||||
|
||||
### Command handler
|
||||
|
||||
<Callout type="warn">
|
||||
This guide example is from a time where parsing the message content of Discord messages was the only option for
|
||||
commands. We have since moved on from this and recommend you do the same with [slash
|
||||
commands](../app-creation/handling-commands). It can still serve as an example for using databases in a more
|
||||
integrated example. We hope it can help you understand the core idea and apply it to your own use cases!
|
||||
</Callout>
|
||||
|
||||
```js
|
||||
client.on(Events.MessageCreate, async (message) => {
|
||||
if (message.author.bot) return;
|
||||
|
||||
let args;
|
||||
// handle messages in a guild
|
||||
if (message.guild) {
|
||||
let prefix;
|
||||
|
||||
if (message.content.startsWith(globalPrefix)) {
|
||||
prefix = globalPrefix;
|
||||
} else {
|
||||
// check the guild-level prefix
|
||||
const guildPrefix = await prefixes.get(message.guild.id);
|
||||
if (message.content.startsWith(guildPrefix)) prefix = guildPrefix;
|
||||
}
|
||||
|
||||
// if we found a prefix, setup args; otherwise, this isn't a command
|
||||
if (!prefix) return;
|
||||
args = message.content.slice(prefix.length).trim().split(/\s+/);
|
||||
} else {
|
||||
// handle DMs
|
||||
const slice = message.content.startsWith(globalPrefix) ? globalPrefix.length : 0;
|
||||
args = message.content.slice(slice).split(/\s+/);
|
||||
}
|
||||
|
||||
// get the first space-delimited argument after the prefix as the command
|
||||
const command = args.shift().toLowerCase();
|
||||
});
|
||||
```
|
||||
|
||||
### Prefix command
|
||||
|
||||
Now that you have a command handler, you can make a command to allow people to use your prefix system.
|
||||
|
||||
```js
|
||||
client.on(Events.MessageCreate, async (message) => {
|
||||
// ...
|
||||
if (command === 'prefix') {
|
||||
// if there's at least one argument, set the prefix
|
||||
if (args.length) {
|
||||
await prefixes.set(message.guild.id, args[0]);
|
||||
return message.channel.send(`Successfully set prefix to \`${args[0]}\``);
|
||||
}
|
||||
|
||||
return message.channel.send(`Prefix is \`${(await prefixes.get(message.guild.id)) || globalPrefix}\``);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
<Callout>
|
||||
You will probably want to set up additional validation, such as required permissions and maximum prefix length.
|
||||
</Callout>
|
||||
|
||||
## Next steps
|
||||
|
||||
Various other applications can use Keyv, such as guild settings; create another instance with a different [namespace](https://github.com/jaredwray/keyv/tree/main/packages/keyv#namespaces) for each setting. Additionally, it can be [extended](https://github.com/jaredwray/keyv/tree/main/packages/keyv#third-party-storage-adapters) to work with whatever storage backend you prefer.
|
||||
|
||||
Check out the [Keyv repository](https://github.com/jaredwray/keyv/tree/main/packages/keyv) for more information.
|
||||
Reference in New Issue
Block a user