Merge branch 'master' of https://github.com/Skillz4Killz/Discordeno into unit-tests

This commit is contained in:
ayyanm
2020-10-28 09:13:49 -07:00
11 changed files with 112 additions and 54 deletions
-13
View File
@@ -1,13 +0,0 @@
name: Greetings
on: [pull_request, issues]
jobs:
greeting:
runs-on: ubuntu-latest
steps:
- uses: actions/first-interaction@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
issue-message: "Thank you for helping contribute to Discordeno. I really do appreciate any and all contributions! Hopefully, together we will be able to make the very best bot Discord API module in the world. Since, this is your very first issue, feel free to look around the repository and then hop on into the Discord server, where you can chat with me directly. https://discord.gg/J4NqJ72"
pr-message: "Thank you for helping contribute to Discordeno. I really do appreciate any and all contributions! Hopefully, together we will be able to make the very best Discord API module in the world. Since, this is your very first pull request, feel free to look around the repository and then hop on into the Discord server, where you can chat with me directly. https://discord.gg/J4NqJ72"
+20 -20
View File
@@ -2,15 +2,19 @@
> Discord API library wrapper in Deno > Discord API library wrapper in Deno
[![Discord](https://img.shields.io/discord/223909216866402304?color=7289da&logo=discord&logoColor=white)](https://discord.gg/J4NqJ72) [![Discord](https://img.shields.io/discord/223909216866402304?color=7289da&logo=discord&logoColor=dark)](https://discord.gg/J4NqJ72)
![Testing/Linting](https://github.com/Skillz4Killz/Discordeno/workflows/Testing/Linting/badge.svg) ![Testing/Linting](https://github.com/Skillz4Killz/Discordeno/workflows/Testing/Linting/badge.svg)
[![nest.land](https://nest.land/badge-large.svg)](https://nest.land/package/Discordeno) [![nest badge](https://nest.land/badge.svg)](https://nest.land/package/Discordeno)
[Website](https://discordeno.netlify.app) [WIP] ![Test](https://github.com/Skillz4Killz/Discordeno/workflows/Test/badge.svg)
## Beginner Developers ## Why Discordeno?
Don't worry a lot of developers start out coding their first projects as a Discord bot(I did 😉) and it is not so easy. With Discordeno, I tried to build it in a way that solved all the headaches I had when first starting out coding bots. If you are a beginner developer, please use a boilerplate: The official one is at: [GitHub](https://github.com/Skillz4Killz/Discordeno-bot-template) but there will be more listed on the website. It is a beautiful website indeed! Check it out! ### Beginner Developers
Don't worry a lot of developers start out coding their first projects as a Discord bot (I did 😉) and it is not so easy to do so. Discordeno is built considering all the issues wit pre-existing libraries, such as discord.js, and issues that I had when I first started out coding bots.
If you are a beginner developer, please use this official boilerplate: [GitHub](https://github.com/Skillz4Killz/Discordeno-bot-template) but there will be more listed on the website. It is a beautiful website indeed! Check it out!
**Modular commands, arguments, events, inhibitors, monitors, tasks.** **Modular commands, arguments, events, inhibitors, monitors, tasks.**
@@ -41,15 +45,10 @@ Don't worry a lot of developers start out coding their first projects as a Disco
- Uses i18next, one of the best localization tools available. - Uses i18next, one of the best localization tools available.
- Supports nested folders to keep cleaner translation files - Supports nested folders to keep cleaner translation files
**Hot Reloadable** - **Hot Reloadable**: Easily update your code without having to restart the bot everytime.
- **Step By Step Guide**: There is a step by step walkthrough to learn how to create Discord bots with Discordeno on our website!
- Easily update your code without having to restart the bot everytime. ### Advanced Developers
**Step By Step Guide**
- There is a step by step walkthrough to learn how to create Discord bots with Discordeno on our website!
## Advanced Developers
The instructions below are meant for advanced developers! The instructions below are meant for advanced developers!
@@ -64,7 +63,7 @@ StartBot({
intents: [Intents.GUILD_MESSAGES, Intents.GUILDS], intents: [Intents.GUILD_MESSAGES, Intents.GUILDS],
eventHandlers: { eventHandlers: {
ready: () => { ready: () => {
console.log(`Logged!`); console.log('Successfully connected to gateway');
}, },
messageCreate: (message) => { messageCreate: (message) => {
if (message.content === "!ping") { if (message.content === "!ping") {
@@ -77,12 +76,13 @@ StartBot({
Alternatively, you can use boilerplate template repositories that were created by wonderful developers. Review the list on the website, and add any of yours if you make your own. Alternatively, you can use boilerplate template repositories that were created by wonderful developers. Review the list on the website, and add any of yours if you make your own.
![image](https://i.imgur.com/z1BfUnt.png) ## Documentation
#### Dark Mode - [API Documentation](https://doc.deno.land/https/deno.land/x/discordeno/mod.ts)
- [Guide](https://discordeno.netlify.com)
- [Support server](https://discord.gg/J4NqJ72)
- [Contributing Guide](https://github.com/Skillz4Killz/Discordeno/blob/master/.github/CONTRIBUTING.md)
![image](https://i.imgur.com/Vr2Bebr.png) ## License
### Tests MIT © Skillz4Killz
![Test](https://github.com/Skillz4Killz/Discordeno/workflows/Test/badge.svg)
+2 -2
View File
@@ -2,16 +2,16 @@ name: Discordeno
description: >- description: >-
Discord Deno TypeScript API library wrapper(Officially vetted library by Discord Deno TypeScript API library wrapper(Officially vetted library by
Discord Team) https://discordeno.netlify.app Discord Team) https://discordeno.netlify.app
version: 9.0.5 version: 9.0.12
stable: true stable: true
entry: mod.ts entry: mod.ts
repository: 'https://github.com/Skillz4Killz/Discordeno' repository: 'https://github.com/Skillz4Killz/Discordeno'
files: files:
- ./src/**/* - ./src/**/*
- LICENSE - LICENSE
- mod.ts
- README.md - README.md
- tsconfig.json - tsconfig.json
- ./deps.ts - ./deps.ts
- mod.ts
checkAll: false checkAll: false
unlisted: false unlisted: false
+1
View File
@@ -48,5 +48,6 @@ export async function handleInternalGuildRoleUpdate(data: DiscordPayload) {
if (!cachedRole) return; if (!cachedRole) return;
const role = await structures.createRole(payload.role); const role = await structures.createRole(payload.role);
guild.roles.set(payload.role.id, role);
eventHandlers.roleUpdate?.(guild, role, cachedRole); eventHandlers.roleUpdate?.(guild, role, cachedRole);
} }
+12 -1
View File
@@ -1,8 +1,10 @@
import { endpoints } from "../constants/discord.ts"; import { endpoints } from "../constants/discord.ts";
import { cacheHandlers } from "../controllers/cache.ts";
import { RequestManager } from "../module/requestManager.ts"; import { RequestManager } from "../module/requestManager.ts";
import { structures } from "../structures/mod.ts"; import { structures } from "../structures/mod.ts";
import type { import {
ChannelEditOptions, ChannelEditOptions,
ChannelTypes,
CreateInviteOptions, CreateInviteOptions,
FollowedChannelPayload, FollowedChannelPayload,
GetMessages, GetMessages,
@@ -160,6 +162,15 @@ export async function sendMessage(
} }
} }
const channel = await cacheHandlers.get("channels", channelID);
if (!channel) throw new Error(Errors.CHANNEL_NOT_FOUND);
if (
![ChannelTypes.DM, ChannelTypes.GUILD_NEWS, ChannelTypes.GUILD_TEXT]
.includes(channel.type)
) {
throw new Error(Errors.CHANNEL_NOT_TEXT_BASED);
}
const result = await RequestManager.post( const result = await RequestManager.post(
endpoints.CHANNEL_MESSAGES(channelID), endpoints.CHANNEL_MESSAGES(channelID),
{ {
+1 -1
View File
@@ -51,7 +51,7 @@ export async function createBasicShard(
const basicShard: BasicShard = { const basicShard: BasicShard = {
id: shardID, id: shardID,
socket: await connectWebSocket(`${data.url}?v=6&encoding=json`), socket: await connectWebSocket(`${data.url}?v=8&encoding=json`),
resumeInterval: 0, resumeInterval: 0,
sessionID: oldShard?.sessionID || "", sessionID: oldShard?.sessionID || "",
previousSequenceNumber: oldShard?.previousSequenceNumber || 0, previousSequenceNumber: oldShard?.previousSequenceNumber || 0,
+18 -7
View File
@@ -286,6 +286,23 @@ async function runMethod(
}); });
} }
async function logErrors(response: Response, errorStack?: unknown) {
try {
const error = await response.json();
console.error(error);
eventHandlers.debug?.({ type: "error", data: { errorStack, error } });
} catch {
eventHandlers.debug?.(
{
type: "error",
data: { errorStack },
},
);
console.error(response);
}
}
function handleStatusCode(response: Response, errorStack?: unknown) { function handleStatusCode(response: Response, errorStack?: unknown) {
const status = response.status; const status = response.status;
@@ -296,13 +313,7 @@ function handleStatusCode(response: Response, errorStack?: unknown) {
return true; return true;
} }
eventHandlers.debug?.( logErrors(response, errorStack);
{
type: "error",
data: { errorStack },
},
);
console.error(response);
switch (status) { switch (status) {
case HttpResponseCode.BadRequest: case HttpResponseCode.BadRequest:
+47 -3
View File
@@ -1,12 +1,18 @@
import type { Timestamps } from "./discord.ts";
export interface ActivityPayload { export interface ActivityPayload {
name: string; name: string;
type: number; type: number;
url?: string; url?: string;
created_at: number; created_at: number;
timestamps: Timestamps; timestamps?: ActivityTimestamps;
application_id?: string;
details?: string; details?: string;
state?: string;
emoji?: ActivityEmoji;
party?: ActivityParty;
assets?: ActivityAssets;
secrets?: ActivitySecrets;
instance?: boolean;
flags?: number;
} }
export enum ActivityType { export enum ActivityType {
@@ -21,3 +27,41 @@ export enum ActivityType {
/** Example: "Competing in Arena World Champions" */ /** Example: "Competing in Arena World Champions" */
Competing, Competing,
} }
export interface ActivityTimestamps {
start?: number;
end?: number;
}
export interface ActivityEmoji {
name: string;
id?: string;
animated?: boolean;
}
export interface ActivityParty {
id?: string;
size?: [number, number];
}
export interface ActivityAssets {
large_image?: string;
large_text?: string;
small_image?: string;
small_text?: string;
}
export interface ActivitySecrets {
join?: string;
spectate?: string;
match?: string;
}
export enum ActivityFlags {
INSTANCE = 1 << 0,
JOIN = 1 << 1,
SPECTATE = 1 << 2,
JOIN_REQUEST = 1 << 3,
SYNC = 1 << 4,
PLAY = 1 << 5,
}
-5
View File
@@ -196,11 +196,6 @@ export interface Properties {
$device: string; $device: string;
} }
export interface Timestamps {
start?: number;
end?: number;
}
export interface Emoji { export interface Emoji {
name: string; name: string;
id?: string; id?: string;
+2
View File
@@ -31,4 +31,6 @@ export enum Errors {
CHANNEL_NOT_IN_GUILD = "CHANNEL_NOT_IN_GUILD", CHANNEL_NOT_IN_GUILD = "CHANNEL_NOT_IN_GUILD",
INVALID_WEBHOOK_NAME = "INVALID_WEBHOOK_NAME", INVALID_WEBHOOK_NAME = "INVALID_WEBHOOK_NAME",
INVALID_WEBHOOK_OPTIONS = "INVALID_WEBHOOK_OPTIONS", INVALID_WEBHOOK_OPTIONS = "INVALID_WEBHOOK_OPTIONS",
CHANNEL_NOT_FOUND = "CHANNEL_NOT_FOUND",
CHANNEL_NOT_TEXT_BASED = "CHANNEL_NOT_TEXT_BASED",
} }
+9 -2
View File
@@ -34,6 +34,8 @@ export function memberHasPermission(
const permissionBits = memberRoleIDs.map((id) => const permissionBits = memberRoleIDs.map((id) =>
guild.roles.get(id)?.permissions guild.roles.get(id)?.permissions
) )
// Removes any edge case undefined
.filter((id) => id)
.reduce((bits, permissions) => { .reduce((bits, permissions) => {
bits |= BigInt(permissions); bits |= BigInt(permissions);
return bits; return bits;
@@ -86,13 +88,18 @@ export async function hasChannelPermissions(
permissions: Permissions[], permissions: Permissions[],
) { ) {
const channel = await cacheHandlers.get("channels", channelID); const channel = await cacheHandlers.get("channels", channelID);
if (!channel?.guildID) return true; if (!channel) return false;
if (!channel.guildID) return true;
const guild = await cacheHandlers.get("guilds", channel.guildID); const guild = await cacheHandlers.get("guilds", channel.guildID);
if (!guild) return false; if (!guild) return false;
if (guild.ownerID === memberID) return true; if (guild.ownerID === memberID) return true;
if (botHasPermission(guild.id, [Permissions.ADMINISTRATOR])) return true; if (
await memberIDHasPermission(memberID, guild.id, ["ADMINISTRATOR"])
) {
return true;
}
const member = guild.members.get(memberID); const member = guild.members.get(memberID);
if (!member) return false; if (!member) return false;