Merge pull request #8 from tresabhi/1.7.5

This commit is contained in:
TrèsAbhi authored and GitHub committed 2023-06-11 21:26:50 -05:00
commit 858efbcdfe
22 files changed
+89 -77

No files matched your search

+15 -24
View File
@@ -8,40 +8,31 @@ on:
- 'main'
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
host:
name: Host
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x]
steps:
- name: Get code
uses: actions/checkout@v2
- name: Use node
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install Yarn
run: npm install --location=global yarn
- name: Use node_modules cache
uses: actions/cache@v2
- name: Get latest release
uses: actions/github-script@v4
with:
path: '**/node_modules'
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
script: |
const response = await github.repos.getLatestRelease({
owner: context.repo.owner,
repo: context.repo.repo
});
console.log(response.data.assets[0].browser_download_url);
core.setOutput("download_url", response.data.assets[0].browser_download_url);
- name: Install dependencies
run: yarn
- name: Download release assets
run: |
curl -L -o dist.zip ${{ steps.get-latest-release.outputs.download_url }}
unzip dist.zip
- name: Host
run: NODE_ENV=production DISCORD_TOKEN=${{ secrets.DISCORD_TOKEN }} WARGAMING_APPLICATION_ID=${{ secrets.WARGAMING_APPLICATION_ID }} yarn dev --dev
- name: Run index.cjs
run: NODE_ENV=production DISCORD_TOKEN=${{ secrets.DISCORD_TOKEN }} WARGAMING_APPLICATION_ID=${{ secrets.WARGAMING_APPLICATION_ID }} node --enable-source-maps dist/index.cjs
+1
View File
@@ -6,3 +6,4 @@ package-lock.json
/playwright/.cache/
dist/
yarn-error.log
dist.zip
+1
View File
@@ -6,6 +6,7 @@
"cleandist",
"fuzzysort",
"kranvagn",
"outfile",
"ownedtanks",
"Resvg",
"searchplayers",
+3 -5
View File
@@ -6,11 +6,9 @@
"type": "module",
"scripts": {
"dev": "yarn build && yarn start",
"start": "node --enable-source-maps dist/server.cjs",
"cleandist": "rm -rf dist",
"build:raw": "npx esbuild src/index.ts --outfile=dist/server.cjs --platform=node --bundle --sourcemap --loader:.node=copy --loader:.ttf=file",
"build:package": "cp package.dist.json dist/package.json",
"build": "yarn cleandist && yarn build:raw && yarn build:package",
"start": "node --enable-source-maps dist/index.cjs",
"zip": "zip -r dist.zip dist",
"build": "node scripts/build",
"lint": "tsc"
},
"license": "MIT",
+23
View File
@@ -0,0 +1,23 @@
import { build } from 'esbuild';
import { rmSync } from 'fs';
console.log('Removing dist...');
rmSync('dist', { recursive: true, force: true });
console.log('Creating context...');
build({
entryPoints: ['src/index.ts'],
outfile: 'dist/index.cjs',
platform: 'node',
loader: {
'.node': 'copy',
'.ttf': 'file',
},
bundle: true,
sourcemap: true,
minifyIdentifiers: false, // causes errors
minifySyntax: true,
minifyWhitespace: true,
});
+2 -2
View File
@@ -13,7 +13,7 @@ import cmdName from '../core/interaction/cmdName.js';
import negativeEmbed from '../core/interaction/negativeEmbed.js';
import positiveEmbed from '../core/interaction/positiveEmbed.js';
import addUsernameOption from '../core/options/addUsernameOption.js';
import { wargamingApplicationId } from '../core/process/args.js';
import { WARGAMING_APPLICATION_ID } from '../core/process/args.js';
import { CommandRegistry } from '../events/interactionCreate.js';
import { AccountInfo } from '../types/accountInfo.js';
@@ -51,7 +51,7 @@ export default {
const clan = interaction.options.getString('clan') as SkilledClan;
const { id, server } = await getBlitzAccount(interaction);
const accountInfo = await getWargamingResponse<AccountInfo>(
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${wargamingApplicationId}&account_id=${id}`,
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
);
const problems: TableInput = [];
const title = `${accountInfo[id].nickname}'s eligibility for ${SKILLED_CLANS[clan]}`;
+3 -3
View File
@@ -10,7 +10,7 @@ import getBlitzClan from '../core/blitz/getBlitzClan.js';
import getWargamingResponse from '../core/blitz/getWargamingResponse.js';
import cmdName from '../core/interaction/cmdName.js';
import addClanChoices from '../core/options/addClanChoices.js';
import { wargamingApplicationId } from '../core/process/args.js';
import { WARGAMING_APPLICATION_ID } from '../core/process/args.js';
import render from '../core/ui/render.js';
import { CommandRegistry } from '../events/interactionCreate.js';
import { AccountInfo } from '../types/accountInfo.js';
@@ -44,12 +44,12 @@ export default {
const time = new Date().getTime() / 1000;
const clanData = (
await getWargamingResponse<ClanInfo>(
`https://api.wotblitz.${server}/wotb/clans/info/?application_id=${wargamingApplicationId}&clan_id=${id}`,
`https://api.wotblitz.${server}/wotb/clans/info/?application_id=${WARGAMING_APPLICATION_ID}&clan_id=${id}`,
)
)[id];
const memberIds = clanData.members_ids;
const accounts = await getWargamingResponse<AccountInfo>(
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${wargamingApplicationId}&account_id=${memberIds.join(
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${memberIds.join(
',',
)}`,
);
+3 -3
View File
@@ -12,7 +12,7 @@ import getWargamingResponse from '../core/blitz/getWargamingResponse.js';
import { TIER_ROMAN_NUMERALS, tankopedia } from '../core/blitz/tankopedia.js';
import cmdName from '../core/interaction/cmdName.js';
import addUsernameOption from '../core/options/addUsernameOption.js';
import { wargamingApplicationId } from '../core/process/args.js';
import { WARGAMING_APPLICATION_ID } from '../core/process/args.js';
import render from '../core/ui/render.js';
import { CommandRegistry } from '../events/interactionCreate.js';
import { AccountInfo } from '../types/accountInfo.js';
@@ -62,14 +62,14 @@ export default {
const account = await getBlitzAccount(interaction);
const { id, server } = account;
const accountInfo = await getWargamingResponse<AccountInfo>(
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${wargamingApplicationId}&account_id=${id}`,
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
);
const tankStats = await getTankStats(interaction, server, id);
const tanks = tankStats
.map((tankData) => tankopedia[tankData.tank_id])
.filter((tank) => tank?.tier === tier);
const clanData = await getWargamingResponse<PlayerClanData>(
`https://api.wotblitz.${server}/wotb/clans/accountinfo/?application_id=${wargamingApplicationId}&account_id=${id}&extra=clan`,
`https://api.wotblitz.${server}/wotb/clans/accountinfo/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}&extra=clan`,
);
const image = await render(
+3 -3
View File
@@ -8,7 +8,7 @@ import cleanTable, { TableInputEntry } from '../core/interaction/cleanTable.js';
import cmdName from '../core/interaction/cmdName.js';
import infoEmbed from '../core/interaction/infoEmbed.js';
import addUsernameOption from '../core/options/addUsernameOption.js';
import { wargamingApplicationId } from '../core/process/args.js';
import { WARGAMING_APPLICATION_ID } from '../core/process/args.js';
import { CommandRegistry } from '../events/interactionCreate.js';
import { AccountAchievements } from '../types/accountAchievements.js';
import { AccountInfo } from '../types/accountInfo.js';
@@ -39,11 +39,11 @@ export default {
const account = await getBlitzAccount(interaction);
const { id, server } = account;
const accounts = await getWargamingResponse<AccountInfo>(
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${wargamingApplicationId}&account_id=${id}`,
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
);
const accountsAchievements =
await getWargamingResponse<AccountAchievements>(
`https://api.wotblitz.${server}/wotb/account/achievements/?application_id=${wargamingApplicationId}&account_id=${id}`,
`https://api.wotblitz.${server}/wotb/account/achievements/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
);
const accountAchievements = accountsAchievements[id];
const compound = {
+2 -2
View File
@@ -7,7 +7,7 @@ import cleanTable from '../core/interaction/cleanTable.js';
import cmdName from '../core/interaction/cmdName.js';
import infoEmbed from '../core/interaction/infoEmbed.js';
import addUsernameOption from '../core/options/addUsernameOption.js';
import { wargamingApplicationId } from '../core/process/args.js';
import { WARGAMING_APPLICATION_ID } from '../core/process/args.js';
import { CommandRegistry } from '../events/interactionCreate.js';
import { AccountInfo } from '../types/accountInfo.js';
@@ -25,7 +25,7 @@ export default {
const account = await getBlitzAccount(interaction);
const { id, server } = account;
const accounts = await getWargamingResponse<AccountInfo>(
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${wargamingApplicationId}&account_id=${id}`,
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
);
const accountInfo = accounts[id];
+2 -2
View File
@@ -6,7 +6,7 @@ import cmdName from '../core/interaction/cmdName.js';
import infoEmbed from '../core/interaction/infoEmbed.js';
import addClanChoices from '../core/options/addClanChoices.js';
import addServerChoices from '../core/options/addServerChoices.js';
import { wargamingApplicationId } from '../core/process/args.js';
import { WARGAMING_APPLICATION_ID } from '../core/process/args.js';
import { CommandRegistry } from '../events/interactionCreate.js';
import { ClanList } from '../types/clanList.js';
@@ -33,7 +33,7 @@ export default {
const clan = interaction.options.getString('clan')!;
const limit = interaction.options.getInteger('limit') ?? 25;
const clanList = await getWargamingResponse<ClanList>(
`https://api.wotblitz.${server}/wotb/clans/list/?application_id=${wargamingApplicationId}&search=${clan}&limit=${limit}`,
`https://api.wotblitz.${server}/wotb/clans/list/?application_id=${WARGAMING_APPLICATION_ID}&search=${clan}&limit=${limit}`,
);
await interaction.editReply({
+2 -2
View File
@@ -7,7 +7,7 @@ import cmdName from '../core/interaction/cmdName.js';
import infoEmbed from '../core/interaction/infoEmbed.js';
import addServerChoices from '../core/options/addServerChoices.js';
import addUsernameOption from '../core/options/addUsernameOption.js';
import { wargamingApplicationId } from '../core/process/args.js';
import { WARGAMING_APPLICATION_ID } from '../core/process/args.js';
import { CommandRegistry } from '../events/interactionCreate.js';
import { AccountList } from '../types/accountList.js';
@@ -38,7 +38,7 @@ export default {
const trimmedSearch = name.trim();
const players = usernamePattern.test(trimmedSearch)
? await getWargamingResponse<AccountList>(
`https://api.wotblitz.${server}/wotb/account/list/?application_id=${wargamingApplicationId}&search=${encodeURIComponent(
`https://api.wotblitz.${server}/wotb/account/list/?application_id=${WARGAMING_APPLICATION_ID}&search=${encodeURIComponent(
trimmedSearch,
)}&limit=${limit}`,
)
+3 -3
View File
@@ -28,7 +28,7 @@ import addStatPeriodChoices, {
statPeriodNames,
} from '../core/options/addStatPeriodChoices.js';
import addUsernameOption from '../core/options/addUsernameOption.js';
import { wargamingApplicationId } from '../core/process/args.js';
import { WARGAMING_APPLICATION_ID } from '../core/process/args.js';
import render from '../core/ui/render.js';
import { CommandRegistry } from '../events/interactionCreate.js';
import {
@@ -53,10 +53,10 @@ export default {
const period = interaction.options.getString('period') as StatPeriod;
const { id, server } = await getBlitzAccount(interaction);
const accountInfo = await getWargamingResponse<AccountInfo>(
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${wargamingApplicationId}&account_id=${id}`,
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
);
const clanData = await getWargamingResponse<PlayerClanData>(
`https://api.wotblitz.${server}/wotb/clans/accountinfo/?application_id=${wargamingApplicationId}&account_id=${id}&extra=clan`,
`https://api.wotblitz.${server}/wotb/clans/accountinfo/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}&extra=clan`,
);
const tankStats = await getTankStats(interaction, server, id);
let stats: AllStats;
+2 -2
View File
@@ -33,7 +33,7 @@ import addStatPeriodChoices, {
} from '../core/options/addStatPeriodChoices.js';
import addTankChoices from '../core/options/addTankChoices.js';
import addUsernameOption from '../core/options/addUsernameOption.js';
import { wargamingApplicationId } from '../core/process/args.js';
import { WARGAMING_APPLICATION_ID } from '../core/process/args.js';
import render from '../core/ui/render.js';
import { CommandRegistry } from '../events/interactionCreate.js';
import { AccountInfo, AllStats } from '../types/accountInfo.js';
@@ -59,7 +59,7 @@ export default {
const blitzAccount = await getBlitzAccount(interaction);
const { id, server } = blitzAccount;
const accountInfo = await getWargamingResponse<AccountInfo>(
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${wargamingApplicationId}&account_id=${id}`,
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
);
const tankStats = await getTankStats(interaction, server, id);
let stats: AllStats;
+3 -3
View File
@@ -24,7 +24,7 @@ import cmdName from '../core/interaction/cmdName.js';
import fullBlitzStarsStats from '../core/interaction/fullBlitzStarsStats.js';
import { supportBlitzStars } from '../core/interaction/supportBlitzStars.js';
import addUsernameOption from '../core/options/addUsernameOption.js';
import { wargamingApplicationId } from '../core/process/args.js';
import { WARGAMING_APPLICATION_ID } from '../core/process/args.js';
import render from '../core/ui/render.js';
import { CommandRegistry } from '../events/interactionCreate.js';
import { AccountInfo, AllStats } from '../types/accountInfo.js';
@@ -50,10 +50,10 @@ export default {
new Date().getTime() / 1000,
);
const accountInfo = await getWargamingResponse<AccountInfo>(
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${wargamingApplicationId}&account_id=${id}`,
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
);
const clanData = await getWargamingResponse<PlayerClanData>(
`https://api.wotblitz.${server}/wotb/clans/accountinfo/?application_id=${wargamingApplicationId}&account_id=${id}&extra=clan`,
`https://api.wotblitz.${server}/wotb/clans/accountinfo/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}&extra=clan`,
);
const careerTankStatsRaw = await getTankStats(interaction, server, id);
const careerStats: Record<number, AllStats> = {
+3 -3
View File
@@ -7,7 +7,7 @@ import getBlitzAccount from '../core/blitz/getBlitzAccount.js';
import getWargamingResponse from '../core/blitz/getWargamingResponse.js';
import cmdName from '../core/interaction/cmdName.js';
import addUsernameOption from '../core/options/addUsernameOption.js';
import { wargamingApplicationId } from '../core/process/args.js';
import { WARGAMING_APPLICATION_ID } from '../core/process/args.js';
import { CommandRegistry } from '../events/interactionCreate.js';
import { AccountInfo } from '../types/accountInfo.js';
import { PlayerClanData } from '../types/playerClanData.js';
@@ -26,10 +26,10 @@ export default {
const blitzAccount = await getBlitzAccount(interaction);
const { id, server } = blitzAccount;
const accountInfo = await getWargamingResponse<AccountInfo>(
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${wargamingApplicationId}&account_id=${id}`,
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
);
const clanData = await getWargamingResponse<PlayerClanData>(
`https://api.wotblitz.${server}/wotb/clans/accountinfo/?application_id=${wargamingApplicationId}&account_id=${id}&extra=clan`,
`https://api.wotblitz.${server}/wotb/clans/accountinfo/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}&extra=clan`,
);
const clan = clanData[id]?.clan;
const clanTag = clan ? ` [${clan!.tag}]` : '';
+2 -2
View File
@@ -1,7 +1,7 @@
import { CacheType, ChatInputCommandInteraction } from 'discord.js';
import { BLITZ_SERVERS, BlitzServer } from '../../constants/servers.js';
import { TanksStats } from '../../types/tanksStats.js';
import { wargamingApplicationId } from '../process/args.js';
import { WARGAMING_APPLICATION_ID } from '../process/args.js';
import errorWithCause from '../process/errorWithCause.js';
import getWargamingResponse from './getWargamingResponse.js';
@@ -11,7 +11,7 @@ export default async function getTankStats(
id: number,
) {
const tankStats = await getWargamingResponse<TanksStats>(
`https://api.wotblitz.${server}/wotb/tanks/stats/?application_id=${wargamingApplicationId}&account_id=${id}`,
`https://api.wotblitz.${server}/wotb/tanks/stats/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
);
if (tankStats[id] === null) {
+4 -4
View File
@@ -1,6 +1,6 @@
import { BlitzServer } from '../../constants/servers.js';
import { Account, AccountList } from '../../types/accountList.js';
import { wargamingApplicationId } from '../process/args.js';
import { WARGAMING_APPLICATION_ID } from '../process/args.js';
import getWargamingResponse from './getWargamingResponse.js';
export type AccountListWithServer = (Account & {
@@ -19,7 +19,7 @@ export default async function listAccountsPanServer(search: string, limit = 9) {
return (
await Promise.all([
getWargamingResponse<AccountList>(
`https://api.wotblitz.com/wotb/account/list/?application_id=${wargamingApplicationId}&search=${encodedSearch}&limit=${normalizedLimit}`,
`https://api.wotblitz.com/wotb/account/list/?application_id=${WARGAMING_APPLICATION_ID}&search=${encodedSearch}&limit=${normalizedLimit}`,
).then(
(value) =>
value &&
@@ -29,7 +29,7 @@ export default async function listAccountsPanServer(search: string, limit = 9) {
})),
),
getWargamingResponse<AccountList>(
`https://api.wotblitz.eu/wotb/account/list/?application_id=${wargamingApplicationId}&search=${encodedSearch}&limit=${normalizedLimit}`,
`https://api.wotblitz.eu/wotb/account/list/?application_id=${WARGAMING_APPLICATION_ID}&search=${encodedSearch}&limit=${normalizedLimit}`,
).then(
(value) =>
value &&
@@ -39,7 +39,7 @@ export default async function listAccountsPanServer(search: string, limit = 9) {
})),
),
getWargamingResponse<AccountList>(
`https://api.wotblitz.asia/wotb/account/list/?application_id=${wargamingApplicationId}&search=${encodedSearch}&limit=${normalizedLimit}`,
`https://api.wotblitz.asia/wotb/account/list/?application_id=${WARGAMING_APPLICATION_ID}&search=${encodedSearch}&limit=${normalizedLimit}`,
).then(
(value) =>
value &&
+4 -4
View File
@@ -1,6 +1,6 @@
import { BlitzServer } from '../../constants/servers.js';
import { Clan, ClanList } from '../../types/clanList.js';
import { wargamingApplicationId } from '../process/args.js';
import { WARGAMING_APPLICATION_ID } from '../process/args.js';
import getWargamingResponse from './getWargamingResponse.js';
export type ClanListWithServer = (Clan & {
@@ -15,7 +15,7 @@ export default async function listClansPanServer(search: string, limit = 9) {
return (
await Promise.all([
getWargamingResponse<ClanList>(
`https://api.wotblitz.com/wotb/clans/list/?application_id=${wargamingApplicationId}&search=${search}&limit=${normalizedLimit}`,
`https://api.wotblitz.com/wotb/clans/list/?application_id=${WARGAMING_APPLICATION_ID}&search=${search}&limit=${normalizedLimit}`,
).then(
(value) =>
value &&
@@ -25,7 +25,7 @@ export default async function listClansPanServer(search: string, limit = 9) {
})),
),
getWargamingResponse<ClanList>(
`https://api.wotblitz.eu/wotb/clans/list/?application_id=${wargamingApplicationId}&search=${search}&limit=${normalizedLimit}`,
`https://api.wotblitz.eu/wotb/clans/list/?application_id=${WARGAMING_APPLICATION_ID}&search=${search}&limit=${normalizedLimit}`,
).then(
(value) =>
value &&
@@ -35,7 +35,7 @@ export default async function listClansPanServer(search: string, limit = 9) {
})),
),
getWargamingResponse<ClanList>(
`https://api.wotblitz.asia/wotb/clans/list/?application_id=${wargamingApplicationId}&search=${search}&limit=${normalizedLimit}`,
`https://api.wotblitz.asia/wotb/clans/list/?application_id=${WARGAMING_APPLICATION_ID}&search=${search}&limit=${normalizedLimit}`,
).then(
(value) =>
value &&
+4 -6
View File
@@ -1,11 +1,9 @@
console.log(process.env);
export const DISCORD_TOKEN = process.env.DISCORD_TOKEN!;
export const WARGAMING_APPLICATION_ID = process.env.WARGAMING_APPLICATION_ID!;
export const discordToken = process.env.DISCORD_TOKEN!;
export const wargamingApplicationId = process.env.WARGAMING_APPLICATION_ID!;
if (!discordToken) {
if (!DISCORD_TOKEN) {
throw new Error('No Discord token provided');
}
if (!wargamingApplicationId) {
if (!WARGAMING_APPLICATION_ID) {
throw new Error('No Wargaming application id provided}');
}
+2 -2
View File
@@ -27,7 +27,7 @@ import tankstats from '../commands/tankstats.js';
import today from '../commands/today.js';
import verify from '../commands/verify.js';
import negativeEmbed from '../core/interaction/negativeEmbed.js';
import { discordToken } from '../core/process/args.js';
import { DISCORD_TOKEN } from '../core/process/args.js';
import getClientId from '../core/process/getClientId.js';
import isDev from '../core/process/isDev.js';
import { handleError } from './error.js';
@@ -42,7 +42,7 @@ export interface CommandRegistry {
autocomplete?: (interaction: AutocompleteInteraction<CacheType>) => void;
}
const rest = new REST().setToken(discordToken);
const rest = new REST().setToken(DISCORD_TOKEN);
const commands = [
debug,
+2 -2
View File
@@ -1,5 +1,5 @@
import { Client, GatewayIntentBits } from 'discord.js';
import { discordToken } from './core/process/args.js';
import { DISCORD_TOKEN } from './core/process/args.js';
import { registerErrorHandlers } from './events/error.js';
import guildMemberAdd from './events/guildMemberAdd.js';
import interactionCreate from './events/interactionCreate.js';
@@ -13,4 +13,4 @@ export const client = new Client({
.on('interactionCreate', interactionCreate);
registerErrorHandlers();
client.login(discordToken);
client.login(DISCORD_TOKEN);