Select the types of activity you want to include in your feed.
[READ-ONLY] Mirror of https://github.com/maybeanerd/MagiBot. MagiBot - the community building discord bot that adds joinsounds to your voice channels!
discord.gg/2Evcf4T
···66import { salt } from './salt';
77import { profile } from './profile';
88import { joinsound } from './joinsound';
99+import { info } from './info';
910import { admin } from './admin/adminApplicationCommands';
1011import { MagibotSlashCommand } from '../types/command';
11121213export const applicationCommands: { [k: string]: MagibotSlashCommand } = {
1313- ping,
1414- roll,
1515- invite,
1616- bugreport,
1717- randomfact,
1818- salt,
1919- profile,
2020- joinsound,
1414+ ping,
1515+ roll,
1616+ invite,
1717+ bugreport,
1818+ randomfact,
1919+ salt,
2020+ profile,
2121+ joinsound,
2222+ info,
21232222- // all admin commands
2323- admin,
2424+ // all admin commands
2525+ admin,
2426};
+64
src/commands/info.ts
···11+import { CommandInteraction, MessageEmbedOptions } from 'discord.js';
22+import { SlashCommandBuilder } from '@discordjs/builders';
33+import { COLOR, user, SIGN } from '../shared_assets';
44+import { commandCategories } from '../types/enums';
55+import { MagibotSlashCommand } from '../types/command';
66+77+const inviteURL = 'https://discord.com/api/oauth2/authorize?client_id=384820232583249921&permissions=276131153&redirect_uri=https%3A%2F%2Fdiscord.gg%2F2Evcf4T&scope=bot';
88+99+async function main(interaction: CommandInteraction) {
1010+ const info: Array<{
1111+ name: string;
1212+ value: string;
1313+ inline: boolean;
1414+ }> = [
1515+ {
1616+ name: 'Links',
1717+ value: `[Invite me to your guild](${inviteURL})\n[Official support Discord](https://discord.gg/2Evcf4T)`,
1818+ inline: false,
1919+ },
2020+ {
2121+ name: 'How to support MagiBot',
2222+ value:
2323+ 'Pledge on [MagiBots Patreon](https://www.patreon.com/MagiBot)\nLeave a review on [bots.ondiscord.xyz](https://bots.ondiscord.xyz/bots/384820232583249921)!',
2424+ inline: false,
2525+ },
2626+ {
2727+ name: 'A bit of background',
2828+ value:
2929+ "MagiBot is being developed in Germany by T0TProduction#0001 as a side project.\nIt was originally a private bot for a Discord guild themed after the Pokemon Magikarp which is the reason it's called MagiBot.",
3030+ inline: false,
3131+ },
3232+ ];
3333+ const embed: MessageEmbedOptions = {
3434+ color: COLOR,
3535+ description: 'Some information about the bot:',
3636+ fields: info,
3737+ footer: {
3838+ iconURL: user().avatarURL() || '',
3939+ text: SIGN,
4040+ },
4141+ };
4242+4343+ interaction.reply({ embeds: [embed] });
4444+}
4545+4646+const slashCommand = new SlashCommandBuilder()
4747+ .setName('info')
4848+ .setDescription('Get some info about the bot and official resources.');
4949+5050+export const info: MagibotSlashCommand = {
5151+ help() {
5252+ return [
5353+ {
5454+ name: '',
5555+ value:
5656+ 'Get some info about the bot as well as links to official MagiBot stuff.',
5757+ },
5858+ ];
5959+ },
6060+ run: main,
6161+ definition: slashCommand.toJSON(),
6262+ permissions: ['SEND_MESSAGES', 'EMBED_LINKS'],
6363+ category: commandCategories.misc,
6464+};
+87-87
src/commands/joinsounds/fileManagement.ts
···11import { createReadStream, createWriteStream } from 'node:fs';
22import {
33- mkdir, unlink, stat, readdir, rmdir,
33+ mkdir, unlink, stat, readdir, rmdir,
44} from 'node:fs/promises';
55import Path from 'path';
66import { get } from 'node:https';
···2121}
22222323async function setupLocalFolders() {
2424- await mkdir(basePath).catch((error) => {
2525- // If the error is that it already exists, that's fine
2626- if (error.code !== 'EEXIST') {
2727- throw error;
2828- }
2929- });
2424+ await mkdir(basePath).catch((error) => {
2525+ // If the error is that it already exists, that's fine
2626+ if (error.code !== 'EEXIST') {
2727+ throw error;
2828+ }
2929+ });
3030}
3131setupLocalFolders();
32323333async function downloadFile(url: string, path: string) {
3434- return new Promise<void>((resolve /* , reject */) => {
3535- get(url, (res) => {
3636- const writeStream = createWriteStream(path);
3737- res.pipe(writeStream);
3838- writeStream.on('finish', () => {
3939- writeStream.close();
4040- resolve();
4141- });
4242- });
4343- });
3434+ return new Promise<void>((resolve /* , reject */) => {
3535+ get(url, (res) => {
3636+ const writeStream = createWriteStream(path);
3737+ res.pipe(writeStream);
3838+ writeStream.on('finish', () => {
3939+ writeStream.close();
4040+ resolve();
4141+ });
4242+ });
4343+ });
4444}
45454646function getFolderSize(path: string): Promise<number> {
4747- return new Promise((resolve, reject) => {
4848- fastFolderSize(path, (err, bytes) => {
4949- if (err) {
5050- reject(err);
5151- }
5252- resolve(bytes !== undefined ? bytes : 9999999);
5353- });
5454- });
4747+ return new Promise((resolve, reject) => {
4848+ fastFolderSize(path, (err, bytes) => {
4949+ if (err) {
5050+ reject(err);
5151+ }
5252+ resolve(bytes !== undefined ? bytes : 9999999);
5353+ });
5454+ });
5555}
56565757const oneMegabyte = 1024 * 1024;
5858const fourtyGigabyte = 40 * 1024 * oneMegabyte;
59596060async function doesServerHaveEnoughSpace() {
6161- const sizeOfFolder = await getFolderSize(basePath);
6262- return sizeOfFolder <= fourtyGigabyte;
6161+ const sizeOfFolder = await getFolderSize(basePath);
6262+ return sizeOfFolder <= fourtyGigabyte;
6363}
64646565const userPrefix = 'user_';
6666const guildPrefix = 'guild_';
67676868function getTargetPath(target: JoinsoundTarget) {
6969- return Path.join(
7070- basePath,
7171- target.userId
7272- ? `${userPrefix}${target.userId}`
7373- : `${guildPrefix}${target.guildId}`,
7474- );
6969+ return Path.join(
7070+ basePath,
7171+ target.userId
7272+ ? `${userPrefix}${target.userId}`
7373+ : `${guildPrefix}${target.guildId}`,
7474+ );
7575}
76767777// eslint-disable-next-line no-undef
7878function gracefullyCatchENOENT(error: NodeJS.ErrnoException) {
7979- // If the error is that it doesn't exists, that's fine
8080- if (error.code !== 'ENOENT') {
8181- throw error;
8282- }
7979+ // If the error is that it doesn't exists, that's fine
8080+ if (error.code !== 'ENOENT') {
8181+ throw error;
8282+ }
8383}
84848585async function doesUserHaveEnoughSpace(
8686- target: JoinsoundTarget,
8787- targetFileName: string,
8686+ target: JoinsoundTarget,
8787+ targetFileName: string,
8888) {
8989- const path = getTargetPath(target);
9090- await mkdir(path).catch((error) => {
9191- // If the error is that it already exists, that's fine
9292- if (error.code !== 'EEXIST') {
9393- throw error;
9494- }
9595- });
9696- const sizeOfFolder = await getFolderSize(path);
9797- const statsOfExistingFile = await stat(targetFileName).catch(
9898- gracefullyCatchENOENT,
9999- );
100100- const sizeOfExistingFile = statsOfExistingFile?.size || 0;
101101- return sizeOfFolder - sizeOfExistingFile <= oneMegabyte;
8989+ const path = getTargetPath(target);
9090+ await mkdir(path).catch((error) => {
9191+ // If the error is that it already exists, that's fine
9292+ if (error.code !== 'EEXIST') {
9393+ throw error;
9494+ }
9595+ });
9696+ const sizeOfFolder = await getFolderSize(path);
9797+ const statsOfExistingFile = await stat(targetFileName).catch(
9898+ gracefullyCatchENOENT,
9999+ );
100100+ const sizeOfExistingFile = statsOfExistingFile?.size || 0;
101101+ return sizeOfFolder - sizeOfExistingFile <= oneMegabyte;
102102}
103103104104function getFilename(target: JoinsoundTarget) {
105105- const title = target.default ? 'default' : `${guildPrefix}${target.guildId}`;
106106- return Path.join(getTargetPath(target), title);
105105+ const title = target.default ? 'default' : `${guildPrefix}${target.guildId}`;
106106+ return Path.join(getTargetPath(target), title);
107107}
108108109109export async function storeJoinsoundOfTarget(
110110- target: JoinsoundTarget,
111111- fileUrl: string,
110110+ target: JoinsoundTarget,
111111+ fileUrl: string,
112112) {
113113- if (!(await doesServerHaveEnoughSpace())) {
114114- // this should not happen. but if it does, we handle it to stop the server from being overloaded
115115- return JoinsoundStoreError.noStorageLeftOnServer;
116116- }
117117- const filename = getFilename(target);
118118- if (!(await doesUserHaveEnoughSpace(target, filename))) {
119119- return JoinsoundStoreError.noStorageLeftForUser;
120120- }
121121- await downloadFile(fileUrl, filename);
122122- return null;
113113+ if (!(await doesServerHaveEnoughSpace())) {
114114+ // this should not happen. but if it does, we handle it to stop the server from being overloaded
115115+ return JoinsoundStoreError.noStorageLeftOnServer;
116116+ }
117117+ const filename = getFilename(target);
118118+ if (!(await doesUserHaveEnoughSpace(target, filename))) {
119119+ return JoinsoundStoreError.noStorageLeftForUser;
120120+ }
121121+ await downloadFile(fileUrl, filename);
122122+ return null;
123123}
124124125125export async function removeLocallyStoredJoinsoundOfTarget(
126126- target: JoinsoundTarget,
126126+ target: JoinsoundTarget,
127127) {
128128- const filename = getFilename(target);
129129- await unlink(filename).catch(gracefullyCatchENOENT);
128128+ const filename = getFilename(target);
129129+ await unlink(filename).catch(gracefullyCatchENOENT);
130130}
131131132132async function getExistingUserFolders() {
133133- const folders = await readdir(basePath, { withFileTypes: true });
134134- return folders
135135- .filter(
136136- (directory) => directory.isDirectory() && directory.name.startsWith(userPrefix),
137137- )
138138- .map((directory) => directory.name.substring(userPrefix.length));
133133+ const folders = await readdir(basePath, { withFileTypes: true });
134134+ return folders
135135+ .filter(
136136+ (directory) => directory.isDirectory() && directory.name.startsWith(userPrefix),
137137+ )
138138+ .map((directory) => directory.name.substring(userPrefix.length));
139139}
140140141141export async function removeLocallyStoredJoinsoundsOfGuild(guildId: string) {
142142- // remove default server sound
143143- await removeLocallyStoredJoinsoundOfTarget({ guildId, default: true });
142142+ // remove default server sound
143143+ await removeLocallyStoredJoinsoundOfTarget({ guildId, default: true });
144144145145- // remove server folder
146146- await rmdir(Path.join(basePath, `${guildPrefix}${guildId}`)).catch(
147147- gracefullyCatchENOENT,
148148- );
145145+ // remove server folder
146146+ await rmdir(Path.join(basePath, `${guildPrefix}${guildId}`)).catch(
147147+ gracefullyCatchENOENT,
148148+ );
149149150150- // remove sounds of all users in server
151151- const userIds = await getExistingUserFolders();
152152- await asyncForEach(userIds, async (userId) => {
153153- await removeLocallyStoredJoinsoundOfTarget({ userId, guildId });
154154- });
150150+ // remove sounds of all users in server
151151+ const userIds = await getExistingUserFolders();
152152+ await asyncForEach(userIds, async (userId) => {
153153+ await removeLocallyStoredJoinsoundOfTarget({ userId, guildId });
154154+ });
155155}
156156157157export function getJoinsoundReadableStreamOfUser(target: JoinsoundTarget) {
158158- return createReadStream(getFilename(target));
158158+ return createReadStream(getFilename(target));
159159}
-64
src/commands/old/info.ts
···11-import { MessageEmbedOptions } from 'discord.js';
22-import { COLOR, user, SIGN } from '../../shared_assets';
33-44-import { commandCategories } from '../../types/enums';
55-import { magibotCommand } from '../../types/command';
66-77-const inviteURL = 'https://discord.com/api/oauth2/authorize?client_id=384820232583249921&permissions=276131153&redirect_uri=https%3A%2F%2Fdiscord.gg%2F2Evcf4T&scope=bot';
88-99-export const inf: magibotCommand = {
1010- dev: false,
1111- name: 'info',
1212- main: ({ message }) => {
1313- const info: Array<{
1414- name: string;
1515- value: string;
1616- inline: boolean;
1717- }> = [];
1818-1919- info.push({
2020- name: 'Links',
2121- value: `[Invite me to your guild](${inviteURL})\n[Official support Discord](https://discord.gg/2Evcf4T)`,
2222- inline: false,
2323- });
2424-2525- info.push({
2626- name: 'How to support MagiBot',
2727- value:
2828- 'Donate a buck via [Paypal](https://paypal.me/pools/c/8be5ok31vB)\nPledge on [MagiBots Patreon](https://www.patreon.com/MagiBot)\nLeave a review on [bots.ondiscord.xyz](https://bots.ondiscord.xyz/bots/384820232583249921)!',
2929- inline: false,
3030- });
3131-3232- info.push({
3333- name: 'A bit of background',
3434- value:
3535- "MagiBot is being developed in Germany by T0TProduction#0001 as a hobby project.\nIt was originally a private bot for a Discord guild themed after the Pokemon Magikarp which is the reason it's called MagiBot.",
3636- inline: false,
3737- });
3838-3939- const embed: MessageEmbedOptions = {
4040- color: COLOR,
4141- description: 'Some information about the bot:',
4242- fields: info,
4343- footer: {
4444- iconURL: user().avatarURL() || '',
4545- text: SIGN,
4646- },
4747- };
4848-4949- message.channel.send({ embeds: [embed] });
5050- },
5151- ehelp() {
5252- return [
5353- {
5454- name: '',
5555- value:
5656- 'Get some info about the bot as well as links to official MagiBot stuff.',
5757- },
5858- ];
5959- },
6060- perm: ['SEND_MESSAGES', 'EMBED_LINKS'],
6161- admin: false,
6262- hide: false,
6363- category: commandCategories.misc,
6464-};
+18-18
src/commands/ping.ts
···44import { MagibotSlashCommand } from '../types/command';
5566const slashCommand = new SlashCommandBuilder()
77- .setName('ping')
88- .setDescription('Returns the round trip time between you and MagiBot!');
77+ .setName('ping')
88+ .setDescription('Returns the round trip time between you and MagiBot!');
991010export const ping: MagibotSlashCommand = {
1111- help() {
1212- return [
1313- {
1414- name: '',
1515- value: 'Ping the bot and get the response time.',
1616- },
1717- ];
1818- },
1919- permissions: 'SEND_MESSAGES',
2020- category: commandCategories.misc,
2121- async run(interaction: CommandInteraction) {
2222- const stop = new Date();
2323- const diff = stop.getTime() - interaction.createdAt.getTime();
2424- await interaction.reply(`Pong! \`(${diff}ms)\``);
2525- },
2626- definition: slashCommand.toJSON(),
1111+ help() {
1212+ return [
1313+ {
1414+ name: '',
1515+ value: 'Ping the bot and get the response time.',
1616+ },
1717+ ];
1818+ },
1919+ permissions: 'SEND_MESSAGES',
2020+ category: commandCategories.misc,
2121+ async run(interaction: CommandInteraction) {
2222+ const stop = new Date();
2323+ const diff = stop.getTime() - interaction.createdAt.getTime();
2424+ await interaction.reply(`Pong! \`(${diff}ms)\``);
2525+ },
2626+ definition: slashCommand.toJSON(),
2727};