mirror of
https://github.com/discordeno/discordeno.git
synced 2026-06-02 17:00:08 +00:00
15
.github/workflows/test.yml
vendored
Normal file
15
.github/workflows/test.yml
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
name: Test
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: denolib/setup-deno@master
|
||||
- name: Cache dependencies
|
||||
run: deno cache mod.ts test/mod.test.ts
|
||||
- name: Run test script
|
||||
run: deno test -A
|
||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -4,5 +4,8 @@
|
||||
"deno.import_intellisense_origins": {
|
||||
"https://deno.land": true
|
||||
},
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.organizeImports": true
|
||||
},
|
||||
"editor.defaultFormatter": "denoland.vscode-deno"
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||

|
||||
[](https://nest.land/package/Discordeno)
|
||||
|
||||
[WIP] 
|
||||
|
||||
## Why Discordeno?
|
||||
|
||||
### Beginner Developers
|
||||
|
||||
5
deps.ts
5
deps.ts
@@ -7,4 +7,9 @@ export {
|
||||
isWebSocketPongEvent,
|
||||
} from "https://deno.land/std@0.67.0/ws/mod.ts";
|
||||
export type { WebSocket } from "https://deno.land/std@0.67.0/ws/mod.ts";
|
||||
export {
|
||||
assert,
|
||||
assertArrayIncludes,
|
||||
assertEquals,
|
||||
} from "https://deno.land/std@0.75.0/testing/asserts.ts";
|
||||
export { decompress_with as inflate } from "https://unpkg.com/@evan/wasm@0.0.11/target/zlib/deno.js";
|
||||
|
||||
@@ -15,9 +15,6 @@ export async function handleInternalMessageCreate(data: DiscordPayload) {
|
||||
const channel = await cacheHandlers.get("channels", payload.channel_id);
|
||||
if (channel) channel.lastMessageID = payload.id;
|
||||
|
||||
const message = await structures.createMessage(payload);
|
||||
// Cache the message
|
||||
cacheHandlers.set("messages", payload.id, message);
|
||||
const guild = payload.guild_id
|
||||
? await cacheHandlers.get("guilds", payload.guild_id)
|
||||
: undefined;
|
||||
@@ -46,6 +43,10 @@ export async function handleInternalMessageCreate(data: DiscordPayload) {
|
||||
}
|
||||
});
|
||||
|
||||
const message = await structures.createMessage(payload);
|
||||
// Cache the message
|
||||
cacheHandlers.set("messages", payload.id, message);
|
||||
|
||||
eventHandlers.messageCreate?.(message);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ import { Permissions } from "../types/permission.ts";
|
||||
import type { RoleData } from "../types/role.ts";
|
||||
import { formatImageURL } from "../utils/cdn.ts";
|
||||
import { Collection } from "../utils/collection.ts";
|
||||
import { botHasPermission } from "../utils/permissions.ts";
|
||||
import { botHasPermission, calculateBits } from "../utils/permissions.ts";
|
||||
import { urlToBase64 } from "../utils/utils.ts";
|
||||
|
||||
/** Create a new guild. Returns a guild object on success. Fires a Guild Create Gateway event. This endpoint can be used only by bots in less than 10 guilds. */
|
||||
@@ -317,7 +317,12 @@ export function editRole(
|
||||
) {
|
||||
throw new Error(Errors.MISSING_MANAGE_ROLES);
|
||||
}
|
||||
return RequestManager.patch(endpoints.GUILD_ROLE(guildID, id), options);
|
||||
return RequestManager.patch(endpoints.GUILD_ROLE(guildID, id), {
|
||||
...options,
|
||||
permissions: options.permissions
|
||||
? calculateBits(options.permissions)
|
||||
: undefined,
|
||||
});
|
||||
}
|
||||
|
||||
/** Delete a guild role. Requires the MANAGE_ROLES permission. */
|
||||
|
||||
@@ -188,6 +188,7 @@ export async function hasChannelPermissions(
|
||||
return botHasPermission(guild.id, permissions);
|
||||
}
|
||||
|
||||
/** This function converts a bitwise string to permission strings */
|
||||
export function calculatePermissions(permissionBits: bigint) {
|
||||
return Object.keys(Permissions).filter((perm) => {
|
||||
if (typeof perm !== "number") return false;
|
||||
@@ -195,6 +196,14 @@ export function calculatePermissions(permissionBits: bigint) {
|
||||
}) as Permission[];
|
||||
}
|
||||
|
||||
/** This function converts an array of permissions into the bitwise string. */
|
||||
export function calculateBits(permissions: Permission[]) {
|
||||
return permissions.reduce(
|
||||
(bits, perm) => bits |= BigInt(Permissions[perm]),
|
||||
BigInt(0),
|
||||
).toString();
|
||||
}
|
||||
|
||||
export async function highestRole(guildID: string, memberID: string) {
|
||||
const guild = await cacheHandlers.get("guilds", guildID);
|
||||
if (!guild) return;
|
||||
|
||||
238
tests/mod.test.ts
Normal file
238
tests/mod.test.ts
Normal file
@@ -0,0 +1,238 @@
|
||||
import { assert, assertArrayIncludes, assertEquals, delay } from "../deps.ts";
|
||||
import {
|
||||
botID,
|
||||
cache,
|
||||
Channel,
|
||||
createClient,
|
||||
createGuildChannel,
|
||||
createGuildRole,
|
||||
createServer,
|
||||
deleteChannel,
|
||||
deleteRole,
|
||||
deleteServer,
|
||||
editRole,
|
||||
getMessage,
|
||||
Guild,
|
||||
Intents,
|
||||
OverwriteType,
|
||||
Role,
|
||||
sendMessage,
|
||||
} from "../mod.ts";
|
||||
import { editChannel } from "../src/handlers/channel.ts";
|
||||
import { getChannel } from "../src/handlers/guild.ts";
|
||||
|
||||
// TODO: add DISCORD_TOKEN variable to GitHub secrets
|
||||
const token = Deno.env.get("DISCORD_TOKEN");
|
||||
if (!token) throw "Token is not provided";
|
||||
|
||||
createClient({
|
||||
token,
|
||||
intents: [Intents.GUILD_MESSAGES, Intents.GUILDS],
|
||||
});
|
||||
|
||||
// Default options for all test cases
|
||||
const testOptions = {
|
||||
sanitizeOps: false,
|
||||
sanitizeResources: false,
|
||||
};
|
||||
|
||||
Deno.test({
|
||||
name: "connect to the gateway",
|
||||
fn: async () => {
|
||||
// Delay the execution by 15 seconds (15000 ms)
|
||||
await delay(15000);
|
||||
|
||||
// Check whether botID is nil or not
|
||||
assert(botID);
|
||||
},
|
||||
...testOptions,
|
||||
});
|
||||
|
||||
const data = {
|
||||
guildID: "",
|
||||
roleID: "",
|
||||
channelID: "",
|
||||
};
|
||||
|
||||
Deno.test({
|
||||
name: "create a guild",
|
||||
async fn() {
|
||||
// Create a guild "Discordeno Test"
|
||||
const createdGuild = (await createServer({
|
||||
name: "Discordeno Test",
|
||||
})) as Guild;
|
||||
|
||||
// Check whether createdGuild is nil or not
|
||||
assert(createdGuild);
|
||||
|
||||
data.guildID = createdGuild.id;
|
||||
},
|
||||
...testOptions,
|
||||
});
|
||||
|
||||
// Role
|
||||
|
||||
Deno.test({
|
||||
name: "create a role in a guild",
|
||||
async fn() {
|
||||
// Create a role "Role 1" in the guild "Discordeno Test"
|
||||
const createdRole = await createGuildRole(data.guildID, {
|
||||
name: "Role 1",
|
||||
});
|
||||
|
||||
// Check whether the created role is nil or not
|
||||
assert(createdRole);
|
||||
|
||||
data.roleID = createdRole.id;
|
||||
},
|
||||
...testOptions,
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: "edit a role in a guild",
|
||||
async fn() {
|
||||
// Edit a role "Role 1" in the guild "Discordeno Test"
|
||||
const editedRole = (await editRole(data.guildID, data.roleID, {
|
||||
name: "Edited Role",
|
||||
color: 4320244,
|
||||
hoist: false,
|
||||
mentionable: false,
|
||||
})) as Role;
|
||||
|
||||
// Assertions
|
||||
assert(editedRole);
|
||||
assertEquals(editedRole.name, "Edited Role");
|
||||
assertEquals(editedRole.color, 4320244);
|
||||
assertEquals(editedRole.hoist, false);
|
||||
assertEquals(editedRole.mentionable, false);
|
||||
|
||||
data.roleID = editedRole.id;
|
||||
},
|
||||
...testOptions,
|
||||
});
|
||||
|
||||
// Channel
|
||||
|
||||
Deno.test({
|
||||
name: "create a channel in a guild",
|
||||
async fn() {
|
||||
const guild = cache.guilds.get(data.guildID);
|
||||
if (!guild) throw "Guild not found";
|
||||
const createdChannel = await createGuildChannel(guild, "test");
|
||||
|
||||
// Check whether the created channel is nil or not
|
||||
assert(createdChannel);
|
||||
|
||||
data.channelID = createdChannel.id;
|
||||
},
|
||||
...testOptions,
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: "get a channel in a guild",
|
||||
async fn() {
|
||||
const channel = await getChannel(data.channelID);
|
||||
|
||||
assertEquals(channel.id, data.channelID);
|
||||
},
|
||||
...testOptions,
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: "edit a channel in a guild",
|
||||
async fn() {
|
||||
const channel = await editChannel(data.channelID, {
|
||||
name: "edited channel",
|
||||
}) as Channel;
|
||||
|
||||
assert(channel);
|
||||
|
||||
data.channelID = channel.id;
|
||||
},
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: "channel overwrite has permission",
|
||||
async fn() {
|
||||
const channel = cache.channels.get(data.channelID);
|
||||
if (!channel) throw "Channel not found";
|
||||
assertArrayIncludes(channel.permission_overwrites!, [
|
||||
{
|
||||
id: data.roleID,
|
||||
type: OverwriteType.ROLE,
|
||||
// The type for Channel#permission_overwrites is "RawOverwrite[] | undefined"
|
||||
// not "Overwrite[]"; therefore, permission strings cannot be used.
|
||||
// allow: ["VIEW_CHANNEL", "SEND_MESSAGES"],
|
||||
// deny: ["USE_EXTERNAL_EMOJIS"],
|
||||
},
|
||||
]);
|
||||
|
||||
// THIS TEST CASE SHOULD BE REFACTORED AND IMPROVED
|
||||
// CURRENTLY, IT USES Channel#permission_overwrites
|
||||
// but preferably, it should use the channelOverwriteHasPermission()
|
||||
},
|
||||
...testOptions,
|
||||
});
|
||||
|
||||
// Message
|
||||
|
||||
let messageID: string;
|
||||
|
||||
Deno.test({
|
||||
name: "create a message in a guild",
|
||||
async fn() {
|
||||
const createdMessage = await sendMessage(data.channelID, "test");
|
||||
|
||||
// Check whether the created message is nil or not
|
||||
assert(createdMessage);
|
||||
|
||||
messageID = createdMessage.id;
|
||||
},
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: "get a message in a guild",
|
||||
async fn() {
|
||||
const message = await getMessage(data.channelID, messageID);
|
||||
|
||||
assertEquals(messageID, message.id);
|
||||
},
|
||||
});
|
||||
|
||||
// Clean up
|
||||
|
||||
Deno.test({
|
||||
name: "delete a role from the guild",
|
||||
async fn() {
|
||||
await deleteRole(data.guildID, data.roleID);
|
||||
data.roleID = "";
|
||||
assertEquals(data.roleID, "");
|
||||
},
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: "delete a channel in the guild",
|
||||
async fn() {
|
||||
await deleteChannel(data.guildID, data.channelID);
|
||||
},
|
||||
...testOptions,
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: "delete a guild",
|
||||
async fn() {
|
||||
await deleteServer(data.guildID);
|
||||
data.guildID = "";
|
||||
assertEquals(data.guildID, "");
|
||||
},
|
||||
...testOptions,
|
||||
});
|
||||
|
||||
// This is meant to be the final test that forcefully crashes the bot
|
||||
Deno.test({
|
||||
name: "exit the process forcefully after all the tests are done",
|
||||
async fn() {
|
||||
Deno.exit(1);
|
||||
},
|
||||
...testOptions,
|
||||
});
|
||||
Reference in New Issue
Block a user