diff --git a/README.md b/README.md index a2effde67..b4c24da9b 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,31 @@ If you are just starting out, you can use the Discordeno Template repo to get th | Official Boilerplate | Skillz4Killz#4500 | [Github](https://github.com/Skillz4Killz/Discordeno-bot-template), [Support Server](https://discord.gg/J4NqJ72) | This is a very minimalistic design for a boilerplate for your bot to get you started. | | DenoBot | NTM Nathan#0001 | [Github](https://github.com/ntm-development/DenoBot), [Support Server](https://discord.com/invite/G2rb53z) | Another boilerplate example of the first one, with more commands and improvements. | +If you would like to start from scratch without any boilerplate/framework: + +```ts +import Client from "https://raw.githubusercontent.com/Skillz4Killz/Discordeno/v4/module/client.ts"; +import { Intents } from "https://raw.githubusercontent.com/Skillz4Killz/Discordeno/v4/types/options.ts"; + +const BotOptions = { + token: "token", + botID: "client ID", + intents: [Intents.GUILD_MESSAGES], + eventHandlers: { + ready: () => { + console.log(`Logged!`); + }, + messageCreate: (message) => { + if(message.content === "!ping"){ + message.channel.sendMessage("Pong!"); + } + } + } +}; + +Client(BotOptions); +``` + ## Open Source Bots Using Discordeno | Bot Name | Developer | Links | diff --git a/structures/guild.ts b/structures/guild.ts index f00343e51..9cdb75a98 100644 --- a/structures/guild.ts +++ b/structures/guild.ts @@ -1,4 +1,5 @@ import { CreateGuildPayload } from "../types/guild.ts"; +import Collection from "../utils/collection.ts"; import { createRole } from "./role.ts"; import { createMember, Member } from "./member.ts"; import { createChannel } from "./channel.ts"; @@ -38,21 +39,21 @@ export const createGuild = (data: CreateGuildPayload, shardID: number) => { preferredLocale: data.preferred_locale, /** The roles in the guild */ - roles: new Map(data.roles.map((r) => [r.id, createRole(r)])), + roles: new Collection(data.roles.map((r) => [r.id, createRole(r)])), /** When this guild was joined at. */ joinedAt: Date.parse(data.joined_at), /** The users in this guild. */ - members: new Map(), + members: new Collection(), /** The channels in the guild */ - channels: new Map( + channels: new Collection( data.channels.map((c) => [c.id, createChannel(c, data.id)]), ), /** The presences of all the users in the guild. */ - presences: new Map(data.presences.map((p) => [p.user.id, p])), + presences: new Collection(data.presences.map((p) => [p.user.id, p])), /** The total number of members in this guild. This value is updated as members leave and join the server. However, if you do not have the intent enabled to be able to listen to these events, then this will not be accurate. */ memberCount: data.member_count || 0, /** The Voice State data for each user in a voice channel in this server. */ - voiceStates: new Map(data.voice_states.map((vs) => [vs.user_id, { + voiceStates: new Collection(data.voice_states.map((vs) => [vs.user_id, { ...vs, guildID: vs.guild_id, channelID: vs.channel_id, diff --git a/utils/cache.ts b/utils/cache.ts index 799584612..653966f44 100644 --- a/utils/cache.ts +++ b/utils/cache.ts @@ -1,20 +1,21 @@ +import Collection from "./collection.ts"; import { Message } from "../structures/message.ts"; import { Guild } from "../structures/guild.ts"; import { Channel } from "../structures/channel.ts"; import { delay } from "https://deno.land/std@0.50.0/async/delay.ts"; export interface CacheData { - guilds: Map; - channels: Map; - messages: Map; - unavailableGuilds: Map; + guilds: Collection; + channels: Collection; + messages: Collection; + unavailableGuilds: Collection; } export const cache: CacheData = { - guilds: new Map(), - channels: new Map(), - messages: new Map(), - unavailableGuilds: new Map(), + guilds: new Collection(), + channels: new Collection(), + messages: new Collection(), + unavailableGuilds: new Collection(), }; async function cleanMessageCache() { diff --git a/utils/collection.ts b/utils/collection.ts new file mode 100644 index 000000000..98d4cf96f --- /dev/null +++ b/utils/collection.ts @@ -0,0 +1,78 @@ +import { chooseRandom } from "./utils.ts"; + +export default class Collection extends Map { + array() { + return [...this.values()]; + } + + first() { + return this.values().next().value; + } + + last() { + return [...this.values()][this.size - 1]; + } + + random() { + return chooseRandom([...this.values()]); + } + + find(callback: (value: V, key: K) => boolean) { + for (const key of this.keys()) { + const value = this.get(key)!; + if (callback(value, key)) return value; + } + // If nothing matched + return; + } + + filter(callback: (value: V, key: K) => boolean) { + const relevant = new Collection(); + this.forEach((value, key) => { + if (callback(value, key)) relevant.set(key, value); + }); + + return relevant; + } + + map(callback: (value: V, key: K) => T) { + const results = []; + for (const key of this.keys()) { + const value = this.get(key)!; + results.push(callback(value, key)); + } + return results; + } + + some(callback: (value: V, key: K) => boolean) { + for (const key of this.keys()) { + const value = this.get(key)!; + if (callback(value, key)) return true; + } + + return false; + } + + every(callback: (value: V, key: K) => boolean) { + for (const key of this.keys()) { + const value = this.get(key)!; + if (!callback(value, key)) return false; + } + + return true; + } + + reduce( + callback: (accumulator: T, value: V, key: K) => T, + initialValue?: T, + ): T { + let accumulator: T = initialValue!; + + for (const key of this.keys()) { + const value = this.get(key)!; + accumulator = callback(accumulator, value, key); + } + + return accumulator; + } +} diff --git a/utils/utils.ts b/utils/utils.ts index 6dd3098a0..e3b5f4cca 100644 --- a/utils/utils.ts +++ b/utils/utils.ts @@ -13,3 +13,7 @@ export function editBotsStatus( ) { sendGatewayCommand("EDIT_BOTS_STATUS", { status, game: { name, type } }); } + +export function chooseRandom(array: T[]) { + return array[Math.floor(Math.random() * array.length)]; +}