diff --git a/structures/client/client.js b/structures/client/client.js index f491b9c..f1227a6 100644 --- a/structures/client/client.js +++ b/structures/client/client.js @@ -7,6 +7,7 @@ import { EventEmitter } from 'events'; import axios from 'axios'; import { exit } from 'process'; import Guild from '../guilds/Guild.js'; +import user from '../messages/User.js'; @@ -158,7 +159,12 @@ export class Client extends EventEmitter { } } else if (response.t == gateWayEvents.InteractionCreate) { - if (data["d"]["user"]["id"] != this.user_profile.id) { + if (data["d"]["member"] && data["d"]["member"]["id"] != this.user_profile.id) { + response.interaction.guild = this.guilds.get(response.interaction.guild_id); + response.interaction.user = new user(data["d"]["member"]["user"]); + this.interactionRecieved(response.interaction); + } + else if (data["d"]["user"]["id"] != this.user_profile.id) { this.interactionRecieved(response.interaction); } } diff --git a/structures/guilds/BaseGuild.js b/structures/guilds/BaseGuild.js new file mode 100644 index 0000000..5afe38d --- /dev/null +++ b/structures/guilds/BaseGuild.js @@ -0,0 +1,142 @@ +export class BaseGuild { + /** @type {String[]} */ + embeded_activities; + + /** @type {String} */ + description; + + /** @type {String} */ + id; + + /** @type {String} */ + name; + + /** @type {String} */ + icon; + + /** @type {Boolean} */ + nsfw; + + /** @type {Map} */ + members; + + /** @type {String} */ + hub_type; + + /** @type {Number} */ + max_video_channel_users; + + /** @type {String[]} */ + stickers; + + /** @type {String} */ + hub_type; + + /** @type {Map} */ + members; + + /** @type {guildRoleManager} */ + roles; + + /** @type {String} */ + banner; + + /** @type {String} */ + application_id; + + /** @type {String} */ + owner_id; + + /** @type {Map} */ + channels; + + /** @type {String} */ + home_header; + + /** @type {Number} */ + premium_tier; + + /** @type {Number} */ + nsfw_level; + + /** @type {Number} */ + verification_level; + + /** @type {Number} */ + mfa_level; + + // /** @type {String} */ //FIXME + // threads; + + /** @type {Number} */ + system_channel_flags; + + /** @type {String} */ + safety_alerts_channel_id; + + /** @type {object[]} */ + presences; + + /** @type {GuildEmoji[]} */ + emojis; + + /** @type {String} */ + public_updates_channel_id; + + /** @type {Object[]} */ + stage_instances; + + /** @type {String} */ + afk_channel_id; + + /** @type {Number} */ + afk_timeout; + + /** @type {Number} */ + verification_level; + + /** @type {Number} */ + default_message_notifications; + + /** @type {Number} */ + explicit_content_filter; + + /** @type {String} */ + system_channel_id; + + /** @type {Number} */ + system_channel_flags; + + /** @type {String} */ + rules_channel_id; + + /** @type {Number} */ + max_presences; + + /** @type {Number} */ + max_members; + + /** @type {String} */ + vanity_url_code; + + /** @type {Number} */ + premium_tier; + + /** @type {Number} */ + premium_subscription_count; + + /** @type {String} */ + preferred_locale; + + /** @type {String} */ + public_updates_channel_id; + + /** @type {Number} */ + max_video_channel_users; + + //Welcome screen + //see https://discord.com/developers/docs/resources/guild#welcome-screen-object + + /** @type {guildStickerManager} */ + stickers; +} \ No newline at end of file diff --git a/structures/guilds/GuildChannelManager.js b/structures/guilds/GuildChannelManager.js new file mode 100644 index 0000000..c6bc017 --- /dev/null +++ b/structures/guilds/GuildChannelManager.js @@ -0,0 +1,45 @@ +import axios from 'axios'; +import {Channel} from '../messages/message.js'; +import Guild from './Guild.js'; + +export class GuildChannelManager { + #token; + + /** @type {Guild} */ + guild; + + /** @type {Map} */ + cache; + + /** + * @returns {Promise} + * @param {{name: String, type: Number, topic: String, position: Number, parent_id: String}} channel + */ + create(channel) { + return new Promise(async (resolve) => { + try { + if (!channel.name) throw "Please provide a channel name"; + + const config = { + headers: { + Authorization: this.#token + } + } + + const response = await axios.post(`https://discord.com/api/guilds/${this.guild.id}/channels`, channel, config); + const newChannel = new Channel(response.data, this.guild, this.#token); + this.cache.set(newChannel.id, newChannel); + resolve(newChannel); + } catch (err) { + throw err; + } + }); + } + + + constructor(token, guild, newCache) { + this.#token = token; + this.guild = guild; + this.cache = newCache; + } +} \ No newline at end of file diff --git a/structures/guilds/GuildStickers.js b/structures/guilds/GuildStickers.js new file mode 100644 index 0000000..f8ee4b2 --- /dev/null +++ b/structures/guilds/GuildStickers.js @@ -0,0 +1,140 @@ +import axios from "axios"; +import user from "../messages/User.js"; +import Guild from "./Guild.js"; + +export class guildSticker { + #token; + + /** @type {String} */ + id; + + /** @type {String} */ + pack_id; + + /** @type {String} */ + name; + + /** @type {String} */ + description; + + /** @type {String} */ + tags; + + /** @type {String} */ + asset; + + /** @type {Number} */ + type; + + /** @type {Number} */ + format_type; + + /** @type {Boolean} */ + available; + + /** @type {Guild} */ + guild; + + /** @type {user} */ + user; + + /** @type {Number} */ + sort_value; + + + #construcorHelper(o) { + for (const k in this) { + if (o[k]) this[k] = o[k]; + else this[k] = 0; + } + } + + /** + * @description modifies the guild sticker IN PLACE + * @param {{name: String, description: String, tags: String}} params + * @returns {Promise} + */ + async modify(params) { + return new Promise(async (resolve) => { + const config = { + headers: { + Authorization: this.#token + } + } + + const response = await axios.patch(`https://discord.com/api/guilds/${this.guild.id}/stickers/${this.id}`, params, config); + this.#construcorHelper(response.data); + + resolve(true); + }); + } + + async delete() { + return new Promise(async (resolve) => { + const config = { + headers: { + Authorization: this.#token + } + } + + await axios.delete(`https://discord.com/api/guilds/${this.guild.id}/stickers/${this.id}`, config); + + resolve(true); + }); + } + + constructor(o, guild, token) { + this.#token = token; + this.guild = guild; + this.#construcorHelper(o); + } +} + + +export class guildStickerManager { + #token; + + /** @type {Map} */ + cache; + + /** @type {Guild} */ + guild; + + /** + * @description Creates the new stickers and adds it to cache + * @returns {Promise} + * @param {{name: String, description: String, tags: String }} sticker + */ + async create(sticker) { + //HOW DO YOU DEAL WITH FILES???????? + //see https://discord.com/developers/docs/reference#image-data maybe? + return Promise.reject(undefined); + return new Promise(async (resolve) => { + if (!sticker.name || !sticker.description || !sticker.tags) return resolve(undefined); + + const config = { + headers: { + Authorization: this.#token + } + } + + const response = await axios.post(`https://discord.com/api/guilds/${this.guild.id}/stickers/${this.id}`, config); + + resolve(new guildSticker(response.data)); + }); + } + + /** + * @param {Guild} guild + * @param {Object[]} o + * @param {String} token + */ + constructor(guild, o, token) { + this.guild = guild; + this.#token = token; + for (const stickerRaw of o) { + const sticker = new guildSticker(stickerRaw); + this.cache.set(sticker.id, sticker); + } + } +} \ No newline at end of file diff --git a/structures/guilds/guild.js b/structures/guilds/guild.js index 996395c..0d50253 100644 --- a/structures/guilds/guild.js +++ b/structures/guilds/guild.js @@ -2,14 +2,17 @@ import axios from 'axios'; import member from './member.js'; import {guildRole, guildRoleManager, guildMemberRoleManager} from './guildRoles.js'; import GuildEmoji from './guildEmoji.js'; -import {Channel} from '../messages/message.js'; import guildInvite from './guildInvite.js'; +import { guildSticker, guildStickerManager } from './GuildStickers.js'; +import { GuildChannelManager } from './GuildChannelManager.js'; +import { Channel } from '../messages/message.js'; //See https://discord.com/developers/docs/resources/guild export default class Guild { #token; + //#region Vars /** @type {String[]} */ embeded_activities; @@ -58,7 +61,7 @@ export default class Guild { /** @type {String} */ owner_id; - /** @type {Map} */ + /** @type {GuildChannelManager} */ channels; /** @type {String} */ @@ -95,7 +98,63 @@ export default class Guild { public_updates_channel_id; /** @type {Object[]} */ - stage_instances + stage_instances; + + /** @type {String} */ + afk_channel_id; + + /** @type {Number} */ + afk_timeout; + + /** @type {Number} */ + verification_level; + + /** @type {Number} */ + default_message_notifications; + + /** @type {Number} */ + explicit_content_filter; + + /** @type {String} */ + system_channel_id; + + /** @type {Number} */ + system_channel_flags; + + /** @type {String} */ + rules_channel_id; + + /** @type {Number} */ + max_presences; + + /** @type {Number} */ + max_members; + + /** @type {String} */ + vanity_url_code; + + /** @type {Number} */ + premium_tier; + + /** @type {Number} */ + premium_subscription_count; + + /** @type {String} */ + preferred_locale; + + /** @type {String} */ + public_updates_channel_id; + + /** @type {Number} */ + max_video_channel_users; + + //Welcome screen + //see https://discord.com/developers/docs/resources/guild#welcome-screen-object + + /** @type {guildStickerManager} */ + stickers; + + //#endregion async #getChannels(token) { @@ -107,10 +166,13 @@ export default class Guild { const response = await axios.get(`https://discord.com/api/guilds/${this.id}/channels`, config); + const m = new Map(); for (const channel of response.data) { if (channel.type == 4) continue; - this.channels.set(channel.id, new Channel(token, channel, this)); + m.set(channel.id, new Channel(channel, this, token)); } + + this.channels = new GuildChannelManager(token, this, m); } @@ -171,6 +233,9 @@ export default class Guild { this.roles = new guildRoleManager(temp, false, token); this.roles.guild = this; } + else if (field == 'stickers') { + this.stickers = new guildStickerManager(this, o[field], token); + } else { this[field] = o[field]; } diff --git a/structures/guilds/guildInvite.js b/structures/guilds/guildInvite.js index 6942183..cda53f1 100644 --- a/structures/guilds/guildInvite.js +++ b/structures/guilds/guildInvite.js @@ -1,4 +1,4 @@ -import author from '../messages/author.js'; +import author from '../messages/User.js'; import Guild from './Guild.js' import { Channel } from '../messages/message.js'; import axios from 'axios'; @@ -38,9 +38,13 @@ export default class invite { async delete() { return new Promise(async (resolve) => { - // const headers = { Authorization: this.#token } - // const response = await axios.delete(`https://discord.com/api/guilds/${this.guild.id}/roles`, role.toObj(), { headers }); - // resolve(response.data); + try { + const headers = { Authorization: this.#token } + const response = await axios.delete(`https://discord.com/api/invites/${this.code}`, { headers }); + resolve(response.data); + } catch (err) { + throw err.data; + } }); } @@ -49,8 +53,8 @@ export default class invite { for (const k in this) { if (o[k]) { if (k == 'guild') { this.guild = guild } - else if (k == 'channel') { this.channel = this.guild.channels.get(o[k]['id']); } - else if (k == 'inviter') { this.inviter = new author(o[k], null); } + // else if (k == 'channel') { this.channel = this.guild.channels.cache?.get(o[k]['id']); } + else if (k == 'inviter') { this.inviter = new author(o[k]); } else { this[k] = o[k]; } } else { this[k] = 0; } } diff --git a/structures/interactions/interaction.js b/structures/interactions/interaction.js index 7421eb4..b3cc91b 100644 --- a/structures/interactions/interaction.js +++ b/structures/interactions/interaction.js @@ -1,7 +1,8 @@ import axios from 'axios'; -import author from '../messages/author.js'; +import author from '../messages/User.js'; import { Channel, message } from '../messages/message.js'; import {Embed} from '../messages/embed.js'; +import Guild from '../guilds/Guild.js'; export class Interaction { @@ -29,6 +30,12 @@ export class Interaction { /** @type {String} */ application_id; + /** @type {Guild} */ + guild; + + /** @type {String} */ + guild_id; + /** * @param {{content: String, ephemeral?: Boolean, embeds: [Embed]} | String} inp @@ -166,10 +173,9 @@ export class Interaction { for (const k in this) { if (intRaw[k] != undefined) { if (k == "user") this[k] = new author(intRaw[k]); - else { if (k == 'channel_id') { - this.channel = new Channel(this.#application.token, intRaw[k]); + this.channel = new Channel(intRaw[k], this.guild, this.#application.token); } this[k] = intRaw[k]; diff --git a/structures/messages/author.js b/structures/messages/User.js similarity index 93% rename from structures/messages/author.js rename to structures/messages/User.js index 8cba8ea..b7075ca 100644 --- a/structures/messages/author.js +++ b/structures/messages/User.js @@ -1,4 +1,4 @@ -export default class msgAuthor { +export default class user { /** @type {String} */ id; diff --git a/structures/messages/message.js b/structures/messages/message.js index 6cd64f0..c0cf484 100644 --- a/structures/messages/message.js +++ b/structures/messages/message.js @@ -1,4 +1,4 @@ -import author from './author.js'; +import author from './User.js'; import axios from 'axios'; @@ -56,7 +56,7 @@ export class Channel { } - constructor(token, channel, guild) { + constructor(channel, guild, token = null) { this.#token = token; for (const k in this) { if (channel[k]) this[k] = channel[k]; @@ -95,6 +95,17 @@ export class Channel { resolve(new message(response.data, this.#token)); }); } + + toObj() { + var obj = {}; + for (const key in this) { + if (key != '#token' && key != 'guild') { + obj[key] = this[key]; + } + } + + return obj; + } } @@ -221,6 +232,7 @@ export class message { */ constructor(msgRaw, token, guild) { this.#token = token; + this.guild = guild; for (const k in this) { if (msgRaw[k] != undefined) { @@ -232,7 +244,7 @@ export class message { } else { if (k == 'channel_id') { - this.channel = new Channel(this.#token, {id: msgRaw[k]}, null); + this.channel = new Channel({id: msgRaw[k]}, this.guild, this.#token); } this[k] = msgRaw[k]; diff --git a/tests/guildTests.js b/tests/guildTests.js index 4310320..2508760 100644 --- a/tests/guildTests.js +++ b/tests/guildTests.js @@ -1,5 +1,6 @@ import Guild from "../structures/guilds/Guild.js"; import { guildRole, newGuildRoleObj } from "../structures/guilds/guildRoles.js"; +import { Channel } from "../structures/messages/message.js"; import { Client } from "../structures/types.js"; const delay = ms => new Promise(resolve => setTimeout(resolve, ms)); @@ -8,10 +9,10 @@ export default async function temp(c) { // c.guilds.forEach(/** @param {Guild} guild */ (guild) => { // console.log(guild); // }); - + const guild = c.guilds.get("930148608400035860"); const member = guild.members.get("720349017829015633"); - console.log(member.roles.cache); + // console.log(member.roles.cache); if (!member.roles.has('946610800418762792')) { const response = await member.roles.add('946610800418762792'); @@ -27,17 +28,19 @@ export default async function temp(c) { // console.log(response2); await delay(2000); - const response3 = await guild.roles.delete(response); + const response3 = await guild.roles.delete(response2); // console.log(response3); } const invites = await guild.getInvites(); await delay(1000); - + //Delete any invite that's gonna expire for (const invite of invites) { if (invite.max_age != 0) { console.log(await invite.delete()); } } + + const newChannel = await guild.channels.create({name: "temptemp"}); } \ No newline at end of file