mirror of
https://github.com/discordeno/discordeno.git
synced 2026-05-21 02:40:08 +00:00
Feat: Website Rewrite (#2996)
* Feat: Remake website * update yarn.lock --------- Co-authored-by: Peter Hanania <peter@pogy.xyz> Co-authored-by: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com>
This commit is contained in:
14
website/.eslintrc.yml
Normal file
14
website/.eslintrc.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
env:
|
||||
browser: true
|
||||
es2021: true
|
||||
extends:
|
||||
- plugin:react/recommended
|
||||
- standard-with-typescript
|
||||
- prettier
|
||||
overrides: []
|
||||
parserOptions:
|
||||
ecmaVersion: latest
|
||||
sourceType: module
|
||||
plugins:
|
||||
- react
|
||||
rules: {}
|
||||
1
website/.gitignore
vendored
1
website/.gitignore
vendored
@@ -18,3 +18,4 @@
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.vscode
|
||||
5
website/.prettierrc
Normal file
5
website/.prettierrc
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"arrowParens": "avoid"
|
||||
}
|
||||
@@ -51,7 +51,7 @@ const app = express()
|
||||
app.use(
|
||||
express.urlencoded({
|
||||
extended: true,
|
||||
}),
|
||||
})
|
||||
)
|
||||
|
||||
app.use(express.json())
|
||||
@@ -62,7 +62,11 @@ app.all('/*', async (req, res) => {
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await REST.makeRequest(req.method, `${REST.baseUrl}${req.url}`, req.body)
|
||||
const result = await REST.makeRequest(
|
||||
req.method,
|
||||
`${REST.baseUrl}${req.url}`,
|
||||
req.body
|
||||
)
|
||||
|
||||
if (result) {
|
||||
res.status(200).json(result)
|
||||
@@ -103,7 +107,10 @@ const INFLUX_BUCKET = process.env.INFLUX_BUCKET as string
|
||||
const INFLUX_TOKEN = process.env.INFLUX_TOKEN as string
|
||||
const INFLUX_URL = process.env.INFLUX_URL as string
|
||||
|
||||
export const influxDB = INFLUX_URL && INFLUX_TOKEN ? new InfluxDB({ url: INFLUX_URL, token: INFLUX_TOKEN }) : undefined
|
||||
export const influxDB =
|
||||
INFLUX_URL && INFLUX_TOKEN
|
||||
? new InfluxDB({ url: INFLUX_URL, token: INFLUX_TOKEN })
|
||||
: undefined
|
||||
export const Influx = influxDB?.getWriteApi(INFLUX_ORG, INFLUX_BUCKET)
|
||||
|
||||
let savingAnalyticsId: NodeJS.Interval | undefined = undefined
|
||||
@@ -114,7 +121,7 @@ if (!saveAnalyticsId) {
|
||||
.then(() => {
|
||||
console.log(`[Influx - REST] Saved events!`)
|
||||
})
|
||||
.catch((error) => {
|
||||
.catch(error => {
|
||||
console.log(`[Influx - REST] Error saving events!`, error)
|
||||
})
|
||||
// Every 30seconds
|
||||
@@ -131,7 +138,11 @@ import { Influx } from './analytics.ts'
|
||||
Now, make sure to scroll to this line as we are going to work around this line now.
|
||||
|
||||
```ts
|
||||
const result = await REST.makeRequest(req.method, `${REST.baseUrl}${req.url}`, req.body)
|
||||
const result = await REST.makeRequest(
|
||||
req.method,
|
||||
`${REST.baseUrl}${req.url}`,
|
||||
req.body
|
||||
)
|
||||
```
|
||||
|
||||
```ts
|
||||
@@ -141,9 +152,13 @@ Influx?.writePoint(
|
||||
.stringField('type', 'REQUEST_FETCHING')
|
||||
.tag('method', options.method)
|
||||
.tag('url', options.url)
|
||||
.tag('bucket', options.bucketId ?? 'NA'),
|
||||
.tag('bucket', options.bucketId ?? 'NA')
|
||||
)
|
||||
const result = await REST.makeRequest(
|
||||
req.method,
|
||||
`${REST.baseUrl}${req.url}`,
|
||||
req.body
|
||||
)
|
||||
const result = await REST.makeRequest(req.method, `${REST.baseUrl}${req.url}`, req.body)
|
||||
```
|
||||
|
||||
This will add to the analytics whenever a request comes in. Then we should add another one for when a request is successful.
|
||||
@@ -155,9 +170,13 @@ Influx?.writePoint(
|
||||
.stringField('type', 'REQUEST_FETCHING')
|
||||
.tag('method', options.method)
|
||||
.tag('url', options.url)
|
||||
.tag('bucket', options.bucketId ?? 'NA'),
|
||||
.tag('bucket', options.bucketId ?? 'NA')
|
||||
)
|
||||
const result = await REST.makeRequest(
|
||||
req.method,
|
||||
`${REST.baseUrl}${req.url}`,
|
||||
req.body
|
||||
)
|
||||
const result = await REST.makeRequest(req.method, `${REST.baseUrl}${req.url}`, req.body)
|
||||
Influx?.writePoint(
|
||||
new Point('restEvents')
|
||||
.timestamp(new Date())
|
||||
@@ -166,7 +185,7 @@ Influx?.writePoint(
|
||||
.tag('url', options.url)
|
||||
.tag('bucket', options.bucketId ?? 'NA')
|
||||
.intField('status', response.status)
|
||||
.tag('statusText', response.statusText),
|
||||
.tag('statusText', response.statusText)
|
||||
)
|
||||
```
|
||||
|
||||
@@ -280,9 +299,18 @@ const bot = createBot({
|
||||
} catch (err) {
|
||||
value = err
|
||||
}
|
||||
response.push(util.inspect(value, inspectOptions).replace(regex, 'YOU WISH!').substring(0, 1985))
|
||||
response.push(
|
||||
util
|
||||
.inspect(value, inspectOptions)
|
||||
.replace(regex, 'YOU WISH!')
|
||||
.substring(0, 1985)
|
||||
)
|
||||
} else {
|
||||
response.push(String(util.inspect(result)).replace(regex, 'YOU WISH!').substring(0, 1985))
|
||||
response.push(
|
||||
String(util.inspect(result))
|
||||
.replace(regex, 'YOU WISH!')
|
||||
.substring(0, 1985)
|
||||
)
|
||||
}
|
||||
|
||||
response.push('```')
|
||||
|
||||
@@ -90,7 +90,7 @@ const app = express()
|
||||
app.use(
|
||||
express.urlencoded({
|
||||
extended: true,
|
||||
}),
|
||||
})
|
||||
)
|
||||
|
||||
app.use(express.json())
|
||||
@@ -107,8 +107,12 @@ app.all('/*', async (req, res) => {
|
||||
return await GATEWAY.requestMembers(req.body.guildId, req.body.options)
|
||||
}
|
||||
default:
|
||||
logger.error(`[Shard] Unknown request received. ${JSON.stringify(req.body)}`)
|
||||
return res.status(404).json({ message: 'Unknown request received.', status: 404 })
|
||||
logger.error(
|
||||
`[Shard] Unknown request received. ${JSON.stringify(req.body)}`
|
||||
)
|
||||
return res
|
||||
.status(404)
|
||||
.json({ message: 'Unknown request received.', status: 404 })
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.log(error)
|
||||
@@ -136,7 +140,10 @@ export const GATEWAY = createGatewayManager({
|
||||
|
||||
GATEWAY.tellWorkerToIdentify = async function (workerId, shardId, bucketId) {
|
||||
const url = process.env[`SERVER_URL_${workerId}`]
|
||||
if (!url) return logger.error(`No server URL found for server #${workerId}. Unable to start Shard #${shardId}`)
|
||||
if (!url)
|
||||
return logger.error(
|
||||
`No server URL found for server #${workerId}. Unable to start Shard #${shardId}`
|
||||
)
|
||||
|
||||
await fetch(url, {
|
||||
method: 'POST',
|
||||
@@ -145,7 +152,7 @@ GATEWAY.tellWorkerToIdentify = async function (workerId, shardId, bucketId) {
|
||||
},
|
||||
body: JSON.stringify({ type: 'IDENTIFY_SHARD', shardId }),
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then(res => res.json())
|
||||
.catch(logger.error)
|
||||
}
|
||||
|
||||
@@ -182,7 +189,7 @@ const app = express()
|
||||
app.use(
|
||||
express.urlencoded({
|
||||
extended: true,
|
||||
}),
|
||||
})
|
||||
)
|
||||
|
||||
app.use(express.json())
|
||||
@@ -203,7 +210,11 @@ app.all('/*', async (req, res) => {
|
||||
// Identify A Shard
|
||||
switch (req.body.type) {
|
||||
case 'IDENTIFY_SHARD': {
|
||||
logger.info(`[Shard] identifying ${SHARDS.has(req.body.shardId) ? 'existing' : 'new'} shard (${req.body.shardId})`)
|
||||
logger.info(
|
||||
`[Shard] identifying ${
|
||||
SHARDS.has(req.body.shardId) ? 'existing' : 'new'
|
||||
} shard (${req.body.shardId})`
|
||||
)
|
||||
const shard =
|
||||
SHARDS.get(req.body.shardId) ??
|
||||
new DiscordenoShard({
|
||||
@@ -230,8 +241,12 @@ app.all('/*', async (req, res) => {
|
||||
})
|
||||
}
|
||||
default:
|
||||
logger.error(`[Shard] Unknown request received. ${JSON.stringify(req.body)}`)
|
||||
return res.status(404).json({ message: 'Unknown request received.', status: 404 })
|
||||
logger.error(
|
||||
`[Shard] Unknown request received. ${JSON.stringify(req.body)}`
|
||||
)
|
||||
return res
|
||||
.status(404)
|
||||
.json({ message: 'Unknown request received.', status: 404 })
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.log(error)
|
||||
@@ -267,10 +282,13 @@ const shard =
|
||||
async message(shrd, payload) {
|
||||
await fetch(getUrlFromShardId(req.body.totalShards, shrd.id), {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', authorization: AUTHORIZATION },
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
authorization: AUTHORIZATION,
|
||||
},
|
||||
body: JSON.stringify({ payload, shardId }),
|
||||
})
|
||||
.then((res) => res.text())
|
||||
.then(res => res.text())
|
||||
.catch(logger.error)
|
||||
},
|
||||
},
|
||||
@@ -297,7 +315,10 @@ const INFLUX_BUCKET = process.env.INFLUX_BUCKET as string
|
||||
const INFLUX_TOKEN = process.env.INFLUX_TOKEN as string
|
||||
const INFLUX_URL = process.env.INFLUX_URL as string
|
||||
|
||||
export const influxDB = INFLUX_URL && INFLUX_TOKEN ? new InfluxDB({ url: INFLUX_URL, token: INFLUX_TOKEN }) : undefined
|
||||
export const influxDB =
|
||||
INFLUX_URL && INFLUX_TOKEN
|
||||
? new InfluxDB({ url: INFLUX_URL, token: INFLUX_TOKEN })
|
||||
: undefined
|
||||
export const Influx = influxDB?.getWriteApi(INFLUX_ORG, INFLUX_BUCKET)
|
||||
|
||||
let savingAnalyticsId: NodeJS.Interval | undefined = undefined
|
||||
@@ -308,7 +329,7 @@ if (!saveAnalyticsId) {
|
||||
.then(() => {
|
||||
console.log(`[Influx - Gateway] Saved events!`)
|
||||
})
|
||||
.catch((error) => {
|
||||
.catch(error => {
|
||||
console.log(`[Influx - Gateway] Error saving events!`, error)
|
||||
})
|
||||
// Every 15 seconds
|
||||
|
||||
@@ -83,7 +83,7 @@ const app = express()
|
||||
app.use(
|
||||
express.urlencoded({
|
||||
extended: true,
|
||||
}),
|
||||
})
|
||||
)
|
||||
|
||||
app.use(express.json())
|
||||
|
||||
@@ -39,73 +39,74 @@ logger.info(`[Startup] Bot started successfully.`)
|
||||
## Creating A Reaction Role
|
||||
|
||||
We need to create the `/roles` command. To do this, let's make a new file `src/commands/roles.ts`. First, let's go ahead and create a command object in here and export it so we can use it later.
|
||||
|
||||
```ts
|
||||
export const command = {};
|
||||
|
||||
export default command;
|
||||
```ts
|
||||
export const command = {}
|
||||
|
||||
export default command
|
||||
```
|
||||
|
||||
Now we can add the command type to this object, to give us the ability to have typescript help us autocomplete some stuff.
|
||||
|
||||
```ts
|
||||
import { CreateApplicationCommand } from '@discordeno/types';
|
||||
import { CreateApplicationCommand } from '@discordeno/types'
|
||||
|
||||
export const command: CreateApplicationCommand = {};
|
||||
export const command: CreateApplicationCommand = {}
|
||||
```
|
||||
|
||||
By now, you should be seeing some TypeScript errors so let's fix that.
|
||||
|
||||
```ts
|
||||
import { CreateApplicationCommand } from '@discordeno/types';
|
||||
import { CreateApplicationCommand } from '@discordeno/types'
|
||||
|
||||
export const command: CreateApplicationCommand = {
|
||||
name: "roles",
|
||||
description: "Role management on your server.",
|
||||
options: []
|
||||
};
|
||||
name: 'roles',
|
||||
description: 'Role management on your server.',
|
||||
options: [],
|
||||
}
|
||||
```
|
||||
|
||||
### Preparing Subcommands
|
||||
|
||||
Nice, so we now have our basic command, `/roles` ready. Next, we should prepare our `/roles reactions` subcommand here.
|
||||
|
||||
```ts
|
||||
export const command: CreateApplicationCommand = {
|
||||
name: "roles",
|
||||
description: "Role management on your server.",
|
||||
options: [
|
||||
{
|
||||
name: "reactions",
|
||||
description: "Manage the role reactions on your server.",
|
||||
// If you add more subcommand groups in future, this would need to be false
|
||||
required: true,
|
||||
type: ApplicationCommandOptionTypes.SubCommandGroup,
|
||||
options: []
|
||||
}
|
||||
]
|
||||
};
|
||||
name: 'roles',
|
||||
description: 'Role management on your server.',
|
||||
options: [
|
||||
{
|
||||
name: 'reactions',
|
||||
description: 'Manage the role reactions on your server.',
|
||||
// If you add more subcommand groups in future, this would need to be false
|
||||
required: true,
|
||||
type: ApplicationCommandOptionTypes.SubCommandGroup,
|
||||
options: [],
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
Now that the `/roles reactions` is complete, we should add the `/roles reactions create` command.
|
||||
|
||||
```ts
|
||||
options: [
|
||||
{
|
||||
name: "reactions",
|
||||
description: "Manage the role reactions on your server.",
|
||||
// If you add more subcommand groups in future, this would need to be false
|
||||
required: true,
|
||||
type: ApplicationCommandOptionTypes.SubCommandGroup,
|
||||
options: [
|
||||
{
|
||||
name: "create",
|
||||
description: "Create a reaction role on your server.",
|
||||
required: false,
|
||||
type: ApplicationCommandOptionTypes.SubCommand,
|
||||
options: []
|
||||
}
|
||||
]
|
||||
}
|
||||
{
|
||||
name: 'reactions',
|
||||
description: 'Manage the role reactions on your server.',
|
||||
// If you add more subcommand groups in future, this would need to be false
|
||||
required: true,
|
||||
type: ApplicationCommandOptionTypes.SubCommandGroup,
|
||||
options: [
|
||||
{
|
||||
name: 'create',
|
||||
description: 'Create a reaction role on your server.',
|
||||
required: false,
|
||||
type: ApplicationCommandOptionTypes.SubCommand,
|
||||
options: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
@@ -201,54 +202,60 @@ The final option to add to this is the label option.
|
||||
Nice. So far your code should look something like this:
|
||||
|
||||
```ts
|
||||
import { CreateApplicationCommand, ApplicationCommandOptionTypes, ButtonStyles } from '@discordeno/types';
|
||||
import {
|
||||
CreateApplicationCommand,
|
||||
ApplicationCommandOptionTypes,
|
||||
ButtonStyles,
|
||||
} from '@discordeno/types'
|
||||
|
||||
const command: CreateApplicationCommand = {
|
||||
name: "roles",
|
||||
description: "Role management on your server.",
|
||||
options: [
|
||||
name: 'roles',
|
||||
description: 'Role management on your server.',
|
||||
options: [
|
||||
{
|
||||
name: 'reactions',
|
||||
description: 'Manage the role reactions on your server.',
|
||||
// If you add more subcommand groups in future, this would need to be false
|
||||
required: true,
|
||||
type: ApplicationCommandOptionTypes.SubCommandGroup,
|
||||
options: [
|
||||
{
|
||||
name: "reactions",
|
||||
description: "Manage the role reactions on your server.",
|
||||
// If you add more subcommand groups in future, this would need to be false
|
||||
required: true,
|
||||
type: ApplicationCommandOptionTypes.SubCommandGroup,
|
||||
options: [
|
||||
{
|
||||
name: "create",
|
||||
description: "Create a reaction role on your server.",
|
||||
required: false,
|
||||
type: ApplicationCommandOptionTypes.SubCommand,
|
||||
options: [
|
||||
{
|
||||
required: true,
|
||||
name: "emoji",
|
||||
description: "What would you like to set as this button's emoji?",
|
||||
type: ApplicationCommandOptionTypes.String,
|
||||
},
|
||||
{
|
||||
required: true,
|
||||
name: "color",
|
||||
description: "What color would you like to set as this button's color?",
|
||||
type: ApplicationCommandOptionTypes.Integer,
|
||||
choices: [
|
||||
{ name: "Blue", value: ButtonStyles.Primary },
|
||||
{ name: "Green", value: ButtonStyles.Success },
|
||||
{ name: "Grey", value: ButtonStyles.Secondary },
|
||||
{ name: "Red", value: ButtonStyles.Danger },
|
||||
],
|
||||
},
|
||||
{
|
||||
required: false,
|
||||
name: "label",
|
||||
description: "What would you like to set for the name on this button?",
|
||||
type: ApplicationCommandOptionTypes.String,
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
name: 'create',
|
||||
description: 'Create a reaction role on your server.',
|
||||
required: false,
|
||||
type: ApplicationCommandOptionTypes.SubCommand,
|
||||
options: [
|
||||
{
|
||||
required: true,
|
||||
name: 'emoji',
|
||||
description: "What would you like to set as this button's emoji?",
|
||||
type: ApplicationCommandOptionTypes.String,
|
||||
},
|
||||
{
|
||||
required: true,
|
||||
name: 'color',
|
||||
description:
|
||||
"What color would you like to set as this button's color?",
|
||||
type: ApplicationCommandOptionTypes.Integer,
|
||||
choices: [
|
||||
{ name: 'Blue', value: ButtonStyles.Primary },
|
||||
{ name: 'Green', value: ButtonStyles.Success },
|
||||
{ name: 'Grey', value: ButtonStyles.Secondary },
|
||||
{ name: 'Red', value: ButtonStyles.Danger },
|
||||
],
|
||||
},
|
||||
{
|
||||
required: false,
|
||||
name: 'label',
|
||||
description:
|
||||
'What would you like to set for the name on this button?',
|
||||
type: ApplicationCommandOptionTypes.String,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
@@ -261,9 +268,7 @@ Whenever you write a little bit of code, stop and test to make sure it does what
|
||||
Now, we should take a minute to test this code out. However, this code as is does nothing it is just a file that exports an object. Let's make it so that whenever we start our bot, it will create this command for us on our test server. Go back to your index file where you created your bot.
|
||||
|
||||
```ts
|
||||
await bot.rest.upsertGuildApplicationCommands("1234", [
|
||||
roles,
|
||||
])
|
||||
await bot.rest.upsertGuildApplicationCommands('1234', [roles])
|
||||
|
||||
logger.info(`[Startup] Starting bot.`)
|
||||
await bot.start()
|
||||
@@ -272,7 +277,7 @@ await bot.start()
|
||||
Once you have added that line above, you need to make 2 small changes. The first change is to stop TypeScript from warning you that `roles` does not exist. Let's import roles at the top of the file
|
||||
|
||||
```ts
|
||||
import roles from './src/commands/roles.js';
|
||||
import roles from './src/commands/roles.js'
|
||||
```
|
||||
|
||||
The second thing is that we need to replace the `1234` with your server's guild id where you will be testing. This will make it so that we update any commands whenever the bot is started.
|
||||
@@ -282,21 +287,21 @@ The second thing is that we need to replace the `1234` with your server's guild
|
||||
Let's take a minute to refactor the code a little before we proceed further. Make a file called `src/commands/index.ts`.
|
||||
|
||||
```ts
|
||||
import { CreateApplicationCommand } from '@discordeno/types';
|
||||
import roles from './roles.js';
|
||||
import { CreateApplicationCommand } from '@discordeno/types'
|
||||
import roles from './roles.js'
|
||||
|
||||
export const commands = new Map<string, CreateApplicationCommand>([
|
||||
roles,
|
||||
].map((cmd) => [cmd.name, cmd]))
|
||||
export const commands = new Map<string, CreateApplicationCommand>(
|
||||
[roles].map(cmd => [cmd.name, cmd])
|
||||
)
|
||||
|
||||
export default commands;
|
||||
export default commands
|
||||
```
|
||||
|
||||
Now back in your index file with your bot, let's make use of this map.
|
||||
|
||||
```ts
|
||||
// This id should reflect your server id by now
|
||||
await bot.rest.upsertGuildApplicationCommands("1234", [...commands.values()]);
|
||||
await bot.rest.upsertGuildApplicationCommands('1234', [...commands.values()])
|
||||
```
|
||||
|
||||
Also make sure to change the import at the top of the file.
|
||||
@@ -313,36 +318,38 @@ Go ahead and start your bot, you will see the command is available on your serve
|
||||
Let's make 2 very small files first. `src/events/index.ts` and `src/events/interactionCreate.ts`. Go to the `interactionCreate` file first.
|
||||
|
||||
```ts
|
||||
import commands from "../commands/index.js";
|
||||
import { commandOptionsParser } from '@discordeno/utils';
|
||||
import commands from '../commands/index.js'
|
||||
import { commandOptionsParser } from '@discordeno/utils'
|
||||
|
||||
export const event: EventHandlers["interactionCreate"] = async function(interaction) {
|
||||
if (interaction.type === InteractionTypes.ApplicationCommand) {
|
||||
if (!interaction.data) return;
|
||||
export const event: EventHandlers['interactionCreate'] = async function (
|
||||
interaction
|
||||
) {
|
||||
if (interaction.type === InteractionTypes.ApplicationCommand) {
|
||||
if (!interaction.data) return
|
||||
|
||||
const command = commands.get(interaction.data.name);
|
||||
if (!command) return;
|
||||
const command = commands.get(interaction.data.name)
|
||||
if (!command) return
|
||||
|
||||
await command.execute(interaction, commandOptionsParser(interaction));
|
||||
}
|
||||
await command.execute(interaction, commandOptionsParser(interaction))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
At this point, we are seeing an error from TypeScript, that the `command` does not have an `.execute()` handler. To add this we need to customize our command just a little bit. Let's make a interface for a custom Command object. Go to `src/commands/index.ts`
|
||||
|
||||
```ts
|
||||
import { CreateApplicationCommand, Interaction } from '@discordeno/types';
|
||||
import roles from './roles.js';
|
||||
import { CreateApplicationCommand, Interaction } from '@discordeno/types'
|
||||
import roles from './roles.js'
|
||||
|
||||
export const commands = new Map<string, CreateApplicationCommand>([
|
||||
roles,
|
||||
].map((cmd) => [cmd.name, cmd]))
|
||||
export const commands = new Map<string, CreateApplicationCommand>(
|
||||
[roles].map(cmd => [cmd.name, cmd])
|
||||
)
|
||||
|
||||
export default commands;
|
||||
export default commands
|
||||
|
||||
export interface Command extends CreateApplicationCommand {
|
||||
/** Handler that will be executed when this command is triggered */
|
||||
execute(interaction: Interaction, args: Record<string, any>): Promise<any>;
|
||||
/** Handler that will be executed when this command is triggered */
|
||||
execute(interaction: Interaction, args: Record<string, any>): Promise<any>
|
||||
}
|
||||
```
|
||||
|
||||
@@ -355,17 +362,19 @@ export const commands = new Map<string, Command>([
|
||||
Next we should edit the command file at `src/commands/role.ts` and edit it to have an execute handler.
|
||||
|
||||
```ts
|
||||
import { CreateApplicationCommand, ApplicationCommandOptionTypes, ButtonStyles } from '@discordeno/types';
|
||||
import {
|
||||
CreateApplicationCommand,
|
||||
ApplicationCommandOptionTypes,
|
||||
ButtonStyles,
|
||||
} from '@discordeno/types'
|
||||
|
||||
const command: CreateApplicationCommand = {
|
||||
name: "roles",
|
||||
description: "Role management on your server.",
|
||||
options: [
|
||||
// Lot's of options here...
|
||||
],
|
||||
async execute(interaction, args) {
|
||||
|
||||
}
|
||||
name: 'roles',
|
||||
description: 'Role management on your server.',
|
||||
options: [
|
||||
// Lot's of options here...
|
||||
],
|
||||
async execute(interaction, args) {},
|
||||
}
|
||||
```
|
||||
|
||||
@@ -378,4 +387,4 @@ import { Command } from './index.js';
|
||||
const command: Command = {
|
||||
```
|
||||
|
||||
Now that this is complete we should go
|
||||
Now that this is complete we should go
|
||||
|
||||
@@ -43,16 +43,18 @@ const config = {
|
||||
sidebarPath: require.resolve('./sidebars.js'),
|
||||
// Please change this to your repo.
|
||||
// Remove this to remove the "edit this page" links.
|
||||
editUrl: 'https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/',
|
||||
editUrl:
|
||||
'https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/',
|
||||
},
|
||||
blog: {
|
||||
showReadingTime: true,
|
||||
// Please change this to your repo.
|
||||
// Remove this to remove the "edit this page" links.
|
||||
editUrl: 'https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/',
|
||||
editUrl:
|
||||
'https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/',
|
||||
},
|
||||
theme: {
|
||||
customCss: require.resolve('./src/css/custom.css'),
|
||||
customCss: require.resolve('./src/styling/index.css'),
|
||||
},
|
||||
}),
|
||||
],
|
||||
@@ -66,7 +68,7 @@ const config = {
|
||||
navbar: {
|
||||
title: 'Discordeno',
|
||||
logo: {
|
||||
alt: 'My Site Logo',
|
||||
alt: 'Discordeno Logo',
|
||||
src: 'img/logo.svg',
|
||||
},
|
||||
items: [
|
||||
@@ -90,7 +92,7 @@ const config = {
|
||||
],
|
||||
},
|
||||
footer: {
|
||||
style: 'dark',
|
||||
style: 'light',
|
||||
links: [
|
||||
{
|
||||
title: 'Docs',
|
||||
|
||||
16379
website/package-lock.json
generated
Normal file
16379
website/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -12,7 +12,9 @@
|
||||
"serve": "docusaurus serve",
|
||||
"write-translations": "docusaurus write-translations",
|
||||
"write-heading-ids": "docusaurus write-heading-ids",
|
||||
"typecheck": "tsc"
|
||||
"typecheck": "tsc",
|
||||
"lint": "eslint src --ext ts,tsx",
|
||||
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,md,mdx}\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/plugin-syntax-flow": "^7.18.6",
|
||||
@@ -20,17 +22,29 @@
|
||||
"@docusaurus/preset-classic": "2.3.1",
|
||||
"@easyops-cn/docusaurus-search-local": "^0.34.0",
|
||||
"@mdx-js/react": "^1.6.22",
|
||||
"animate.css": "^4.1.1",
|
||||
"chart.js": "^4.2.1",
|
||||
"clsx": "^1.2.1",
|
||||
"prism-react-renderer": "^1.3.5",
|
||||
"react": "^17.0.2",
|
||||
"react-chartjs-2": "^5.2.0",
|
||||
"react-dom": "^17.0.2"
|
||||
"react-dom": "^17.0.2",
|
||||
"styled-components": "^5.3.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "2.3.1",
|
||||
"@tsconfig/docusaurus": "^1.0.5",
|
||||
"typescript": "^4.7.4"
|
||||
"@typescript-eslint/eslint-plugin": "^5.57.1",
|
||||
"@typescript-eslint/parser": "^5.57.1",
|
||||
"eslint": "^8.38.0",
|
||||
"eslint-config-prettier": "^8.8.0",
|
||||
"eslint-config-standard-with-typescript": "^34.0.1",
|
||||
"eslint-plugin-import": "^2.27.5",
|
||||
"eslint-plugin-n": "^15.7.0",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"eslint-plugin-react": "^7.32.2",
|
||||
"prettier": "^2.8.7",
|
||||
"typescript": "^4.9.5"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
|
||||
@@ -1,7 +1,26 @@
|
||||
import { CategoryScale, Chart as ChartJS, Legend, LinearScale, LineController, LineElement, PointElement, Title, Tooltip } from 'chart.js'
|
||||
import {
|
||||
CategoryScale,
|
||||
Chart as ChartJS,
|
||||
Legend,
|
||||
LinearScale,
|
||||
LineController,
|
||||
LineElement,
|
||||
PointElement,
|
||||
Title,
|
||||
Tooltip,
|
||||
} from 'chart.js'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { Chart } from 'react-chartjs-2'
|
||||
ChartJS.register(CategoryScale, LineController, LinearScale, PointElement, LineElement, Title, Tooltip, Legend)
|
||||
ChartJS.register(
|
||||
CategoryScale,
|
||||
LineController,
|
||||
LinearScale,
|
||||
PointElement,
|
||||
LineElement,
|
||||
Title,
|
||||
Tooltip,
|
||||
Legend
|
||||
)
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
||||
const BenchmarkResultChart = ({
|
||||
@@ -40,11 +59,11 @@ const BenchmarkResultChart = ({
|
||||
}>
|
||||
}) => {
|
||||
const data = {
|
||||
labels: dataset.map((d) => d.commit.id.slice(0, 7)),
|
||||
labels: dataset.map(d => d.commit.id.slice(0, 7)),
|
||||
datasets: [
|
||||
{
|
||||
label: name,
|
||||
data: dataset.map((d) => d.bench.value),
|
||||
data: dataset.map(d => d.bench.value),
|
||||
borderColor: '#ff3838',
|
||||
backgroundColor: '#ff383860', // Add alpha for #rrggbbaa
|
||||
},
|
||||
@@ -75,13 +94,21 @@ const BenchmarkResultChart = ({
|
||||
plugins: {
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
afterTitle: (items) => {
|
||||
afterTitle: items => {
|
||||
const index = items[0].dataIndex
|
||||
const data = dataset[index]
|
||||
return '\n' + data.commit.message + '\n\n' + data.commit.timestamp + ' committed by @' + data.commit.author.username + '\n'
|
||||
return (
|
||||
'\n' +
|
||||
data.commit.message +
|
||||
'\n\n' +
|
||||
data.commit.timestamp +
|
||||
' committed by @' +
|
||||
data.commit.author.username +
|
||||
'\n'
|
||||
)
|
||||
},
|
||||
label: (item) => {
|
||||
let label = item.formattedValue
|
||||
label: item => {
|
||||
let label = item.formattedValue
|
||||
const { range, unit } = dataset[item.datasetIndex].bench
|
||||
label += ` ${unit}`
|
||||
if (range) {
|
||||
@@ -89,7 +116,7 @@ const BenchmarkResultChart = ({
|
||||
}
|
||||
return label
|
||||
},
|
||||
afterLabel: (item) => {
|
||||
afterLabel: item => {
|
||||
const { extra } = dataset[item.datasetIndex].bench
|
||||
return extra ? `\n${extra}` : ''
|
||||
},
|
||||
@@ -118,8 +145,14 @@ export default function BenchmarkResultCharts(): JSX.Element {
|
||||
;(async () => {
|
||||
setData(
|
||||
JSON.parse(
|
||||
(await (await fetch('https://raw.githubusercontent.com/discordeno/discordeno/benchies/benchmarksResult/data.js')).text()).slice(24),
|
||||
),
|
||||
(
|
||||
await (
|
||||
await fetch(
|
||||
'https://raw.githubusercontent.com/discordeno/discordeno/benchies/benchmarksResult/data.js'
|
||||
)
|
||||
).text()
|
||||
).slice(24)
|
||||
)
|
||||
)
|
||||
})()
|
||||
}
|
||||
@@ -146,8 +179,15 @@ export default function BenchmarkResultCharts(): JSX.Element {
|
||||
return (
|
||||
<div style={{ minHeight: '100vh' }}>
|
||||
{data ? (
|
||||
Array.from(collectBenchesPerTestCase(data.entries.Benchmark), ([key, value]) => ({ benchName: key, benches: value })).map((bench, index) => (
|
||||
<BenchmarkResultChart key={index} name={bench.benchName} dataset={bench.benches} />
|
||||
Array.from(
|
||||
collectBenchesPerTestCase(data.entries.Benchmark),
|
||||
([key, value]) => ({ benchName: key, benches: value })
|
||||
).map((bench, index) => (
|
||||
<BenchmarkResultChart
|
||||
key={index}
|
||||
name={bench.benchName}
|
||||
dataset={bench.benches}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<></>
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
import React from 'react'
|
||||
import clsx from 'clsx'
|
||||
import styles from './styles.module.css'
|
||||
|
||||
type FeatureItem = {
|
||||
title: string
|
||||
Svg: React.ComponentType<React.ComponentProps<'svg'>>
|
||||
description: JSX.Element
|
||||
}
|
||||
|
||||
const FeatureList: FeatureItem[] = [
|
||||
{
|
||||
title: 'REST does not rest!',
|
||||
Svg: require('@site/static/img/undraw_docusaurus_mountain.svg').default,
|
||||
description: (
|
||||
<>
|
||||
<ul>
|
||||
<li>Restart without losing any requests.</li>
|
||||
<li>Prevent Invalid 1 Hour Discord Bans.</li>
|
||||
<li>Freedom from global rate limit errors.</li>
|
||||
<li>Single source of contact to API.</li>
|
||||
<li>Beautiful analytics plugins.</li>
|
||||
<li>Scalability! Scalability! Scalability!</li>
|
||||
</ul>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Zero Downtime Updates',
|
||||
Svg: require('@site/static/img/undraw_docusaurus_tree.svg').default,
|
||||
description: (
|
||||
<>
|
||||
<ul>
|
||||
<li>Instant bot restarts/updates.</li>
|
||||
<li>
|
||||
Automated sharding &{' '}
|
||||
<strong>
|
||||
<i>re</i>
|
||||
</strong>
|
||||
sharding.
|
||||
</li>
|
||||
<li>Scale horizontally and save money!</li>
|
||||
<li>Stop losing events during reboots!</li>
|
||||
<li>Max efficiency with Shards/Worker!</li>
|
||||
<li>Scalability! Scalability! Scalability!</li>
|
||||
</ul>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'No More Forks!',
|
||||
Svg: require('@site/static/img/undraw_docusaurus_react.svg').default,
|
||||
description: (
|
||||
<>
|
||||
<ul>
|
||||
<li>100% customizable without forking!</li>
|
||||
<li>By default, the lib caches NOTHING!</li>
|
||||
<li>100% Custom cache support.</li>
|
||||
<li>Cache only the props your bot needs.</li>
|
||||
<li>Customize any internal function!</li>
|
||||
<li>Scalability! Scalability! Scalability!</li>
|
||||
</ul>
|
||||
</>
|
||||
),
|
||||
},
|
||||
]
|
||||
|
||||
function Feature({ title, Svg, description }: FeatureItem) {
|
||||
return (
|
||||
<div className={clsx('col col--4')}>
|
||||
<div className="text--center">
|
||||
<Svg className={styles.featureSvg} role="img" />
|
||||
</div>
|
||||
<div className="text--center padding-horiz--md">
|
||||
<h3>{title}</h3>
|
||||
<p>{description}</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default function HomepageFeatures(): JSX.Element {
|
||||
return (
|
||||
<section className={styles.features}>
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
{FeatureList.map((props, idx) => (
|
||||
<Feature key={idx} {...props} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
19
website/src/components/footer/index.tsx
Normal file
19
website/src/components/footer/index.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import React from 'react'
|
||||
|
||||
export default function Footer() {
|
||||
return (
|
||||
<svg
|
||||
viewBox="0 0 1440 320"
|
||||
style={{
|
||||
background: 'var(--ifm-navbar-background-color)',
|
||||
marginBottom: '-80px',
|
||||
}}
|
||||
>
|
||||
<path
|
||||
fill="var(--ifm-footer-background-color)"
|
||||
fillOpacity="1"
|
||||
d="M0,96L34.3,85.3C68.6,75,137,53,206,64C274.3,75,343,117,411,138.7C480,160,549,160,617,170.7C685.7,181,754,203,823,186.7C891.4,171,960,117,1029,112C1097.1,107,1166,149,1234,144C1302.9,139,1371,85,1406,58.7L1440,32L1440,320L1405.7,320C1371.4,320,1303,320,1234,320C1165.7,320,1097,320,1029,320C960,320,891,320,823,320C754.3,320,686,320,617,320C548.6,320,480,320,411,320C342.9,320,274,320,206,320C137.1,320,69,320,34,320L0,320Z"
|
||||
></path>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
21
website/src/components/header/index.tsx
Normal file
21
website/src/components/header/index.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import Link from '@docusaurus/Link'
|
||||
import { Header, Highlight, Button, HeaderBody } from '@site/src/styling'
|
||||
import React from 'react'
|
||||
|
||||
export default function DiscordenoHeader(): JSX.Element {
|
||||
return (
|
||||
<>
|
||||
<Header>
|
||||
<h1>Its time to ditch Eris and Discord.js</h1>
|
||||
<h2>
|
||||
Making <Highlight>Scalable</Highlight> Bots Easy!
|
||||
</h2>
|
||||
<HeaderBody>
|
||||
<Button variant="primary">
|
||||
<Link to="/docs/intro">Documentation</Link>
|
||||
</Button>
|
||||
</HeaderBody>
|
||||
</Header>
|
||||
</>
|
||||
)
|
||||
}
|
||||
84
website/src/components/home/faq/index.tsx
Normal file
84
website/src/components/home/faq/index.tsx
Normal file
@@ -0,0 +1,84 @@
|
||||
import {
|
||||
FaqAnswer,
|
||||
FaqContainer,
|
||||
FaqQuestion,
|
||||
FaqSection,
|
||||
} from '@site/src/styling'
|
||||
import React from 'react'
|
||||
|
||||
const Faq = ({
|
||||
question,
|
||||
answer,
|
||||
defaultExpanded,
|
||||
}: {
|
||||
question: string
|
||||
answer: string
|
||||
defaultExpanded?: boolean
|
||||
}) => {
|
||||
const [visible, setVisible] = React.useState(defaultExpanded ?? false)
|
||||
|
||||
const toggleVisibility = () => {
|
||||
setVisible(!visible)
|
||||
}
|
||||
|
||||
return (
|
||||
<FaqContainer>
|
||||
<div>
|
||||
<FaqQuestion onClick={toggleVisibility}>
|
||||
{question}
|
||||
{visible ? (
|
||||
<svg height="24" width="24" id="rotated">
|
||||
<path d="m12 15.375-6-6 1.4-1.4 4.6 4.6 4.6-4.6 1.4 1.4Z"></path>
|
||||
</svg>
|
||||
) : (
|
||||
<svg height="24" width="24">
|
||||
<path d="m12 15.375-6-6 1.4-1.4 4.6 4.6 4.6-4.6 1.4 1.4Z"></path>
|
||||
</svg>
|
||||
)}
|
||||
</FaqQuestion>
|
||||
<FaqAnswer visible={visible}>{answer}</FaqAnswer>
|
||||
</div>
|
||||
</FaqContainer>
|
||||
)
|
||||
}
|
||||
|
||||
const questions = [
|
||||
{
|
||||
question: 'Question 1',
|
||||
answer: 'Answer 1',
|
||||
defaultExpanded: true,
|
||||
},
|
||||
{
|
||||
question: 'Question 2',
|
||||
answer: 'Answer 2',
|
||||
defaultExpanded: true,
|
||||
},
|
||||
{
|
||||
question: 'Question 3',
|
||||
answer: 'Answer 3',
|
||||
},
|
||||
{
|
||||
question: 'Question 4',
|
||||
answer: 'Answer 4',
|
||||
},
|
||||
]
|
||||
|
||||
export default function DiscordenoFAQ() {
|
||||
return (
|
||||
<>
|
||||
<FaqSection>
|
||||
<div>
|
||||
<h1>Frequently Asked Questions</h1>
|
||||
{questions.map((question, index) => (
|
||||
<Faq
|
||||
key={index}
|
||||
question={question.question}
|
||||
answer={question.answer}
|
||||
defaultExpanded={question.defaultExpanded}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</FaqSection>
|
||||
</>
|
||||
)
|
||||
}
|
||||
16
website/src/components/home/features/feature.tsx
Normal file
16
website/src/components/home/features/feature.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import React from 'react'
|
||||
import { FeatureList } from '@site/src/types'
|
||||
import clsx from 'clsx'
|
||||
|
||||
export default function Feature({ data }: FeatureList): JSX.Element {
|
||||
return (
|
||||
<div className={clsx('col col--4 animate__animated animate__fadeInDown')}>
|
||||
<div className="text--center">{data.feature.Svg}</div>
|
||||
|
||||
<div className="text--center padding-horiz--md">
|
||||
<h3>{data.feature.title}</h3>
|
||||
<p>{data.feature.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
131
website/src/components/home/features/index.tsx
Normal file
131
website/src/components/home/features/index.tsx
Normal file
@@ -0,0 +1,131 @@
|
||||
import React from 'react'
|
||||
import styles from '@site/src/styling/styles.module.css'
|
||||
import { FeatureItem } from '@site/src/types'
|
||||
import Feature from './feature'
|
||||
|
||||
const FeatureList: FeatureItem[] = [
|
||||
{
|
||||
title: 'REST does not rest!',
|
||||
Svg: (
|
||||
<svg
|
||||
width="54"
|
||||
height="54"
|
||||
viewBox="0 0 54 54"
|
||||
fill="none"
|
||||
style={{
|
||||
color: 'inherit',
|
||||
}}
|
||||
>
|
||||
<path
|
||||
d="M45.225 20.7482C41.1525 20.7482 39.4875 17.8682 41.5125 14.3357C42.6825 12.2882 41.985 9.67815 39.9375 8.50815L36.045 6.28065C34.2675 5.22315 31.9725 5.85315 30.915 7.63065L30.6675 8.05815C28.6425 11.5907 25.3125 11.5907 23.265 8.05815L23.0175 7.63065C22.005 5.85315 19.71 5.22315 17.9325 6.28065L14.04 8.50815C11.9925 9.67815 11.295 12.3107 12.465 14.3582C14.5125 17.8682 12.8475 20.7482 8.775 20.7482C6.435 20.7482 4.5 22.6607 4.5 25.0232V28.9832C4.5 31.3232 6.4125 33.2582 8.775 33.2582C12.8475 33.2582 14.5125 36.1382 12.465 39.6707C11.295 41.7182 11.9925 44.3282 14.04 45.4982L17.9325 47.7257C19.71 48.7832 22.005 48.1532 23.0625 46.3757L23.31 45.9482C25.335 42.4157 28.665 42.4157 30.7125 45.9482L30.96 46.3757C32.0175 48.1532 34.3125 48.7832 36.09 47.7257L39.9825 45.4982C42.03 44.3282 42.7275 41.6957 41.5575 39.6707C39.51 36.1382 41.175 33.2582 45.2475 33.2582C47.5875 33.2582 49.5225 31.3457 49.5225 28.9832V25.0232C49.5 22.6832 47.5875 20.7482 45.225 20.7482ZM27 34.3157C22.9725 34.3157 19.6875 31.0307 19.6875 27.0032C19.6875 22.9757 22.9725 19.6907 27 19.6907C31.0275 19.6907 34.3125 22.9757 34.3125 27.0032C34.3125 31.0307 31.0275 34.3157 27 34.3157Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
),
|
||||
description: (
|
||||
<>
|
||||
<ul>
|
||||
<li>Restart without losing any requests.</li>
|
||||
<li>Prevent Invalid 1 Hour Discord Bans.</li>
|
||||
<li>Freedom from global rate limit errors.</li>
|
||||
<li>Single source of contact to API.</li>
|
||||
<li>Beautiful analytics plugins.</li>
|
||||
<li>Scalability! Scalability! Scalability!</li>
|
||||
</ul>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Zero Downtime Updates',
|
||||
Svg: (
|
||||
<svg
|
||||
width="54"
|
||||
height="54"
|
||||
viewBox="0 0 54 54"
|
||||
fill="none"
|
||||
style={{
|
||||
color: 'inherit',
|
||||
}}
|
||||
>
|
||||
<path
|
||||
d="M27 18.5625C22.9725 18.5625 19.6875 21.8475 19.6875 25.875C19.6875 29.9025 22.9725 33.1875 27 33.1875C31.0275 33.1875 34.3125 29.9025 34.3125 25.875C34.3125 21.8475 31.0275 18.5625 27 18.5625ZM29.25 25.155C29.25 26.5275 28.5075 27.8325 27.3375 28.53L25.605 29.565C25.335 29.7225 25.0425 29.8125 24.7275 29.8125C24.165 29.8125 23.6025 29.52 23.2875 29.0025C22.815 28.1925 23.0625 27.1575 23.8725 26.685L25.5825 25.65C25.7625 25.5375 25.8525 25.3575 25.8525 25.1775V23.085C25.8525 22.1625 26.6175 21.3975 27.54 21.3975C28.4625 21.3975 29.25 22.14 29.25 23.0625V25.155Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M41.7168 9.38392L29.3418 4.7489C28.0593 4.27642 25.9668 4.27642 24.6843 4.7489L12.3093 9.38392C9.92426 10.2839 7.98926 13.0739 7.98926 15.6164V33.8414C7.98926 35.6639 9.18176 38.0714 10.6443 39.1514L23.0193 48.3989C25.2018 50.0414 28.7793 50.0414 30.9618 48.3989L43.3368 39.1514C44.7993 38.0489 45.9918 35.6639 45.9918 33.8414V15.6164C46.0143 13.0739 44.0793 10.2839 41.7168 9.38392ZM27.0018 36.5639C21.1068 36.5639 16.3143 31.7714 16.3143 25.8764C16.3143 19.9814 21.1068 15.1889 27.0018 15.1889C32.8968 15.1889 37.6893 19.9814 37.6893 25.8764C37.6893 31.7714 32.8968 36.5639 27.0018 36.5639Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
),
|
||||
description: (
|
||||
<>
|
||||
<ul>
|
||||
<li>Instant bot restarts/updates.</li>
|
||||
<li>
|
||||
Automated sharding &{' '}
|
||||
<strong>
|
||||
<i>re</i>
|
||||
</strong>
|
||||
sharding.
|
||||
</li>
|
||||
<li>Scale horizontally and save money!</li>
|
||||
<li>Stop losing events during reboots!</li>
|
||||
<li>Max efficiency with Shards/Worker!</li>
|
||||
<li>Scalability! Scalability! Scalability!</li>
|
||||
</ul>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'No More Forks!',
|
||||
Svg: (
|
||||
<svg
|
||||
width="54"
|
||||
height="54"
|
||||
viewBox="0 0 54 54"
|
||||
fill="none"
|
||||
style={{
|
||||
color: 'inherit',
|
||||
}}
|
||||
>
|
||||
<path
|
||||
d="M36.4275 4.5H17.5725C9.3825 4.5 4.5 9.3825 4.5 17.5725V36.405C4.5 44.6175 9.3825 49.5 17.5725 49.5H36.405C44.595 49.5 49.4775 44.6175 49.4775 36.4275V17.5725C49.5 9.3825 44.6175 4.5 36.4275 4.5ZM22.7925 32.625C23.445 33.2775 23.445 34.3575 22.7925 35.01C22.455 35.3475 22.0275 35.505 21.6 35.505C21.1725 35.505 20.745 35.3475 20.4075 35.01L14.805 29.4075C13.4775 28.08 13.4775 25.9425 14.805 24.615L20.4075 19.0125C21.06 18.36 22.14 18.36 22.7925 19.0125C23.445 19.665 23.445 20.745 22.7925 21.3975L17.19 27L22.7925 32.625ZM39.195 29.385L33.5925 34.9875C33.255 35.325 32.8275 35.4825 32.4 35.4825C31.9725 35.4825 31.545 35.325 31.2075 34.9875C30.555 34.335 30.555 33.255 31.2075 32.6025L36.81 27L31.2075 21.375C30.555 20.7225 30.555 19.6425 31.2075 18.99C31.86 18.3375 32.94 18.3375 33.5925 18.99L39.195 24.5925C40.5225 25.92 40.5225 28.08 39.195 29.385Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
),
|
||||
|
||||
description: (
|
||||
<>
|
||||
<ul>
|
||||
<li>100% customizable without forking!</li>
|
||||
<li>By default, the lib caches NOTHING!</li>
|
||||
<li>100% Custom cache support.</li>
|
||||
<li>Cache only the props your bot needs.</li>
|
||||
<li>Customize any internal function!</li>
|
||||
<li>Scalability! Scalability! Scalability!</li>
|
||||
</ul>
|
||||
</>
|
||||
),
|
||||
},
|
||||
]
|
||||
|
||||
export default function DiscordenoFeatures(): JSX.Element {
|
||||
return (
|
||||
<section className={styles.features}>
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
{FeatureList.map((props, idx) => (
|
||||
<Feature
|
||||
key={idx}
|
||||
data={{
|
||||
feature: props,
|
||||
featureList: FeatureList,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
253
website/src/components/home/reviews/index.tsx
Normal file
253
website/src/components/home/reviews/index.tsx
Normal file
@@ -0,0 +1,253 @@
|
||||
import {
|
||||
ReviewsBox,
|
||||
ReviewsElement,
|
||||
ReviewsElementWrapper,
|
||||
ReviewsHeader,
|
||||
ReviewsLeft,
|
||||
ReviewsOther,
|
||||
ReviewsOtherContainer,
|
||||
ReviewsRight,
|
||||
ReviewsSection,
|
||||
StarContainer,
|
||||
StarIcon,
|
||||
} from '@site/src/styling'
|
||||
import { DiscordLibraries, IReview } from '@site/src/types'
|
||||
import React from 'react'
|
||||
|
||||
const reviewList: IReview[] = [
|
||||
{
|
||||
review: `The best library I've ever seen in JS, very much leaning towards optimization for larger bots while still keeping it easy to use. Highly customizable without needing to fork the lib at all. The maintainers and the community are very nice, friendly and helpful. `,
|
||||
bot: {
|
||||
username: 'Giveaway Boat',
|
||||
discriminator: '2911',
|
||||
avatar:
|
||||
'https://media.discordapp.net/attachments/785384884197392387/1094721866167492658/giveaway_boat.png',
|
||||
invite_url: 'https://invite.giveaway.boats/',
|
||||
guild_count: 150000,
|
||||
},
|
||||
developer: {
|
||||
username: 'Awesome Stickz',
|
||||
discriminator: '9999',
|
||||
},
|
||||
stars: 5,
|
||||
previous_library: 'ERIS',
|
||||
memory_improvement: {
|
||||
from: 20000,
|
||||
to: 7000,
|
||||
},
|
||||
},
|
||||
{
|
||||
review: `DiscordEno is the best library that offers very high customization. It is perfect for scaling large Discord bots. This library helped us improve our memory usage by 7 times!`,
|
||||
bot: {
|
||||
username: 'Ai Image Generator',
|
||||
discriminator: '8424',
|
||||
avatar:
|
||||
'https://cdn.discordapp.com/avatars/1032699319368814652/8abbc5911333d3df288ff962a2120d75.png',
|
||||
invite_url:
|
||||
'https://discord.com/oauth2/authorize?client_id=1032699319368814652&permissions=274877959232&scope=bot%20applications.commands',
|
||||
guild_count: 41000,
|
||||
},
|
||||
developer: {
|
||||
username: '8au',
|
||||
discriminator: '7840',
|
||||
},
|
||||
stars: 5,
|
||||
previous_library: 'DISCORD_JS',
|
||||
memory_improvement: {
|
||||
from: 4500,
|
||||
to: 614,
|
||||
},
|
||||
},
|
||||
{
|
||||
review: `The library prioritizes the needs and opinions of its core users, and offers a straightforward yet highly customizable implementation. The Core Contributors bring their extensive experience in developing large-scale bots.`,
|
||||
bot: {
|
||||
username: 'Fibo',
|
||||
discriminator: '6503',
|
||||
avatar:
|
||||
'https://cdn.discordapp.com/avatars/735147814878969968/8b72f174c30276f4d48c1e66608df70c.webp',
|
||||
invite_url:
|
||||
'https://discord.com/api/oauth2/authorize?client_id=735147814878969968&permissions=805825744&scope=applications.commands%20bot',
|
||||
guild_count: 211477,
|
||||
},
|
||||
developer: {
|
||||
username: 'Meister',
|
||||
discriminator: '9667',
|
||||
},
|
||||
stars: 5,
|
||||
previous_library: 'DISCORD_JS',
|
||||
memory_improvement: {
|
||||
from: 13000,
|
||||
to: 11000,
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export default function DiscordenoReviews() {
|
||||
return (
|
||||
<ReviewsSection>
|
||||
<div>
|
||||
<div>
|
||||
<h1>Discordeno Community Feedback</h1>
|
||||
</div>
|
||||
<ReviewsElementWrapper>
|
||||
{reviewList
|
||||
.sort((a, b) => {
|
||||
return b.bot.guild_count - a.bot.guild_count
|
||||
})
|
||||
.map((review, idx) => (
|
||||
<ReviewsElement
|
||||
key={review.bot.username}
|
||||
className="animate__animated animate__fadeInDown"
|
||||
>
|
||||
<ReviewsHeader>
|
||||
<ReviewsLeft>
|
||||
<img src={review.bot.avatar} alt={review.bot.username} />
|
||||
<div>
|
||||
<span>
|
||||
<div id="username">{review.bot.username}</div>
|
||||
<div id="discriminator">
|
||||
#{review.bot.discriminator}
|
||||
</div>
|
||||
<div id="badge">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="12"
|
||||
height="16"
|
||||
viewBox="0 0 12 16"
|
||||
>
|
||||
<path
|
||||
fill="#fff"
|
||||
fillRule="evenodd"
|
||||
d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"
|
||||
></path>
|
||||
</svg>
|
||||
Bot
|
||||
</div>
|
||||
</span>
|
||||
<div id="sub_header">
|
||||
by <div id="username">{review.developer.username}</div>
|
||||
<div id="discriminator">
|
||||
#{review.developer.discriminator}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ReviewsLeft>
|
||||
<ReviewsRight>
|
||||
<StarContainer>
|
||||
{([1, 2, 3, 4, 5] as const).map(star => (
|
||||
<StarIcon
|
||||
key={star}
|
||||
active={star > review.stars}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 20 20"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<title>{`Star ${star}`}</title>
|
||||
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
|
||||
</StarIcon>
|
||||
))}
|
||||
</StarContainer>
|
||||
<div>
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12 2C9.38 2 7.25 4.13 7.25 6.75C7.25 9.32 9.26 11.4 11.88 11.49C11.96 11.48 12.04 11.48 12.1 11.49C12.12 11.49 12.13 11.49 12.15 11.49C12.16 11.49 12.16 11.49 12.17 11.49C14.73 11.4 16.74 9.32 16.75 6.75C16.75 4.13 14.62 2 12 2Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M17.0809 14.1606C14.2909 12.3006 9.74094 12.3006 6.93094 14.1606C5.66094 15.0006 4.96094 16.1506 4.96094 17.3806C4.96094 18.6106 5.66094 19.7506 6.92094 20.5906C8.32094 21.5306 10.1609 22.0006 12.0009 22.0006C13.8409 22.0006 15.6809 21.5306 17.0809 20.5906C18.3409 19.7406 19.0409 18.6006 19.0409 17.3606C19.0309 16.1406 18.3409 14.9906 17.0809 14.1606ZM14.3309 16.5606L11.8109 19.0806C11.6909 19.2006 11.5309 19.2606 11.3709 19.2606C11.2109 19.2606 11.0509 19.1906 10.9309 19.0806L9.67094 17.8206C9.43094 17.5806 9.43094 17.1806 9.67094 16.9406C9.91094 16.7006 10.3109 16.7006 10.5509 16.9406L11.3709 17.7606L13.4509 15.6806C13.6909 15.4406 14.0909 15.4406 14.3309 15.6806C14.5809 15.9206 14.5809 16.3206 14.3309 16.5606Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
{String(review.bot.guild_count).replace(
|
||||
/\B(?=(\d{3})+(?!\d))/g,
|
||||
','
|
||||
)}{' '}
|
||||
guilds
|
||||
</div>
|
||||
</ReviewsRight>
|
||||
</ReviewsHeader>
|
||||
<ReviewsBox>{review.review}</ReviewsBox>
|
||||
<ReviewsOtherContainer>
|
||||
<a
|
||||
href={review.bot.invite_url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12 2C6.49 2 2 6.49 2 12C2 17.51 6.49 22 12 22C17.51 22 22 17.51 22 12C22 6.49 17.51 2 12 2ZM16 12.75H12.75V16C12.75 16.41 12.41 16.75 12 16.75C11.59 16.75 11.25 16.41 11.25 16V12.75H8C7.59 12.75 7.25 12.41 7.25 12C7.25 11.59 7.59 11.25 8 11.25H11.25V8C11.25 7.59 11.59 7.25 12 7.25C12.41 7.25 12.75 7.59 12.75 8V11.25H16C16.41 11.25 16.75 11.59 16.75 12C16.75 12.41 16.41 12.75 16 12.75Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
Invite this bot
|
||||
</a>
|
||||
<div>
|
||||
<div>
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M22 22.75H5C2.93 22.75 1.25 21.07 1.25 19V2C1.25 1.59 1.59 1.25 2 1.25C2.41 1.25 2.75 1.59 2.75 2V19C2.75 20.24 3.76 21.25 5 21.25H22C22.41 21.25 22.75 21.59 22.75 22C22.75 22.41 22.41 22.75 22 22.75Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M4.99982 17.7498C4.82982 17.7498 4.64982 17.6898 4.50982 17.5698C4.19982 17.2998 4.15982 16.8298 4.42982 16.5098L9.01982 11.1498C9.51982 10.5698 10.2398 10.2198 10.9998 10.1898C11.7598 10.1698 12.5098 10.4498 13.0498 10.9898L13.9998 11.9398C14.2498 12.1898 14.5698 12.3098 14.9298 12.3098C15.2798 12.2998 15.5998 12.1398 15.8298 11.8698L20.4198 6.50982C20.6898 6.19982 21.1598 6.15982 21.4798 6.42982C21.7898 6.69982 21.8298 7.16982 21.5598 7.48982L16.9698 12.8498C16.4698 13.4298 15.7498 13.7798 14.9898 13.8098C14.2198 13.8298 13.4798 13.5498 12.9398 13.0098L11.9998 12.0598C11.7498 11.8098 11.4198 11.6798 11.0698 11.6898C10.7198 11.6998 10.3998 11.8598 10.1698 12.1298L5.57982 17.4898C5.41982 17.6598 5.20982 17.7498 4.99982 17.7498Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
{review.memory_improvement
|
||||
? (review.memory_improvement.from / 1000)
|
||||
.toString()
|
||||
.replace(/\B(?=(\d{3})+(?!\d))/g, ',') +
|
||||
'GB' +
|
||||
` (${DiscordLibraries[review.previous_library]})`
|
||||
: DiscordLibraries[review.previous_library]}
|
||||
<div>→</div>
|
||||
{review.memory_improvement
|
||||
? (review.memory_improvement.to / 1000)
|
||||
.toString()
|
||||
.replace(/\B(?=(\d{3})+(?!\d))/g, ',') + 'GB'
|
||||
: 'Discordeno'}
|
||||
|
||||
{review.memory_improvement && (
|
||||
// show in percentage the improvement
|
||||
<div>
|
||||
{' '}
|
||||
—{' '}
|
||||
<strong>
|
||||
{(
|
||||
((review.memory_improvement.from -
|
||||
review.memory_improvement.to) /
|
||||
review.memory_improvement.from) as any
|
||||
).toFixed(2) * 100}
|
||||
%
|
||||
</strong>
|
||||
RAM improvement
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</ReviewsOtherContainer>
|
||||
</ReviewsElement>
|
||||
))}
|
||||
</ReviewsElementWrapper>
|
||||
</div>
|
||||
</ReviewsSection>
|
||||
)
|
||||
}
|
||||
@@ -1,37 +1,28 @@
|
||||
import React from 'react'
|
||||
import clsx from 'clsx'
|
||||
import Link from '@docusaurus/Link'
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext'
|
||||
import Layout from '@theme/Layout'
|
||||
import HomepageFeatures from '@site/src/components/HomepageFeatures'
|
||||
|
||||
import styles from './index.module.css'
|
||||
|
||||
function HomepageHeader() {
|
||||
const { siteConfig } = useDocusaurusContext()
|
||||
return (
|
||||
<header className={clsx('hero hero--primary', styles.heroBanner)}>
|
||||
<div className="container">
|
||||
<h1 className="hero__title">It's time to ditch Eris and Discord.JS</h1>
|
||||
<p className="hero__subtitle">Discordeno - {siteConfig.tagline}</p>
|
||||
<div className={styles.buttons}>
|
||||
<Link className="button button--secondary button--lg" to="/docs/intro">
|
||||
Learn Discordeno!
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
import 'animate.css'
|
||||
import DiscordenoHeader from '../components/header'
|
||||
import { MainPage } from '../styling'
|
||||
import DiscordenoFeatures from '../components/home/features'
|
||||
import Footer from '../components/footer'
|
||||
import DiscordenoReviews from '../components/home/reviews'
|
||||
import DiscordenoFAQ from '../components/home/faq'
|
||||
|
||||
export default function Home(): JSX.Element {
|
||||
const { siteConfig } = useDocusaurusContext()
|
||||
return (
|
||||
<Layout title={`Hello from ${siteConfig.title}`} description="Description will go into a meta tag in <head />">
|
||||
<HomepageHeader />
|
||||
<main>
|
||||
<HomepageFeatures />
|
||||
</main>
|
||||
<Layout
|
||||
title={`Discordeno Documentation`}
|
||||
description="An in-depth guide to using the Discordeno library for Deno."
|
||||
>
|
||||
<DiscordenoHeader />
|
||||
<MainPage>
|
||||
<DiscordenoFeatures />
|
||||
<DiscordenoReviews />
|
||||
<DiscordenoFAQ />
|
||||
</MainPage>
|
||||
<Footer />
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
/* You can override the default Infima variables here. */
|
||||
:root {
|
||||
--ifm-color-primary: #2e8555;
|
||||
--ifm-color-primary: #5c76b5;
|
||||
--ifm-color-primary-dark: #29784c;
|
||||
--ifm-color-primary-darker: #277148;
|
||||
--ifm-color-primary-darkest: #205d3b;
|
||||
@@ -15,6 +15,10 @@
|
||||
--ifm-color-primary-lightest: #3cad6e;
|
||||
--ifm-code-font-size: 95%;
|
||||
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);
|
||||
--ifm-navbar-background-color: #83a7ff;
|
||||
--ifm-footer-color: #fff;
|
||||
--ifm-footer-link-color: #cfcfcf;
|
||||
--ifm-footer-background-color: #273b6c;
|
||||
}
|
||||
|
||||
/* For readability concerns, you should choose a lighter palette in dark mode. */
|
||||
@@ -27,4 +31,8 @@
|
||||
--ifm-color-primary-lighter: #32d8b4;
|
||||
--ifm-color-primary-lightest: #4fddbf;
|
||||
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
--ifm-navbar-background-color: #0f0f0f;
|
||||
--ifm-footer-color: #fff;
|
||||
--ifm-footer-link-color: #cfcfcf;
|
||||
--ifm-footer-background-color: #0c0c0c;
|
||||
}
|
||||
411
website/src/styling/index.ts
Normal file
411
website/src/styling/index.ts
Normal file
@@ -0,0 +1,411 @@
|
||||
import styled from 'styled-components'
|
||||
|
||||
export const Header = styled.div`
|
||||
background: url('/img/deno_background.png') repeat center center fixed;
|
||||
background-repeat: repeat;
|
||||
height: 60vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
|
||||
::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
right: 0px;
|
||||
left: 0px;
|
||||
height: 10px;
|
||||
background: linear-gradient(
|
||||
0deg,
|
||||
var(--ifm-navbar-background-color),
|
||||
hsla(0, 0%, 7%, 0)
|
||||
);
|
||||
z-index: 2147483647;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 4rem;
|
||||
font-weight: 900;
|
||||
color: var(--ifm-color-white);
|
||||
line-height: 1.25;
|
||||
text-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
font-weight: 800;
|
||||
color: var(--ifm-color-white);
|
||||
line-height: 1.25;
|
||||
text-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
|
||||
text-align: center;
|
||||
}
|
||||
`
|
||||
|
||||
export const HeaderCode = styled.div``
|
||||
|
||||
export const Highlight = styled.span`
|
||||
background: linear-gradient(135deg, #000, #443281, #443281, #7289da),
|
||||
repeating-linear-gradient(135deg, #000, #000 10px, #000 10px, #443281 20px);
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
color: transparent;
|
||||
background-size: 600% 600%;
|
||||
animation: gradient 10s ease infinite;
|
||||
height: 100vh;
|
||||
-webkit-text-decoration-color: transparent;
|
||||
|
||||
@keyframes gradient {
|
||||
0% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
50% {
|
||||
background-position: 100% 50%;
|
||||
}
|
||||
100% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
export const Button = styled.button<{
|
||||
variant: 'primary' | 'link'
|
||||
}>`
|
||||
background: transparent;
|
||||
border: transparent;
|
||||
|
||||
a {
|
||||
background: ${({ variant }) =>
|
||||
variant === 'primary' ? '#181818' : 'transparent'};
|
||||
color: ${({ variant }) => (variant === 'primary' ? '#fff' : 'primary')};
|
||||
animation: gradient 10s ease infinite;
|
||||
-webkit-text-decoration-color: transparent;
|
||||
border: none;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
font-size: 1.5rem;
|
||||
font-weight: 900;
|
||||
border: 2px solid black;
|
||||
padding: 0.7rem 1.1rem;
|
||||
border-radius: 0.5rem;
|
||||
margin: 0.5rem;
|
||||
transition: all 0.3s ease-in-out;
|
||||
|
||||
@keyframes gradient {
|
||||
0% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
50% {
|
||||
background-position: 100% 50%;
|
||||
}
|
||||
100% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
}
|
||||
|
||||
:hover {
|
||||
background: ${({ variant }) =>
|
||||
variant === 'primary' ? '#0F0F0F' : 'transparent'};
|
||||
color: ${({ variant }) => (variant === 'primary' ? '#fff' : 'primary')};
|
||||
animation: gradient 10s ease infinite;
|
||||
-webkit-text-decoration-color: transparent;
|
||||
border: none;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
font-size: 1.5rem;
|
||||
font-weight: 900;
|
||||
border: 2px solid black;
|
||||
padding: 0.7rem 1.1rem;
|
||||
border-radius: 0.5rem;
|
||||
margin: 0.5rem;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
}
|
||||
`
|
||||
export const HeaderBody = styled.div`
|
||||
margin-top: 2rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
`
|
||||
|
||||
export const MainPage = styled.div`
|
||||
background: var(--ifm-navbar-background-color);
|
||||
`
|
||||
|
||||
export const ReviewsSection = styled.div`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-top: 2rem;
|
||||
margin-left: 2vw;
|
||||
margin-right: 2vw;
|
||||
|
||||
h1 {
|
||||
margin-top: 3rem;
|
||||
margin-bottom: 2rem;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: 3rem;
|
||||
font-weight: 900;
|
||||
color: var(--ifm-color-white);
|
||||
line-height: 1.25;
|
||||
text-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
`
|
||||
|
||||
export const ReviewsElementWrapper = styled.div`
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(700px, 1fr));
|
||||
gap: 1rem;
|
||||
|
||||
@media (max-width: 768px) {
|
||||
grid-template-columns: repeat(auto-fill, minmax(95vw, 1fr));
|
||||
}
|
||||
`
|
||||
|
||||
export const ReviewsElement = styled.div`
|
||||
background: var(--ifm-footer-background-color);
|
||||
border-radius: 5px;
|
||||
height: 240px;
|
||||
padding: 32px 40px;
|
||||
position: relative;
|
||||
`
|
||||
|
||||
export const ReviewsHeader = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
`
|
||||
|
||||
export const ReviewsRight = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
font-size: 1.5rem;
|
||||
font-weight: 900;
|
||||
color: var(--ifm-color-white);
|
||||
|
||||
div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.2rem;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
display: none;
|
||||
}
|
||||
`
|
||||
|
||||
export const ReviewsLeft = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.7rem;
|
||||
|
||||
img {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
div {
|
||||
#sub_header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.1rem;
|
||||
color: var(--ifm-color-white);
|
||||
|
||||
#username {
|
||||
margin-left: 0.3rem;
|
||||
font-size: 1rem;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
#discriminator {
|
||||
font-size: 0.8rem;
|
||||
color: lightgray;
|
||||
font-weight: 900;
|
||||
margin-left: 0.1rem;
|
||||
margin-top: 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: var(--ifm-color-white);
|
||||
|
||||
#username {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 900;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
#discriminator {
|
||||
font-size: 1rem;
|
||||
color: lightgray;
|
||||
font-weight: 900;
|
||||
margin-top: 0.4rem;
|
||||
margin-left: 0.3rem;
|
||||
}
|
||||
|
||||
#badge {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #5865f2;
|
||||
font-size: 0.65em;
|
||||
margin-left: 5px;
|
||||
padding: 3px 4px;
|
||||
border-radius: 3px;
|
||||
line-height: 100%;
|
||||
text-transform: uppercase;
|
||||
|
||||
svg {
|
||||
margin-right: 2px;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export const ReviewsBox = styled.div`
|
||||
margin-top: 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
height: 80px;
|
||||
color: var(--ifm-color-white);
|
||||
`
|
||||
|
||||
export const StarContainer = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
`
|
||||
|
||||
export const StarIcon = styled.svg`
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
fill: ${props => (props.active ? 'currentColor' : '#CBD5E0')};
|
||||
`
|
||||
|
||||
export const ReviewsOther = styled.div`
|
||||
margin-top: 7px;
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
`
|
||||
|
||||
export const ReviewsOtherContainer = styled.div`
|
||||
margin-top: 7px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: var(--ifm-color-white);
|
||||
|
||||
a {
|
||||
color: var(--ifm-color-white);
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease-in-out;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.2rem;
|
||||
text-decoration: underline;
|
||||
|
||||
svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
:hover {
|
||||
color: lightblue;
|
||||
}
|
||||
}
|
||||
|
||||
div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
text-transform: capitalize;
|
||||
|
||||
@media (max-width: 768px) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
strong {
|
||||
margin-left: 4px;
|
||||
margin-right: -2px;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export const FaqSection = styled.div`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-top: 5rem;
|
||||
margin-left: 2vw;
|
||||
margin-right: 2vw;
|
||||
|
||||
h1 {
|
||||
margin-top: 3rem;
|
||||
margin-bottom: 2rem;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: 3rem;
|
||||
font-weight: 900;
|
||||
color: var(--ifm-color-white);
|
||||
line-height: 1.25;
|
||||
text-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
`
|
||||
|
||||
export const FaqContainer = styled.div`
|
||||
border: 1px solid var(--ifm-footer-background-color);
|
||||
border-radius: 5px;
|
||||
margin-bottom: 10px;
|
||||
width: 40vw;
|
||||
background-color: var(--ifm-footer-background-color);
|
||||
|
||||
#rotated {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
width: 90vw;
|
||||
}
|
||||
`
|
||||
|
||||
export const FaqQuestion = styled.h3`
|
||||
cursor: pointer;
|
||||
padding: 10px;
|
||||
margin: 0;
|
||||
background-color: var(--ifm-footer-background-color);
|
||||
color: var(--ifm-color-white);
|
||||
user-select: none;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
svg {
|
||||
fill: var(--ifm-color-white);
|
||||
}
|
||||
`
|
||||
|
||||
export const FaqAnswer = styled.div`
|
||||
padding: ${({ visible }) => (visible ? '10px' : '0px')};
|
||||
background-color: var(--ifm-footer-background-color);
|
||||
color: #fff;
|
||||
height: ${({ visible }) => (visible ? 'auto' : '0px')};
|
||||
overflow: hidden;
|
||||
transition: height 0.3s;
|
||||
`
|
||||
56
website/src/types.ts
Normal file
56
website/src/types.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
export type FeatureList = {
|
||||
data: {
|
||||
feature: FeatureItem
|
||||
featureList: FeatureItem[]
|
||||
}
|
||||
}
|
||||
|
||||
export type FeatureItem = {
|
||||
title: string
|
||||
Svg: JSX.Element
|
||||
description: JSX.Element
|
||||
}
|
||||
|
||||
export enum DiscordLibraries {
|
||||
DISCORD_JS = 'Discord.js',
|
||||
DISCORD_GO = 'Discordgo',
|
||||
DISCORD_RB = 'discordrb',
|
||||
SWORD = 'Sword',
|
||||
REST_CORD = 'RestCord',
|
||||
DISCORD_PHP = 'DiscordPHP',
|
||||
JAVACORD = 'Javacord',
|
||||
DISCORD_PY = 'discord.py',
|
||||
SERENITY = 'serenity',
|
||||
D_SHARP_PLUS = 'DSharpPlus',
|
||||
DISCORD_DOT_NET = 'Discord.Net',
|
||||
DISCORD_4J = 'Discord4J',
|
||||
DISCORDIE = 'discordie',
|
||||
DISCORD_RS = 'discord-rs',
|
||||
DISCORDIA = 'Discordia',
|
||||
ERIS = 'eris',
|
||||
DISCORD_HS = 'discord-hs',
|
||||
DISCORD_CR = 'discordcr',
|
||||
JDA = 'JDA',
|
||||
CUSTOM = 'Custom', // Custom library
|
||||
}
|
||||
|
||||
export type IReview = {
|
||||
review: string // the review
|
||||
bot: {
|
||||
username: string // Clyde
|
||||
discriminator: string // 0000
|
||||
avatar: string // https://cdn.discordapp.com/avatars/123456789012345678/abcdefg1234567890.png
|
||||
invite_url: string // https://discord.com/api/oauth2/authorize?client_id=123456789012345678&permissions=8&scope=bot
|
||||
guild_count: number // 123456 => automatically frontent converts to 123,456...
|
||||
}
|
||||
developer: {
|
||||
username: string // Peter_
|
||||
discriminator: string // 4444
|
||||
}
|
||||
stars: 4 | 5 // 4 or 5, discordeno can't have lower because it's the best :D
|
||||
previous_library?: keyof typeof DiscordLibraries // previous library used by the bot (if any)
|
||||
memory_improvement?: {
|
||||
from: number // 100 => frontend converts to 100MB
|
||||
to: number // 50 => frontend converts to 50MB
|
||||
}
|
||||
}
|
||||
BIN
website/static/img/deno_background.png
Normal file
BIN
website/static/img/deno_background.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 950 B |
2440
website/yarn.lock
2440
website/yarn.lock
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user