BREAKING: node migration + major improvements and style changes (#2783)

* Setup turborepo (#2610)

* chore: BREAKING move to monorepo structure

* chore: setup turborepo

* setup more eslint and tsconfig (#2612)

* fix packages setting lcoation

* add dist to ignore

* style

* fix: .vscode set prettier and remove deno configs (#2611)

* fix: rewrite to process.env

* chore: add node types

* style: run eslint --fix

* fix: tests import ext

* chore: fix formatter

* chore: add build script

* chore: remove site from turborepo

* chore: move to seperate packages

* chore: seperate util

* chore: rename to index

* fix: utils

* chore: bump typescript

* fix: in process of fixing rest

* fix: logger

* style

* chore: fix turbo script

* fix: types

* fix: types

* fix: shard

* fix: gateway

* fixing: bot

* fix: at least it can run now

* chore: fix turbo script

* chore: move plugins

* chore: add type and utils export

* chore: working bot type and cache plugin

* Add git hooks (#2618)

* CI: Setup ci (#2669)

* ci: fix test

* ci: fix typo

* fix: turbo script

* fixes: yarn and linter errors in embeds pkg

* chore: fix yarn gitignore

* Node migration - devcontainer (#2672)

*  - feat: devcontainer -> node

* 👷‍♂ - ci: devcontainer - add tabnine, prettier

* fix: ignore .env and debug.ts

* fix: couple of linter errors

* fix: linter error

* fix: gateway linter errors

* style: update style

* style: fix bot style

* fix: type

* ci: move all old workflow

* chore: close #2619

* chore: close #2671

* test: add mocha

* chore: add typescript plugin

* test: add mocha

* test: add test to utils

* test/ci: update ci and coverage

* chore: change script naming

* ci: update include test

* test: add coverage

* ci: fix cache

* ci: fix ci and codecov

* Discordeno Documentation  (#2673)

* Add git hooks

* Add documentation generatation

* Change Documentation Engine

* Add documentation

* Remove autogenerated docs

* combine lint staged action into one

* style: fix

Co-authored-by: H01001000 <heiheiho000@gmail.com>

* chore: new package client

* test: add rest test

* ci: enable codecov

* fix: type

* test: add test to all packages

* ci: add release to gh per commit

* fix: ci syntax

* fix: package version

* fix: publish script

* fix: remove private from gateway

* ci: add filter for changes

* fix: ci syntex

* ci: try fix path filter

* ci: try fix path filter

* test: add test

* ci: fix string and  boolean

* fix: package and ci

* chore: fix turbo type cache

* ci: also publish to npm

* ci: change to public

* fix: not publish to npm

* fix: dependencies

* chore: fix fmt script

* fix: better rest typecheck Closes #2621

* fix: run yarn install

* feat: add transformers to rest

* feat: add helpers to rest

* test: move bot utils test

* reverse change to release.yml

* chore: add clean build

* refactor: discordeno

* chore: add import type

* chore: remove bot

* fix: change deps from bot to dd

* chore: update yarn lock

* test: temp remove test from logger

* refactor: remove transformers in helpers/channel

* type: close #2622

* ci(fix): explicitly define coverage file

* refactor: remove transformers in helpers/emoji

* type: fix discord guild type

* feat: DiscordEditAutomoderationRule type

* fix: remove unused type

* feat: DiscordCreateGuildEmoji DiscordModifyGuildEmoji & DiscordModifyCHannel types

* feat: DiscordCreateChannel DiscordBuDeleteMessages DiscordCreateMessage DiscordEditMessage

* feat: DiscordCreateScheduledEvent EditScheduledEvent DiscordCreateInvite

* fix: types for guild stuff for rest

* feat: thread discord types for rest

* feat: channel rest types

* feat: member rest types

* feat: more discord rest types

* fix: type errors

* fix: docs bot param name should be rest

* type: fix type error

* ci(fix): codecov

* chore(client) :add export transformer

* fix: verifySignature

* test: fix types

* test: add test prevent #2683 #2678

* fix: export transformer twice

* ci: reuse cache

* test: add test:unit-noTextCoverage

* feat: add transform and constant package

* fix: half fix #2683 #2688

* fix: #2688 fix all transformer.spec.ts

* fix: transformer name

* ci: update style

* fix: dependencies

* fix: naming

* fix: yarn lock

* fix: remove validations from helpers. Closes #2700

* fix: rest routes as a constants pkg

* fix: esm import with .js

* test: add exception case

* feat: adding transformer

* chore: change script name

* chore: add path fixing to coverage file

* fix: camelize tuple bug

* fix: reverse transformers

* fix: transformers folder to camel

* fix: transformers as an object

* fix: linter error

* ci: run test with deno close #2701

* fix: test depends on build

* fix: deno import node:crypto

* fix: rest improvements

* fix: channel type

* fix: export user

* chore: move to unit dir

* test: moving bench

* fix: remove transformers from rest package

* fix: move toggle transformers to bot pkg

* fix: move out gw helpers to gw package

* test: add rest e2e test

* fix: syntex

* ci: add discord token

* fix: ci not passing secret

* test: add role test

* ci: fix secret inherit

* fix: role helpers transformer

* test: increase timeout to 10s

* fix: member helpers transformer

* test: add member test

* fix: name and type

* fix: guild ban

* test: fix test

* fix: test add await

* test: skip some test

* test: increase timeout

* chore: add transformer to import map

* fix: test

* test: add why-is-node-still-running

* test: add debug hook

* ci: add timeout incase any async running

* test: try fix

* test: turn on rest debug

* fix: if undefined

* test: reduce timeout

* fix: queue not running after some request

* fix: increase remaining after request without ratelimit header

* fix: partial webhook

* fix: fetch hooks not working if debug defined later

* fix: nickname null to undefined

* test: finish adding webhook test

* refactor(test): move rest to utils

* fix: add await

* fix: sticker

* feat: add message embed component transformer

* fix: test not done

* fix: arg type to bigString

* fix: sendMessage

* fix: add allowedMentions, interactionResponse

* test: add emoji e2e test

* test: add guild e2e test

* refactor(test): remove extra rest call

* fix: create emoji BINARY_TYPE_INVALID_DATA_URI

* fix: create guild rate limit

* fix: automode rule helpers and test

* fix: test run in only

* test: add some queue bucket test

* test: remove empty test

* refactor(test): use new guild

* test: use new guild for other test

* fix: guild not defind

* reactor(test): remove duplicated creat channel

* test: increase timeout to 30s

* test: add thread test

* fix: more transformers

* fix: gateway helpers use transformers

* fix: types belong in types pkg

* fix: helpers use transformers

* BREAKING: v19 rewrite to node + major improvements (#2703)

* fix: move all to old folder

* fix: cleanup types

* fix: more cleanup

* fix: more base cleanup

* fix: token dotenv

* fix: add base transformer

* fix: partial error handling

* fix: handle 429 rate limit

* test(rest): fix unit test

* fix(script): transform extension

* test: fix error and buffer

* feat: camelizer util

* fix: cleanup

* fix: rate limit queues and headers processing

* fix: rest exports

* fix: no more transformers

* fix: queue header null bug

* fix: add gateway package base

* fix: lint error

* fix: add prettier file

* fix: prettier is default fmtr

* fix: fmt shard file

* fix: fmt

* fix: types issue

* fix: remove unused consts

* fix: all import issues

* fix: import error

* fix: import ending with .js

* fix: remove transformers package

* Fix eslint (#2710)

* fix: typing of button component label to be optional (#2708)

* feat: add guild_connections to role tags and toggles (#2706)

Co-authored-by: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com>

* Add lint checks and autofixing workflow (#2702)

* Add lint checks and autofixing workflow

* Update lint.yml

* Fix: use yarn instead npm

* fix: add ts to eslint_extensions

* fix: update dir

* fix: lint.yml format

Co-authored-by: Jonathan Ho <heiheiho000@gmail.com>

* fix: unused deps

* ci: fix e2e test not running

* chore: run yarn install

* test: this should run test

* feat: getCHannel

* feat: createEMji helper

* feat: collection class in util package

* fix: gateway bugs

* why on earth is this needed change

* fix: cleanup docs on collection

* Emoji rest methods (node-migration-clean) (#2713)

* feat: all emoji rest methods

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: stuff

* fix: bot types

* fix: remove logs

* fix: camelize all gateway payloads

* fix: remove todos

* fix: start deris

* fix: lint/ts errors except shard file

* thats 1 way to fix type errors

* yes (#2714)

Co-authored-by: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com>

* feat: rest channel helpers

* Update release.yml

* Update release.yml

* ci: add build filter

* ci: fail fast false

* fix: complete webhook related helpers

* fix: follow announcement helper

* add forum helper

* add stage helpers

* add thread related helpers

* alphabetize

* cleanup webhook routes

* automod helpers

* scheduled events

* integrations helpers

* invite stuff incomplete

* dm channel and avatar url

* chore: move ts-node into package

* fix: importing esm

* fix: tris message helpers

* test(rest): add simplifyUrl test

* test(rest): add checkRateLimits test

* test(rest): add processRateLimitedPaths test

* test(rest): fix missing beforeEach

* test(utils): enable old test

* interaction helpers

* perf(utils): optimize snake to camel case conversion (#2717)

* perf(utils): optimize snake to camel case conversion

* fmt

* wont change much but still faster

* actually this was a stupid idea

* shh

* Fix(client): Fix typings. (#2716)

Co-authored-by: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com>

* test: fix rest and utils test (#2723)

* test(utils): fix  cant import collection

* test(rest): await expect

* fix(utils): deno compactability

* test(utils): typing

* fix(utils): add return type

* Add rest helpers for templates (#2727)

* Add rest helpers for templates

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: remove frozenAt

* fix: cleanup templates

* ci: release to npm (#2725)

* ci: release to npm

* Update release.yml

* 🐛 - fix: types - slashcommands - add nsfw prop (#2731)

* feat(rest helpers): Add template and member helpers. (#2728)

* feat(rest helpers): Add template and member helpers.

* format code

* feat(rest): add template routes

* fix(rest): routes and runMethod

* fix(rest): try to fix most of type

Co-authored-by: H01001000 <heiheiho000@gmail.com>
Co-authored-by: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com>

* ci: fix release (#2732)

* fix: rest type errors

* fix: v19 begin

* fix: yarn lock

* chore: fix deps and script (#2733)

* fix: bug camelizer deleting letters

* fix: falsy token check

* fix: add frozenat check for queue

* fix: max stack trace error do to infinite loop

* fix: type error

* test(rest): fix missing import (#2734)

Co-authored-by: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com>

* fix: file paths for imports

* fix: lastShardId should default to 0

* fix: use isomorphic ws

* test(rest): fix "TypeError: [Function] is not a thenable" (#2736)

* test(utils): add utils tests (#2737)

* test(utils): add urltobase64 test

* test(utils): add token test

* test(utils): fix missing import buffer

* test(utils): add casting test

* test(utils): add casting test

* test(utils): fix use correct function

* chore: make eslint error if missing .js extension (#2735)

* chore: eslint error if missing .js extension

* chore

* lint: fix missing .js error

Co-authored-by: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com>

* fix: readme runtime list (#2739)

* Bot pkg (#2740)

* fix: bot pkg test

* Fix code style issues with ESLint

* Update Guild.ts

* Update Guild.ts

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>
Co-authored-by: Jonathan Ho <heiheiho000@gmail.com>

* Update tsdoc.json (#2741)

Updates tsdoc.json to reflect the current packages.

* Interaction types - remove member,channel,role from value type (#2743)

https://discord.com/channels/785384884197392384/1067265182776176690/1068189883073572924

* Add missing types (#2742)

* Revert "fix: use isomorphic ws" (#2744)

This reverts commit ad306b0d0a.

* fix: interaction requests that sent without full url

* fix: lint issues

* fix: remote gateway test file

* fix: interaction response bug with body being invalid (#2746)

* fix: readme runtime list

* Fix code style issues with ESLint

* node 18

* fix: websocket import type

* fix: body for interaction requests

---------

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: interaction followup type (#2747)

* fix: readme runtime list

* Fix code style issues with ESLint

* node 18

* fix: websocket import type

* fix: body for interaction requests

* fix: perma fix for type error in ci

* fix: followupmessage option type

---------

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: e2e exit bug (#2748)

* fix: readme runtime list

* Fix code style issues with ESLint

* node 18

* fix: websocket import type

* fix: body for interaction requests

* fix: perma fix for type error in ci

* fix: followupmessage option type

* fix: e2e tests exit bug

* fix: color console logger

---------

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: rest sending attachments files (#2749)

* fix: readme runtime list

* Fix code style issues with ESLint

* node 18

* fix: websocket import type

* fix: body for interaction requests

* fix: perma fix for type error in ci

* fix: followupmessage option type

* fix: e2e tests exit bug

* fix: color console logger

* fix: image file sending

* Fix code style issues with ESLint

---------

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: guild and role methods (#2751)

* fix: readme runtime list

* Fix code style issues with ESLint

* node 18

* fix: websocket import type

* fix: body for interaction requests

* fix: perma fix for type error in ci

* fix: followupmessage option type

* fix: e2e tests exit bug

* fix: color console logger

* fix: image file sending

* Fix code style issues with ESLint

* guild and role methods

* Fix code style issues with ESLint

---------

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* ci: add bot package (#2752)

* ci: add bot package

* ci: fix test

* e2e test stuff (#2754)

* fix: readme runtime list

* Fix code style issues with ESLint

* node 18

* fix: websocket import type

* fix: body for interaction requests

* fix: perma fix for type error in ci

* fix: followupmessage option type

* fix: e2e tests exit bug

* fix: color console logger

* fix: image file sending

* Fix code style issues with ESLint

* guild and role methods

* Fix code style issues with ESLint

* fix: dont send heartbeat if socket is not open

* fix: remove logs

* fox: remove more logs

* fix some bugs in role tests

* Switch to after hook style

* hoti's speed snaker

* auto convert objects for discord

* Fix code style issues with ESLint

* fix: remove dup imports

* fix: i hate linters

* speeder

---------

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: delete guilds test (#2758)

* fix: readme runtime list

* Fix code style issues with ESLint

* node 18

* fix: websocket import type

* fix: body for interaction requests

* fix: perma fix for type error in ci

* fix: followupmessage option type

* fix: e2e tests exit bug

* fix: color console logger

* fix: image file sending

* Fix code style issues with ESLint

* guild and role methods

* Fix code style issues with ESLint

* fix: dont send heartbeat if socket is not open

* fix: remove logs

* fox: remove more logs

* fix some bugs in role tests

* Switch to after hook style

* hoti's speed snaker

* auto convert objects for discord

* Fix code style issues with ESLint

* fix: remove dup imports

* fix: i hate linters

* speeder

* fix: tests delete guilds

* Fix code style issues with ESLint

---------

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* chore: fix deps (#2757)

* ci/test: fix bot pkg e2e test (#2759)

* chore: fix script and update import map (#2761)

* chore: fix version script

* chore: update import map

* chore: fix ws import map

* chore: fix deno import map

* test: fix

* fix: more rest e2e tests (#2763)

* fix: readme runtime list

* Fix code style issues with ESLint

* node 18

* fix: websocket import type

* fix: body for interaction requests

* fix: perma fix for type error in ci

* fix: followupmessage option type

* fix: e2e tests exit bug

* fix: color console logger

* fix: image file sending

* Fix code style issues with ESLint

* guild and role methods

* Fix code style issues with ESLint

* fix: dont send heartbeat if socket is not open

* fix: remove logs

* fox: remove more logs

* fix some bugs in role tests

* Switch to after hook style

* hoti's speed snaker

* auto convert objects for discord

* Fix code style issues with ESLint

* fix: remove dup imports

* fix: i hate linters

* speeder

* fix: tests delete guilds

* Fix code style issues with ESLint

* fix: easier to provide custom intents in bot

* fix: shutdown bot after test

* fix: add getGuild

* fix: multiple guild delete attempts

* fix: add emoji e2e tests

* fix: remaining old e2e rest tests

* Fix code style issues with ESLint

---------

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* test: add gateway integration test (#2756)

* test: add gateway integration test

* test(gateway): fix connection test

* test(gateway): add heartbeat test

* ci: add integration test

* fix: add uWebSockets.js

* ci: add timeout

* test(utils): remove old test

* Revert "test(utils): remove old test"

This reverts commit 04fb6dd4b5.

* test(gateway): fix uws server

* test(gateway): fix type

* chore: update codecov flag

* test(gateway): remove dev code

---------

Co-authored-by: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com>

* Update release.yml (#2768)

* fix: bot logger (#2769)

* fix: readme runtime list

* Fix code style issues with ESLint

* node 18

* fix: websocket import type

* fix: body for interaction requests

* fix: perma fix for type error in ci

* fix: followupmessage option type

* fix: e2e tests exit bug

* fix: color console logger

* fix: image file sending

* Fix code style issues with ESLint

* guild and role methods

* Fix code style issues with ESLint

* fix: dont send heartbeat if socket is not open

* fix: remove logs

* fox: remove more logs

* fix some bugs in role tests

* Switch to after hook style

* hoti's speed snaker

* auto convert objects for discord

* Fix code style issues with ESLint

* fix: remove dup imports

* fix: i hate linters

* speeder

* fix: tests delete guilds

* Fix code style issues with ESLint

* fix: easier to provide custom intents in bot

* fix: shutdown bot after test

* fix: add getGuild

* fix: multiple guild delete attempts

* fix: add emoji e2e tests

* fix: remaining old e2e rest tests

* Fix code style issues with ESLint

* fix: add bot.logger

* fix: make logger name capital

---------

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* chore: update readme (#2772)

* chore: add coverage per pkg

* chore: add npm version

* chore: add test status

* chore: fix ci

* chore: fix ci

* ci: fix ci needs

* chore: add only push event

* style: remove import logger

* 📚 - docs: fix README package links (#2773)

* test(all): add test importing index (#2774)

* test(all): add test importing index

* chore: remove old benchmark dir

* chore: disable coverage status fail

* test(client): add import test with try catch

* test(rest): fix narrow import scope

* test(utils): add test (#2764)

* test(utils): remove old test

* test(utils): add color test

* test(utils): fix import mocha

* test(utils): fix test type error

* test(utils): remove dev code

* fix(utils): bucket not export all function

* test(utils): add some test for bucket

* fix(utils): close #2775

* test(utils): add test for permissions.ts

* test(utils): fix missing mocha import

* fix(utils): better fix for #2775

* feat: addReaction & addReactions

* feat: connectToVoice

* fix: linters issues

* fix: remove aliases and add createGuildFromTemplate

* feat: deleteMessages

* fix: reaction related helpers

* mfa level

* voie states editing

* image urls

* fix: typos

* get message typeguards

* fix: more helpers

* fix: remaining helpers

* fix: add logs to gateway manager

* fix: rest resolve sends status and body

* fix: lots of errors

* fix: client errors

* fix: remove old pkg

* snaker

* fix: broken util import for image url

* fix: cleanup shard and circular deps

* fix: remove ThreadChannel from GuildChannel

* fix: generate interaction usage

* fix: more bugs

* fix: use node:events to import

* fix(rest): add interface RestRequestRejection (#2782)

* fix: remove invalid todo

* fix: timeout bug

---------

Co-authored-by: Skillz <skillz@discord.gg/ddeno>
Co-authored-by: Jonathan Ho <heiheiho000@gmail.com>
Co-authored-by: deepsarda <92147339+deepsarda@users.noreply.github.com>
Co-authored-by: Awesome Stickz <awesome@stickz.dev>
Co-authored-by: Lint Action <lint-action@samuelmeuli.com>
Co-authored-by: Lars_und_so <46791248+Larsundso@users.noreply.github.com>
Co-authored-by: ITOH <to@itoh.at>
Co-authored-by: Yaikava <83710104+Yaikava@users.noreply.github.com>
Co-authored-by: Andreas Fink <mail@afink.dev>

---------

Co-authored-by: Jonathan Ho <48591478+H01001000@users.noreply.github.com>
Co-authored-by: H01001000 <heiheiho000@gmail.com>
Co-authored-by: deepsarda <92147339+deepsarda@users.noreply.github.com>
Co-authored-by: Yaikava <83710104+Yaikava@users.noreply.github.com>
Co-authored-by: Skillz <skillz@discord.gg/ddeno>
Co-authored-by: Awesome Stickz <awesome@stickz.dev>
Co-authored-by: Lint Action <lint-action@samuelmeuli.com>
Co-authored-by: Lars_und_so <46791248+Larsundso@users.noreply.github.com>
Co-authored-by: ITOH <to@itoh.at>
Co-authored-by: Andreas Fink <mail@afink.dev>
This commit is contained in:
Skillz4Killz
2023-02-20 15:00:00 -06:00
committed by GitHub
co-authored by H01001000 Lint Action Skillz deepsarda Awesome Stickz Lars_und_so ITOH Yaikava Andreas Fink Jonathan Ho
parent 1a717ddc7d
commit 2714e1e7d1
1057 changed files with 53134 additions and 55520 deletions
+3
View File
@@ -0,0 +1,3 @@
import { Buffer } from 'node:buffer'
export const fakeToken = `${Buffer.from('1033452747380494366', 'base64').toString()}.zawsxedcrftvgybhu`
+281
View File
@@ -0,0 +1,281 @@
import type { Camelize, DiscordChannel, DiscordGuild } from '@discordeno/types'
import {
AutoModerationActionType,
AutoModerationEventTypes,
AutoModerationTriggerTypes
} from '@discordeno/types'
import { expect } from 'chai'
import { e2ecache, rest } from './utils.js'
before(async () => {
if (!e2ecache.guild) {
e2ecache.guild = await rest.createGuild({
name: 'Discordeno-test',
})
}
})
after(async () => {
if (rest.invalidBucket.timeoutId) clearTimeout(rest.invalidBucket.timeoutId)
if (e2ecache.guild.id && !e2ecache.deletedGuild) {
e2ecache.deletedGuild = true;
await rest.deleteGuild(e2ecache.guild.id)
}
})
describe('[automod] Run automod tests', async () => {
it('[automod] Create a MessageSend rule for Keyword with BlockMessage action.', async () => {
const rule = await rest.createAutomodRule(e2ecache.guild.id, {
name: 'test',
eventType: AutoModerationEventTypes.MessageSend,
triggerType: AutoModerationTriggerTypes.Keyword,
triggerMetadata: {
keywordFilter: ['iblamewolf']
},
actions: [
{
type: AutoModerationActionType.BlockMessage
}
]
})
expect(rule.id).to.be.exist
const fetchedRule = await rest.getAutomodRule(e2ecache.guild.id, rule.id)
expect(fetchedRule.id).to.be.exist
expect(fetchedRule.name).to.equal(rule.name)
expect(fetchedRule.eventType).to.equal(
AutoModerationEventTypes.MessageSend
)
expect(fetchedRule.triggerType).to.equal(
AutoModerationTriggerTypes.Keyword
)
expect(fetchedRule.triggerMetadata?.keywordFilter?.[0]).to.equal(
'iblamewolf'
)
expect(fetchedRule.actions).to.be.exist
expect(fetchedRule.actions[0]).to.be.exist
expect(fetchedRule.actions[0].type).to.equal(
AutoModerationActionType.BlockMessage
)
await rest.deleteAutomodRule(e2ecache.guild.id, rule.id)
})
it('[automod] Create a MessageSend rule for Keyword with Timeout action.', async () => {
const rule = await rest.createAutomodRule(e2ecache.guild.id, {
name: 'test',
eventType: AutoModerationEventTypes.MessageSend,
triggerType: AutoModerationTriggerTypes.Keyword,
triggerMetadata: {
keywordFilter: ['iblamewolf']
},
actions: [
{
type: AutoModerationActionType.Timeout,
metadata: {
durationSeconds: 10
}
}
]
})
expect(rule.id).to.be.exist
const fetchedRule = await rest.getAutomodRule(e2ecache.guild.id, rule.id)
expect(fetchedRule.id).to.be.exist
expect(fetchedRule.name).to.equal(rule.name)
expect(fetchedRule.eventType).to.equal(
AutoModerationEventTypes.MessageSend
)
expect(fetchedRule.triggerType).to.equal(
AutoModerationTriggerTypes.Keyword
)
expect(fetchedRule.triggerMetadata?.keywordFilter?.[0]).to.equal(
'iblamewolf'
)
expect(fetchedRule.actions).to.be.exist
expect(fetchedRule.actions[0]).to.be.exist
expect(fetchedRule.actions[0].type).to.equal(
AutoModerationActionType.Timeout
)
expect(fetchedRule.actions[0].metadata?.durationSeconds).to.equal(10)
await rest.deleteAutomodRule(e2ecache.guild.id, rule.id)
})
it('[automod] Create a MessageSend rule for Keyword with BlockMessage & Timeout action.', async () => {
const rule = await rest.createAutomodRule(e2ecache.guild.id, {
name: 'test',
eventType: AutoModerationEventTypes.MessageSend,
triggerType: AutoModerationTriggerTypes.Keyword,
triggerMetadata: {
keywordFilter: ['iblamewolf']
},
actions: [
{
type: AutoModerationActionType.BlockMessage
},
{
type: AutoModerationActionType.Timeout,
metadata: {
durationSeconds: 10
}
}
]
})
expect(rule.id).to.be.exist
await rest.deleteAutomodRule(e2ecache.guild.id, rule.id)
})
describe('with a channel', () => {
let channel: Camelize<DiscordChannel>
beforeEach(async () => {
channel = await rest.createChannel(e2ecache.guild.id, {
name: 'test'
})
})
afterEach(async () => {
await rest.deleteChannel(channel.id)
})
it('[automod] Create a MessageSend rule for Keyword with SendAlertMessage action.', async () => {
const rule = await rest.createAutomodRule(e2ecache.guild.id, {
name: 'test',
eventType: AutoModerationEventTypes.MessageSend,
triggerType: AutoModerationTriggerTypes.Keyword,
triggerMetadata: {
keywordFilter: ['iblamewolf']
},
actions: [
{
type: AutoModerationActionType.SendAlertMessage,
metadata: {
channelId: channel.id
}
}
]
})
expect(rule.id).to.be.exist
const fetchedRule = await rest.getAutomodRule(e2ecache.guild.id, rule.id)
expect(fetchedRule.id).to.be.exist
expect(fetchedRule.name).to.equal(rule.name)
expect(fetchedRule.eventType).to.equal(
AutoModerationEventTypes.MessageSend
)
expect(fetchedRule.triggerType).to.equal(
AutoModerationTriggerTypes.Keyword
)
expect(fetchedRule.triggerMetadata?.keywordFilter?.[0]).to.equal(
'iblamewolf'
)
expect(fetchedRule.actions).to.be.exist
expect(fetchedRule.actions[0]).to.be.exist
expect(fetchedRule.actions[0].type).to.equal(
AutoModerationActionType.SendAlertMessage
)
expect(fetchedRule.actions[0].metadata?.channelId).to.equal(channel.id)
await rest.deleteAutomodRule(e2ecache.guild.id, rule.id)
})
it('[automod] Create a MessageSend rule for Keyword with SendAlertMessage & Timeout action.', async () => {
const rule = await rest.createAutomodRule(e2ecache.guild.id, {
name: 'test',
eventType: AutoModerationEventTypes.MessageSend,
triggerType: AutoModerationTriggerTypes.Keyword,
triggerMetadata: {
keywordFilter: ['iblamewolf']
},
actions: [
{
type: AutoModerationActionType.SendAlertMessage,
metadata: {
channelId: channel.id
}
},
{
type: AutoModerationActionType.Timeout,
metadata: {
durationSeconds: 10
}
}
]
})
expect(rule.id).to.be.exist
await rest.deleteAutomodRule(e2ecache.guild.id, rule.id)
})
it('[automod] Create a MessageSend rule for Keyword with BlockMessage & SendAlertMessage & Timeout action.', async () => {
const rule = await rest.createAutomodRule(e2ecache.guild.id, {
name: 'test',
eventType: AutoModerationEventTypes.MessageSend,
triggerType: AutoModerationTriggerTypes.Keyword,
triggerMetadata: {
keywordFilter: ['iblamewolf']
},
actions: [
{
type: AutoModerationActionType.BlockMessage
},
{
type: AutoModerationActionType.SendAlertMessage,
metadata: {
channelId: channel.id
}
},
{
type: AutoModerationActionType.Timeout,
metadata: {
durationSeconds: 10
}
}
]
})
expect(rule.id).to.be.exist
// Get the rule again to make sure it was created correctly
const fetchedRule = await rest.getAutomodRule(e2ecache.guild.id, rule.id)
expect(fetchedRule.id).to.be.exist
expect(fetchedRule.name).to.equal(rule.name)
expect(fetchedRule.eventType).to.equal(
AutoModerationEventTypes.MessageSend
)
expect(fetchedRule.triggerType).to.equal(
AutoModerationTriggerTypes.Keyword
)
expect(fetchedRule.triggerMetadata?.keywordFilter?.[0]).to.equal(
'iblamewolf'
)
expect(fetchedRule.actions).to.be.exist
expect(fetchedRule.actions[0]).to.be.exist
expect(fetchedRule.actions[1].metadata).to.be.exist
expect(fetchedRule.actions[2].metadata).to.be.exist
expect(fetchedRule.actions[1].metadata.channelId).to.equal(channel.id)
expect(fetchedRule.actions[2].metadata.durationSeconds).to.equal(10)
expect(fetchedRule.actions[0].type).to.equal(
AutoModerationActionType.BlockMessage
)
expect(fetchedRule.actions[1].type).to.equal(
AutoModerationActionType.SendAlertMessage
)
expect(fetchedRule.actions[2].type).to.equal(
AutoModerationActionType.Timeout
)
await rest.deleteAutomodRule(e2ecache.guild.id, rule.id)
})
})
})
+9
View File
@@ -0,0 +1,9 @@
import dotenv from 'dotenv'
dotenv.config({ path: '../../.env' })
if (!process.env.DISCORD_TOKEN) throw new Error('Token was not provided.')
export const token = process.env.DISCORD_TOKEN
export const E2E_TEST_GUILD_ID = process.env.E2E_TEST_GUILD_ID!
if (!E2E_TEST_GUILD_ID) throw new Error('COMMUNITY guild id was not provided.')
+131
View File
@@ -0,0 +1,131 @@
import type { Camelize, DiscordEmoji } from '@discordeno/types'
import { urlToBase64 } from '@discordeno/utils'
import chai, { expect } from 'chai'
import chaiAsPromised from 'chai-as-promised'
import { after, afterEach, before, beforeEach, describe, it } from 'mocha'
import { e2ecache, rest } from './utils.js'
chai.use(chaiAsPromised)
before(async () => {
if (!e2ecache.guild) {
e2ecache.guild = await rest.createGuild({
name: 'Discordeno-test',
})
}
})
after(async () => {
if (rest.invalidBucket.timeoutId) clearTimeout(rest.invalidBucket.timeoutId)
if (e2ecache.guild.id && !e2ecache.deletedGuild) {
e2ecache.deletedGuild = true
await rest.deleteGuild(e2ecache.guild.id)
}
})
describe('Emoji helpers', () => {
describe('Create and delete', () => {
it('create an emoji', async () => {
const emoji = await rest.createEmoji(e2ecache.guild.id, {
name: 'blamewolf',
image: await urlToBase64('https://cdn.discordapp.com/emojis/814955268123000832.png'),
roles: [],
})
// Assertions
expect(emoji.id).to.be.exist
await rest.deleteEmoji(e2ecache.guild.id, emoji.id!)
})
// delete an emoji without a reason
it('delete an emoji without a reason', async () => {
const emoji = await rest.createEmoji(e2ecache.guild.id, {
name: 'blamewolf',
image: await urlToBase64('https://cdn.discordapp.com/emojis/814955268123000832.png'),
roles: [],
})
// Assertions
expect(emoji.id).to.be.exist
await rest.deleteEmoji(e2ecache.guild.id, emoji.id!)
await expect(rest.getEmoji(e2ecache.guild.id, emoji.id!)).to.eventually.rejected
})
// delete an emoji with a reason
it('delete an emoji with a reason', async () => {
const emoji = await rest.createEmoji(e2ecache.guild.id, {
name: 'blamewolf',
image: await urlToBase64('https://cdn.discordapp.com/emojis/814955268123000832.png'),
roles: [],
})
// Assertions
expect(emoji.id).to.be.exist
await rest.deleteEmoji(e2ecache.guild.id, emoji.id!, 'with a reason')
await expect(rest.getEmoji(e2ecache.guild.id, emoji.id!)).to.eventually.rejected
})
})
describe('edit and get', () => {
let emoji: Camelize<DiscordEmoji> & { id: string }
beforeEach(async () => {
emoji = (await rest.createEmoji(e2ecache.guild.id, {
name: 'blamewolf',
image: await urlToBase64('https://cdn.discordapp.com/emojis/814955268123000832.png'),
roles: [],
})) as Camelize<DiscordEmoji> & { id: string }
})
afterEach(async () => {
await rest.deleteEmoji(e2ecache.guild.id, emoji.id)
})
// edit an emoji name
it('Edit an emoji name', async () => {
await rest.editEmoji(e2ecache.guild.id, emoji.id, {
name: 'edited',
})
const edited = await rest.getEmoji(e2ecache.guild.id, emoji.id)
expect(edited.name).to.equal('edited')
})
// edit an emoji roles
it("Edit an emoji's roles", async () => {
const role = await rest.createRole(e2ecache.guild.id, {
name: 'dd-test-emoji',
})
await rest.editEmoji(e2ecache.guild.id, emoji.id, {
roles: [role.id],
})
const edited = await rest.getEmoji(e2ecache.guild.id, emoji.id)
expect(edited.roles?.length).to.equal(1)
})
// get an emoji
it('get an emoji', async () => {
const exists = await rest.getEmoji(e2ecache.guild.id, emoji.id)
expect(exists.id).to.be.exist
expect(emoji.id).to.equal(exists.id)
})
it('get all guild emojis', async () => {
await rest.createEmoji(e2ecache.guild.id, {
name: 'blamewolf2',
image: await urlToBase64('https://cdn.discordapp.com/emojis/814955268123000832.png'),
roles: [],
})
const exists = await rest.getEmojis(e2ecache.guild.id)
expect(exists.length).to.greaterThan(1)
})
})
})
+112
View File
@@ -0,0 +1,112 @@
import { ChannelTypes } from '@discordeno/types'
import { logger } from '@discordeno/utils'
import chai, { expect } from 'chai'
import chaiAsPromised from 'chai-as-promised'
import { after, describe, it } from 'mocha'
import { rest } from './utils.js'
chai.use(chaiAsPromised)
describe('Guild helpers', async () => {
// Delete the oldest guild(most likely to have finished tests).
it('Create and delete a guild', async () => {
logger.info('Create and delete a guild')
const guild = await rest.createGuild({
name: 'Discordeno-test',
})
logger.info('Guild created', guild.id)
expect(guild.id).to.be.exist
logger.info('Guild exists', guild.id)
await rest.deleteGuild(guild.id)
logger.info('Guild deleted', guild.id)
// Make sure the guild was deleted
await expect(rest.getGuild(guild.id)).to.eventually.rejected
logger.info('Guild deleted confirmed', guild.id)
})
describe('Edit and get', async () => {
const guild = await rest.createGuild({
name: 'Discordeno-test',
})
after(async () => {
await rest.deleteGuild(guild.id)
})
it('Get a guild', async () => {
const exists = await rest.getGuild(guild.id)
expect(exists).to.be.exist
expect(exists.id).to.be.exist
expect(exists.name).to.equal(guild.name)
})
it('Edit a guild', async () => {
const voiceChannel = await rest.createChannel(guild.id, {
name: 'edit-guild-test',
type: ChannelTypes.GuildVoice,
})
expect(voiceChannel.id).to.be.exist
const edited = await rest.editGuild(guild.id, {
name: 'Discordeno-test-edited',
afkChannelId: voiceChannel.id,
// afkTimeout: 5,
})
expect(edited.name).to.equal('Discordeno-test-edited')
expect(guild.afkChannelId).to.not.equal(voiceChannel.id)
expect(edited.afkChannelId).to.equal(voiceChannel.id)
// expect(guild.afkTimeout).to.equal(0);
// expect(edited.afkTimeout).to.equal(5);
it("Reset a guild's afk channel id", async () => {
const edited2 = await rest.editGuild(guild.id, { afkChannelId: null })
expect(edited.afkChannelId).to.not.equal(edited2.afkChannelId)
expect(edited2.afkChannelId).to.equal(undefined)
})
await rest.deleteChannel(voiceChannel.id)
})
// it("Edit a guild's afk settings", async () => {
// });
it('Get audit logs', async () => {
const auditLogs = await rest.getAuditLog(guild.id, { limit: 1 })
expect(auditLogs.auditLogEntries.length).to.be.exist
})
// Get available voice regions
it('Get available voice regions', async () => {
const regions = await rest.getVoiceRegions(guild.id)
expect(regions.length).to.be.exist
})
// Get a guild ban
it('Get a guild ban', async () => {
await rest.banMember(guild.id, 379643682984296448n)
const fetchedBan = await rest.getBan(guild.id, 379643682984296448n)
// Assertions
expect(fetchedBan).to.be.exist
expect(fetchedBan.user.id).to.equal('379643682984296448')
// Get multiple guild bans
it('Get multiple guild bans', async () => {
await rest.banMember(guild.id, 416477607966670869n)
await rest.banMember(guild.id, 635383782576357407n)
const fetchedBans = await rest.getBans(guild.id)
// Assertions
expect(fetchedBans).to.be.exist
})
})
// Get vanity URL
it('Get vanity URL', async () => {
await expect(rest.getVanityUrl(guild.id)).to.eventually.rejected
})
})
})
+127
View File
@@ -0,0 +1,127 @@
import chai, { expect } from 'chai'
import chaiAsPromised from 'chai-as-promised'
import { describe, it } from 'mocha'
import { e2ecache, rest } from './utils.js'
chai.use(chaiAsPromised)
// THIS IS WOLF, IF ANYTHING BREAKS BLAME HIM!
const wolfID = 270273690074087427n
// THIS IS IAN, HE PLAY GOLDEN SUN. BAN HIM BEFORE HE MAKES US ADDICTED TO IT!!!
const ianID = 90339695967350784n
// THIS IS LTS, HE PLAY TETRIS EFFECT: CONNECTED. BAN HIM BEFORE HE MAKES US ADDICTED TO IT!!!
const ltsID = 379643682984296448n
before(async () => {
if (!e2ecache.guild) {
e2ecache.guild = await rest.createGuild({
name: 'Discordeno-test',
})
}
})
after(async () => {
if (rest.invalidBucket.timeoutId) clearTimeout(rest.invalidBucket.timeoutId)
if (e2ecache.guild.id && !e2ecache.deletedGuild) {
e2ecache.deletedGuild = true;
await rest.deleteGuild(e2ecache.guild.id)
}
})
describe('[member] Member tests', async () => {
describe('Get members', () => {
it("Fetches the bot and compares the bot's id with the fetched member's id", async () => {
const member = await rest.getMember(e2ecache.communityGuildId, rest.applicationId)
expect(member?.user.id).to.exist
expect(member?.user.id).to.equal(rest.applicationId.toString())
})
it('Gets a member list and checks if the bot is in the member list', async () => {
const members = await rest.getMembers(e2ecache.communityGuildId, {
limit: 10
})
expect(members.some(m => m.user.id === rest.applicationId.toString())).to.equal(true)
})
// fetch a single member by id
it('fetch a single member by id', async () => {
const member = await rest.getMember(e2ecache.communityGuildId, rest.applicationId)
expect(member?.user.id).to.exist
})
})
describe('Ban member', () => {
// ban user from guild without reason
describe('ban user from guild without reason', async () => {
await rest.banMember(e2ecache.communityGuildId, wolfID)
// get a single user's ban
it("get a single user's ban", async () => {
expect(await rest.getBan(e2ecache.communityGuildId, wolfID)).to.exist
})
})
// ban member from guild with a reason
it('ban member from guild with a reason', async () => {
await rest.banMember(e2ecache.communityGuildId, ianID, {
reason: 'Blame Wolf'
})
expect(await rest.getBan(e2ecache.communityGuildId, ianID)).to.exist
})
// ban member from guild and delete messages
it('ban member from guild and delete messages', async () => {
await rest.banMember(e2ecache.communityGuildId, ltsID, {
deleteMessageSeconds: 604800
})
expect(await rest.getBan(e2ecache.communityGuildId, ltsID)).to.exist
})
// get bans on a server
it('get bans on a server', async () => {
const bans = await rest.getBans(e2ecache.communityGuildId)
expect(bans.length).to.greaterThan(1)
})
// unban member from guild
it('unban member from guild', async () => {
await Promise.all([
rest.unbanMember(e2ecache.communityGuildId, wolfID),
rest.unbanMember(e2ecache.communityGuildId, ianID)
])
await expect(rest.getBan(e2ecache.communityGuildId, wolfID)).to.eventually
.rejected
})
})
describe('nickname', () => {
it("Edit a bot's nickname", async () => {
const nick = 'lts20050703'
const member = await rest.editBotMember(e2ecache.communityGuildId, {
nick
})
expect(member.nick).to.equal(nick)
// Change nickname back
const member2 = await rest.editBotMember(e2ecache.communityGuildId, {
nick: null
})
expect(member2.nick).to.null
})
})
// waiting for channel
describe.skip('DM', () => {
it('[member] get dm channel and send a message', async () => {
// Itoh Alt ID
const channel = await rest.getDmChannel(750661528360845322n)
expect(channel?.id).to.exist
const message = await rest.sendMessage(channel.id, {
content: 'https://i.imgur.com/doG55NR.png'
})
expect(message?.content).to.exist
})
})
})
+76
View File
@@ -0,0 +1,76 @@
import { expect } from 'chai'
import { describe, it } from 'mocha'
import { e2ecache, rest } from './utils.js'
before(async () => {
if (!e2ecache.guild) {
e2ecache.guild = await rest.createGuild({
name: 'Discordeno-test',
})
}
})
after(async () => {
if (rest.invalidBucket.timeoutId) clearTimeout(rest.invalidBucket.timeoutId)
if (e2ecache.guild.id && !e2ecache.deletedGuild) {
e2ecache.deletedGuild = true;
await rest.deleteGuild(e2ecache.guild.id)
}
})
describe('[rest] Message related tests', () => {
describe('Send a message', () => {
it('With content', async () => {
const message = await rest.sendMessage('1041029705790402611', { content: 'testing rate limit manager' })
expect(message.content).to.be.equal('testing rate limit manager')
})
it('With an image', async () => {
const image = await fetch("https://cdn.discordapp.com/avatars/270010330782892032/d031ea881688526d1ae235fd2843e53c.jpg?size=2048").then(async res => await res.blob()).catch(()=> undefined)
expect(image).to.not.be.undefined
if (!image) throw new Error("Was not able to fetch the image.")
const message = await rest.sendMessage('1041029705790402611', { file: { blob: image, name: "gamer" }})
expect(message.attachments.length).to.be.greaterThan(0)
const [attachment] = message.attachments
expect(attachment.filename).to.be.equal("gamer")
})
})
describe('Rate limit manager testing', () => {
it('Send 10 messages to 1 channel', async () => {
await Promise.all([0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(async (i) => {
await rest.sendMessage('1041029705790402611', { content: `10 messages to 1 channel testing rate limit manager ${i}` })
}))
})
// TODO: Make this dynamic when we can create channels
const spamChannelIds = [
'1041029705790402611', '1041029706838966393',
'1041029707459731586', '1041029708004995199',
'1041029708453789766', '1041029709049385010',
'1041029709632377003', '1041029710227976313',
'1041029710764834856', '1041029711414956202',
'1041029712153149524', '1041029712933306459',
'1041029713566646313', '1041029714254508042',
'1041029714921406555', '1041029716334870629',
'1041029717127614636', '1041029717689647114',
'1041029718603997214', '1041029719925215302',
'1041029721179308082', '1041029721988812860',
'1041029722466943037', '1041029723217743964',
'1041029723872034826', '1041029724492804156',
'1041029725117743144', '1041029725818212474',
'1041029726531227741', '1041029727231684638'
]
it('Send 10 messages to 10 channels', async () => {
await Promise.all(spamChannelIds.map(async (channelId) => {
await Promise.all([...Array(10).keys()].map(async (_, index) => {
await rest.sendMessage(channelId, { content: `testing rate limit manager ${index}` })
}))
}))
})
})
})
+192
View File
@@ -0,0 +1,192 @@
import type { Camelize, DiscordRole } from '@discordeno/types'
import { calculateBits } from '@discordeno/utils'
import { expect } from 'chai'
import { afterEach, before, beforeEach, describe, it } from 'mocha'
import { e2ecache, rest } from './utils.js'
before(async () => {
if (!e2ecache.guild) {
e2ecache.guild = await rest.createGuild({
name: 'Discordeno-test',
})
}
})
after(async () => {
if (rest.invalidBucket.timeoutId) clearTimeout(rest.invalidBucket.timeoutId)
if (e2ecache.guild.id && !e2ecache.deletedGuild) {
await rest.deleteGuild(e2ecache.guild.id)
}
})
describe('[role] Role tests', async () => {
// Create a role with a reason
it('Create a role with a reason', async () => {
const role = await rest.createRole(
e2ecache.guild?.id,
{
name: `test role ${Date.now()}`,
},
'test reason',
)
expect(role.id).to.exist
await rest.deleteRole(e2ecache.guild.id, role.id)
})
// Create a role without a reason
it('Create a role without a reason', async () => {
const role = await rest.createRole(e2ecache.guild.id, {
name: `test role ${Date.now()}`,
})
expect(role.id).to.exist
await rest.deleteRole(e2ecache.guild.id, role.id)
})
// Delete a role
it('Delete a role', async () => {
const role = await rest.createRole(e2ecache.guild.id, {
name: `test role ${Date.now()}`,
})
await rest.deleteRole(e2ecache.guild.id, role.id)
const deletedRoles = await rest.getRoles(e2ecache.guild.id)
expect(deletedRoles.some((r) => r.id === role.id)).to.equal(false)
})
// Edit a role
describe('Edit a role', async () => {
let role: Camelize<DiscordRole>
beforeEach(async () => {
role = await rest.createRole(e2ecache.guild.id, {
name: `test role ${Date.now()}`,
})
})
afterEach(async () => {
await rest.deleteRole(e2ecache.guild.id, role.id)
})
// Edit the roles name
it('Edit the roles name', async () => {
const edited = await rest.editRole(e2ecache.guild.id, role.id, {
name: 'test role 4',
})
expect(edited.name).to.equal('test role 4')
})
// Edit the roles color
it('Edit the roles color', async () => {
const edited = await rest.editRole(e2ecache.guild.id, role.id, {
color: 0x0000ff,
})
expect(edited.color).to.equal(0x0000ff)
})
// Edit the roles hoist
it('Edit the roles hoist', async () => {
expect(role.hoist).to.equal(false)
const edited = await rest.editRole(e2ecache.guild.id, role.id, {
hoist: true
})
expect(edited.hoist).to.equal(true)
})
// Make hoist false
it('Make hoist false', async () => {
await rest.editRole(e2ecache.guild.id, role.id, { hoist: true })
const edited = await rest.editRole(e2ecache.guild.id, role.id, {
hoist: false
})
expect(edited.hoist).to.equal(false)
})
// Edit the roles mentionable
it('Edit the roles mentionable', async () => {
const edited = await rest.editRole(e2ecache.guild.id, role.id, {
mentionable: true
})
expect(edited.mentionable).to.equal(true)
})
// Make mentionable false
it('Make mentionable false', async () => {
await rest.editRole(e2ecache.guild.id, role.id, {
mentionable: true
})
const edited = await rest.editRole(e2ecache.guild.id, role.id, {
mentionable: false
})
expect(edited.mentionable).to.equal(false)
})
// Edit the roles permissions
it('Edit the roles permissions', async () => {
const edited = await rest.editRole(e2ecache.guild.id, role.id, {
permissions: ['SEND_MESSAGES', 'VIEW_CHANNEL'],
})
expect(edited.permissions.toString()).to.equal(calculateBits(['SEND_MESSAGES', 'VIEW_CHANNEL']))
})
})
describe('Remove a role from a user', async () => {
let role: Camelize<DiscordRole>
beforeEach(async () => {
role = await rest.createRole(e2ecache.guild.id, {
name: `test role ${Date.now()}`,
})
await rest.addRole(e2ecache.guild.id, rest.applicationId, role.id)
})
// afterEach(async () => {
// await rest.deleteRole(e2ecache.guild.id, role.id)
// })
it('without a reason', async () => {
await rest.removeRole(e2ecache.guild.id, rest.applicationId, role.id)
const member = await rest.getMember(e2ecache.guild.id, rest.applicationId)
// console.log('member', member.errors.userId.Errors)
expect(member?.roles.includes(role.id)).to.equal(false)
})
it('with a reason', async () => {
await rest.removeRole(e2ecache.guild.id, rest.applicationId, role.id, 'test reason')
const member = await rest.getMember(e2ecache.guild.id, rest.applicationId)
expect(member?.roles.includes(role.id)).to.equal(false)
})
})
describe('Assign a role to a user', async () => {
let role: Camelize<DiscordRole>
beforeEach(async () => {
role = await rest.createRole(e2ecache.guild.id, {
name: `test role ${Date.now()}`,
})
})
afterEach(async () => {
await rest.removeRole(e2ecache.guild.id, rest.applicationId, role.id)
await rest.deleteRole(e2ecache.guild.id, role.id)
})
it('Without a reason.', async () => {
// Assign the role to the user
await rest.addRole(e2ecache.guild.id, rest.applicationId, role.id)
const member = await rest.getMember(e2ecache.guild.id, rest.applicationId)
expect(member?.roles.includes(role.id)).to.equal(true)
})
// Add the role to the user with a reason
it('With a reason', async () => {
await rest.addRole(e2ecache.guild.id, rest.applicationId, role.id, 'test reason')
const member = await rest.getMember(e2ecache.guild.id, rest.applicationId)
expect(member?.roles.includes(role.id)).to.equal(true)
})
})
})
+135
View File
@@ -0,0 +1,135 @@
import type { Camelize, DiscordSticker } from '@discordeno/types'
import { StickerFormatTypes } from '@discordeno/types'
import chai, { expect } from 'chai'
import chaiAsPromised from 'chai-as-promised'
import { afterEach, beforeEach, describe, it } from 'mocha'
import { e2ecache, rest } from './utils.js'
chai.use(chaiAsPromised)
before(async () => {
if (!e2ecache.guild) {
e2ecache.guild = await rest.createGuild({
name: 'Discordeno-test',
})
}
})
after(async () => {
if (rest.invalidBucket.timeoutId) clearTimeout(rest.invalidBucket.timeoutId)
if (e2ecache.guild.id && !e2ecache.deletedGuild) {
e2ecache.deletedGuild = true
await rest.deleteGuild(e2ecache.guild.id)
}
})
// waiting for channel
describe('[stickers] Sticker helpers', async () => {
it('Can get a sticker', async () => {
const sticker = await rest.getSticker(749054660769218631n)
expect(sticker.name).to.equal('Wave')
})
describe('Guild sticker helpers', () => {
describe('Create and delete guild sticker helpers', () => {
it('Can create a sticker', async () => {
const sticker = await rest.createGuildSticker(e2ecache.guild.id, {
name: 'sticker name',
description: 'sticker description',
tags: 'sticker tags',
file: {
blob: await (await fetch('https://i.imgur.com/ejqd6Ro.png')).blob(),
name: 'ddlogo.png',
},
})
expect(sticker.name).to.equal('sticker name')
expect(sticker.description).to.equal('sticker description')
expect(sticker.tags).to.equal('sticker tags')
const channel = await rest.createChannel(e2ecache.guild.id, {
name: 'test',
})
const message = await rest.sendMessage(channel.id, {
stickerIds: [sticker.id],
})
expect(message.stickerItems?.[0].formatType).to.equal(StickerFormatTypes.Png)
expect(message.stickerItems?.[0].id).to.equal(sticker.id)
expect(message.stickerItems?.[0].name).to.equal(sticker.name)
await rest.deleteGuildSticker(e2ecache.guild.id, sticker.id)
await rest.deleteChannel(channel.id)
})
it('Can delete a sticker', async () => {
const sticker = await rest.createGuildSticker(e2ecache.guild.id, {
name: 'sticker name',
description: 'sticker description',
tags: 'sticker tags',
file: {
blob: await (await fetch('https://i.imgur.com/ejqd6Ro.png')).blob(),
name: 'ddlogo.png',
},
})
await rest.deleteGuildSticker(e2ecache.guild.id, sticker.id)
await expect(rest.getGuildSticker(e2ecache.guild.id, sticker.id)).to.eventually.rejected
})
})
describe('Get and edit guild sticker helpers', () => {
let sticker: Camelize<DiscordSticker>
beforeEach(async () => {
sticker = await rest.createGuildSticker(e2ecache.guild.id, {
name: 'sticker name',
description: 'sticker description',
tags: 'sticker tags',
file: {
blob: await (await fetch('https://i.imgur.com/ejqd6Ro.png')).blob(),
name: 'ddlogo.png',
},
})
})
afterEach(async () => {
await rest.deleteGuildSticker(e2ecache.guild.id, sticker.id)
})
it('Can get a sticker', async () => {
const getSticker = await rest.getGuildSticker(e2ecache.guild.id, sticker.id)
expect(getSticker.name).to.equal('sticker name')
expect(getSticker.description).to.equal('sticker description')
expect(getSticker.tags).to.equal('sticker tags')
})
it('Can get stickers', async () => {
const sticker2 = await rest.createGuildSticker(e2ecache.guild.id, {
name: 'sticker 2',
description: 'sticker 2',
tags: 'sticker tags 2',
file: {
blob: await (await fetch('https://i.imgur.com/ejqd6Ro.png')).blob(),
name: 'ddlogo.png',
},
})
const stickers = await rest.getGuildStickers(e2ecache.guild.id)
await rest.deleteGuildSticker(e2ecache.guild.id, sticker2.id)
expect(stickers.length).to.greaterThan(1)
})
it('Can edit sticker', async () => {
const editSticker = await rest.editGuildSticker(e2ecache.guild.id, sticker.id, {
name: 'sticker name',
description: 'sticker description',
tags: 'sticker tags',
})
expect(editSticker.name).to.equal('sticker name')
expect(editSticker.description).to.equal('sticker description')
expect(editSticker.tags).to.equal('sticker tags')
})
})
})
})
+53
View File
@@ -0,0 +1,53 @@
import chai, { expect } from 'chai'
import chaiAsPromised from 'chai-as-promised'
import { describe, it } from 'mocha'
import { e2ecache, rest } from './utils.js'
chai.use(chaiAsPromised)
before(async () => {
if (!e2ecache.guild) {
e2ecache.guild = await rest.createGuild({
name: 'Discordeno-test',
})
}
})
after(async () => {
if (rest.invalidBucket.timeoutId) clearTimeout(rest.invalidBucket.timeoutId)
if (e2ecache.guild.id && !e2ecache.deletedGuild) {
await rest.deleteGuild(e2ecache.guild.id)
}
})
describe('[rest] User related tests', () => {
describe('Get a user from the api', () => {
it('With a valid user id', async () => {
const user = await rest.getUser('130136895395987456')
describe('User has correct shape and form', () => {
it('Has correct id', () => {
expect(user.id).to.be.equal('130136895395987456')
})
it('Has a valid username', () => {
expect(user.username.length).to.be.greaterThanOrEqual(1)
})
it('Has a valid discriminator', () => {
expect(user.discriminator.length).to.be.equal(4)
})
it('Has been camelized', () => {
const keys = Object.keys(user)
expect(keys.includes('public_flags')).to.be.false
expect(keys.includes('publicFlags')).to.be.true
})
})
})
it('With an invalid user id', async () => {
await expect(rest.getUser('123')).eventually.throws
})
})
})
+18
View File
@@ -0,0 +1,18 @@
import { LogDepth, logger, LogLevels } from '@discordeno/utils'
import { createRestManager } from '../../src/manager.js'
import { E2E_TEST_GUILD_ID, token } from './constants.js'
// For debugging purposes
// logger.setLevel(LogLevels.Debug)
// logger.setDepth(LogDepth.Full)
export const rest = createRestManager({
token,
})
rest.deleteQueueDelay = 10000
export const e2ecache = {
guild: await rest.createGuild({ name: 'ddenotester' }),
deletedGuild: false,
communityGuildId: E2E_TEST_GUILD_ID
}
+157
View File
@@ -0,0 +1,157 @@
import type { Camelize, DiscordMessage } from '@discordeno/types'
import chai, { expect } from 'chai'
import chaiAsPromised from 'chai-as-promised'
import { beforeEach, describe, it } from 'mocha'
import { e2ecache, rest } from './utils.js'
chai.use(chaiAsPromised)
before(async () => {
if (!e2ecache.guild) {
e2ecache.guild = await rest.createGuild({
name: 'Discordeno-test',
})
}
})
after(async () => {
if (rest.invalidBucket.timeoutId) clearTimeout(rest.invalidBucket.timeoutId)
if (e2ecache.guild.id && !e2ecache.deletedGuild) {
e2ecache.deletedGuild = true
await rest.deleteGuild(e2ecache.guild.id)
}
})
// waiting for channel
describe('[webhooks] Webhook helpers', async () => {
const channel = await rest.createChannel(e2ecache.guild.id, {
name: 'wbhook',
})
const webhook = await rest.createWebhook(channel.id, {
name: 'idk',
})
describe('General webhook helpers', () => {
it('Can create a webhook', async () => {
expect(webhook).to.exist
expect(webhook.name).to.equal('idk')
})
it('Can delete a webhook', async () => {
const hookToDelete = await rest.createWebhook(channel.id, {
name: 'delme',
})
await rest.deleteWebhook(hookToDelete.id)
// Fetch the webhook to validate it was deleted
await expect(rest.getWebhook(hookToDelete.id)).to.eventually.rejected
})
it('Can delete a webhook with token', async () => {
const hookToDelete = await rest.createWebhook(channel.id, {
name: 'delme',
})
expect(hookToDelete?.id).to.exist
expect(hookToDelete.token).to.exist
await rest.deleteWebhookWithToken(hookToDelete.id, hookToDelete.token!)
// Fetch the webhook to validate it was deleted
await expect(rest.getWebhook(hookToDelete.id)).to.eventually.rejected
})
})
describe('Guild webhook helpers', async () => {
it('Can edit a guild webhook', async () => {
const edited = await rest.editWebhook(webhook.id, {
name: 'edited',
})
expect(webhook.name).to.not.equal(edited.name)
})
it('Can edit a guild webhook with token', async () => {
const edited = await rest.editWebhookWithToken(webhook.id, webhook.token!, {
name: 'editedtoken',
})
expect(webhook.name).to.not.equal(edited.name)
})
it('Can get a guild webhook', async () => {
const fetched = await rest.getWebhook(webhook.id)
expect(fetched).to.exist
expect(webhook.id).to.equal(fetched.id)
})
it('Can get a guild webhook with a token', async () => {
expect(webhook.token).to.exist
const fetched = await rest.getWebhookWithToken(webhook.id, webhook.token!)
expect(webhook.id).to.equal(fetched.id)
})
})
describe('Guild channel webhook helpers', async () => {
// console.log('in guild channel webhook helper', 1)
await rest.createWebhook(channel.id, {
name: 'idkk',
})
// console.log('in guild channel webhook helper', 2)
it('Can create guild channel webhooks', async () => {
// console.log('in guild channel webhook helper', 3)
// console.log('in guild channel webhook helper', 4)
const fetched = await rest.getChannelWebhooks(channel.id)
// console.log('in guild channel webhook helper', 1)
expect(fetched.length).to.greaterThan(1)
// console.log('in guild channel webhook helper', 6)
})
// console.log('in guild channel webhook helper', 7)
it('Can get a guild channel webhooks', async () => {
// console.log('in guild channel webhook helper', 8)
const guildWebhooks = await rest.getGuildWebhooks(channel.guildId!)
// console.log('in guild channel webhook helper', 9)
expect(guildWebhooks.length).to.greaterThan(1)
// console.log('in guild channel webhook helper', 10)
})
})
describe('Webhook Message helpers', async () => {
let message: Camelize<DiscordMessage>
beforeEach(async () => {
const msg = await rest.executeWebhook(webhook.id, webhook.token!, {
content: 'discordeno is best lib',
wait: true,
})
if (!msg) throw new Error('message not send')
message = msg
})
it('Can send message with webhook', async () => {
expect(message?.id).to.exist
})
it('Can delete a message with webhook', async () => {
await rest.deleteWebhookMessage(webhook.id, webhook.token!, message.id)
await expect(rest.getWebhookMessage(webhook.id, webhook.token!, message.id)).to.eventually.rejected
})
it('Can get a message with webhook', async () => {
const fetched = await rest.getWebhookMessage(webhook.id, webhook.token!, message.id)
expect(fetched).to.exist
expect(fetched.content).to.equal(message.content)
})
it('Can edit a message with webhook', async () => {
const edited = await rest.editWebhookMessage(webhook.id, webhook.token!, message.id, {
content: 'different',
})
expect(edited).to.exist
expect(edited.content).to.not.equal(message.content)
})
})
})
+7
View File
@@ -0,0 +1,7 @@
import { describe, it } from 'mocha'
describe('index.ts', () => {
it('will import without error', async () => {
await import('../../src/index.js')
})
})
+208
View File
@@ -0,0 +1,208 @@
import { expect } from 'chai'
import { afterEach, beforeEach, describe, it } from 'mocha'
import sinon from 'sinon'
import type { RestManager } from '../../src/manager.js'
import { createRestManager } from '../../src/manager.js'
import { fakeToken as token } from '../constants.js'
describe('[rest] manager', () => {
describe('create a rest manager with only a token', () => {
const rest = createRestManager({ token })
it('Token is set properly.', () => {
expect(rest.token).to.be.equal(token)
})
it('Default values are set when none are provided.', () => {
expect(rest.version).to.be.equal(10)
expect(rest.baseUrl).to.be.equal('https://discord.com/api')
})
})
describe('create a manager with other options', () => {
const options = {
token,
version: 9,
baseUrl: 'https://localhost:8000',
} as const
const rest = createRestManager(options)
it('With a version', () => {
expect(rest.version).to.be.equal(options.version)
})
it('With a base url', () => {
expect(rest.baseUrl).to.be.equal(options.baseUrl)
})
})
describe('rest.simplifyUrl', () => {
describe('the ending id', () => {
it('Will change to x for channel, guild, message, messages', () => {
const rest = createRestManager({ token })
expect(rest.simplifyUrl('/messages/555555555555555555', 'PUT')).to.be.equal('/messages/x')
expect(rest.simplifyUrl('/users/555555555555555555', 'PUT')).to.be.equal('/users/x')
expect(rest.simplifyUrl('/webhooks/555555555555555555', 'PUT')).to.be.equal('/webhooks/x')
expect(rest.simplifyUrl('/channel/555555555555555555', 'PUT')).to.be.equal('/channel/x')
expect(rest.simplifyUrl('/guild/555555555555555555', 'PUT')).to.be.equal('/guild/x')
})
it('Will not change to x for channels, guilds', () => {
const rest = createRestManager({ token })
expect(rest.simplifyUrl('/channels/555555555555555555', 'PUT')).to.be.equal('/channels/555555555555555555')
expect(rest.simplifyUrl('/guilds/555555555555555555', 'PUT')).to.be.equal('/guilds/555555555555555555')
})
})
describe('with route', () => {
describe('/reactions', () => {
it('Will remove path after reactions', () => {
const rest = createRestManager({ token })
expect(rest.simplifyUrl('/channels/555555555555555555/reactions/555555555555555555/wdiubaibfwuabfobaowbfoibnion', 'PUT')).to.be.equal(
'/channels/555555555555555555/reactions',
)
})
})
describe('/messages', () => {
it('Will add method in front route if method is DELETE', () => {
const rest = createRestManager({ token })
expect(rest.simplifyUrl('/channels/555555555555555555/messages/555555555555555555', 'DELETE')).to.be.equal(
'DELETE/channels/555555555555555555/messages/x',
)
})
it('Will not add method in front route', () => {
const rest = createRestManager({ token })
expect(rest.simplifyUrl('/channels/555555555555555555/messages/555555555555555555', 'POST')).to.be.equal(
'/channels/555555555555555555/messages/x',
)
expect(rest.simplifyUrl('/channels/555555555555555555/messages/555555555555555555', 'GET')).to.be.equal(
'/channels/555555555555555555/messages/x',
)
expect(rest.simplifyUrl('/channels/555555555555555555/messages/555555555555555555', 'PUT')).to.be.equal(
'/channels/555555555555555555/messages/x',
)
})
})
})
})
describe('rest.checkRateLimits', () => {
let rest: RestManager
let clock: sinon.SinonFakeTimers
beforeEach(() => {
rest = createRestManager({ token })
clock = sinon.useFakeTimers()
})
afterEach(() => {
clock.restore()
})
it('will return false for path without rate limited', () => {
expect(rest.checkRateLimits('/channel/555555555555555555')).to.be.equal(false)
})
describe('With per URL rateLimitedPath', () => {
it('Will return time until reset if before resetTimestamp', () => {
rest.rateLimitedPaths.set('/channel/555555555555555555', {
url: '/channel/555555555555555555',
resetTimestamp: Date.now() + 6541,
})
expect(rest.checkRateLimits('/channel/555555555555555555')).to.be.equal(6541)
})
it('Will return false if before resetTimestamp', () => {
rest.rateLimitedPaths.set('/channel/555555555555555555', {
url: '/channel/555555555555555555',
resetTimestamp: Date.now(),
})
expect(rest.checkRateLimits('/channel/555555555555555555')).to.be.equal(false)
})
})
describe('With global rateLimitedPath', () => {
it('Will return time until reset if before resetTimestamp', () => {
rest.rateLimitedPaths.set('global', {
url: '/channel/555555555555555555',
resetTimestamp: Date.now() + 9849,
})
expect(rest.checkRateLimits('/channel/555555555555555555')).to.be.equal(9849)
})
it('Will return false if before resetTimestamp', () => {
rest.rateLimitedPaths.set('global', {
url: '/channel/555555555555555555',
resetTimestamp: Date.now(),
})
expect(rest.checkRateLimits('/channel/555555555555555555')).to.be.equal(false)
})
})
describe('With both URL and Global rateLimitedPath', () => {
it('Will return URL time first if before resetTimestamp', () => {
rest.rateLimitedPaths.set('/channel/555555555555555555', {
url: '/channel/555555555555555555',
resetTimestamp: Date.now() + 6541,
})
rest.rateLimitedPaths.set('global', {
url: '/channel/555555555555555555',
resetTimestamp: Date.now() + 9849,
})
expect(rest.checkRateLimits('/channel/555555555555555555')).to.be.equal(6541)
})
})
})
describe('rest.processRateLimitedPaths', () => {
let rest: RestManager
let time: sinon.SinonFakeTimers
beforeEach(() => {
rest = createRestManager({ token: ' ' })
time = sinon.useFakeTimers()
})
afterEach(() => {
time.restore()
})
describe('rateLimitedPaths', () => {
it('Will not delete path from rateLimitedPaths before resetTimestamp', () => {
rest.rateLimitedPaths.set('', {
resetTimestamp: Date.now() + 1,
url: '',
})
rest.processRateLimitedPaths()
expect(rest.rateLimitedPaths.size).to.be.equal(1)
})
it('Will delete path from rateLimitedPaths after resetTimestamp', () => {
rest.rateLimitedPaths.set('', { resetTimestamp: Date.now(), url: '' })
rest.processRateLimitedPaths()
expect(rest.rateLimitedPaths.size).to.be.equal(0)
})
it('Will mark globallyRateLimited false if key is global', () => {
rest.rateLimitedPaths.set('global', {
resetTimestamp: Date.now(),
url: '',
})
rest.globallyRateLimited = true
rest.processRateLimitedPaths()
expect(rest.rateLimitedPaths.size).to.be.equal(0)
expect(rest.globallyRateLimited).to.be.equal(false)
})
it('Will not mark globallyRateLimited false if key is not global', () => {
rest.rateLimitedPaths.set('', { resetTimestamp: Date.now(), url: '' })
rest.globallyRateLimited = true
rest.processRateLimitedPaths()
expect(rest.rateLimitedPaths.size).to.be.equal(0)
expect(rest.globallyRateLimited).to.be.equal(true)
})
})
})
})