discord-freepbx-manager/index.js
2025-02-11 08:52:22 -07:00

191 lines
5.6 KiB
JavaScript

require("dotenv").config();
const cron = require("node-cron")
const fs = require('fs');
const mariadb = require("mariadb");
const pool = mariadb.createPool({
host: process.env.DB_HOST,
port: process.env.DB_PORT || 3306,
user: process.env.DB_USER,
password: process.env.DB_PASS,
database: "asterisk",
connectionLimit: 5,
});
const FreepbxManager = require("./freepbx");
const fpbx = new FreepbxManager({
url: process.env.FREEPBX_URL,
clientId: process.env.FREEPBX_CLIENT_ID,
clientSecret: process.env.FREEPBX_CLIENT_SECRET,
dbPool: pool,
});
const Discord = require('discord.js');
const client = new Discord.Client({
intents: ["GuildMembers", "Guilds", "GuildPresences"]
});
const colors = require('colors');
const log = {
log: (msg) => {
console.log(msg);
},
info: (msg) => {
console.log(`${colors.cyan("[INFO]")} ${msg}`);
},
warn: (msg) => {
console.log(`${colors.yellow("[WARN]")} ${msg}`);
},
error: (msg) => {
console.log(`${colors.red("[ERROR]")} ${msg}`);
},
success: (msg) => {
console.log(`${colors.green("[SUCCESS]")} ${msg}`);
},
debug: (msg) => {
console.log(`${colors.magenta("[DEBUG]")} ${msg}`);
}
}
// Put clients in global for use elsewhere.
global.pool = pool;
global.fpbx = fpbx;
global.client = client;
global.log = log;
const deletion = require("./deletions.js");
client.on('ready', async () => {
log.success(`Logged in as ${client.user.displayName}`);
const commands = require("./commands")
// Command registration
log.info("Registering commands...")
await (async () => {
try {
const rest = new Discord.REST().setToken(client.token);
// Global Commands
log.info(`Registering global commands`);
rest.put(Discord.Routes.applicationCommands(client.user.id), { body: commands }).then(() => {
log.success("Global commands registered")
}).catch((error) => {
log.error(error)
});
// // Clear guild commands
// log.info("Clearing guild commands...")
// const guilds = client.guilds.cache.map(guild => guild.id);
// for (const guild of guilds) {
// rest.put(Discord.Routes.applicationGuildCommands(client.user.id, guild), { body: [] }).then(() => {
// log.success(`Cleared commands for guild ${guild}`)
// }).catch((error) => {
// log.error(error)
// });
// }
} catch (error) {
log.error(error)
}
})();
cron.schedule('* * * * *', () => {
try {
deletion.handleScheduled();
} catch (error) {
log.error(`Failed to execute deletion task: ${error}`);
}
});
cron.schedule('0 * * * *', () => {
log.info("Checking for orphaned extensions...");
try {
deletion.findOrphans();
} catch (error) {
log.error(`Failed to execute orphan task: ${error}`);
}
});
deletion.findOrphans();
deletion.handleScheduled();
});
client.on('interactionCreate', async interaction => {
if (!interaction.inGuild()) return interaction.reply({ content: "This bot is not designed to be used in DMs.", ephemeral: true });
switch (interaction.type) {
case Discord.InteractionType.ApplicationCommand:
const command = require(`./interactionHandlers/commands/${interaction.commandName}`);
if (!command) return;
try {
await command.execute(interaction);
} catch (error) {
log.error(error);
await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true }).catch((error) => {
log.error(`Failed to inform user of error: ${error}`);
});;
}
break;
case Discord.InteractionType.MessageComponent:
const component = require(`./interactionHandlers/components/${interaction.customId}`);
if (!component) return;
try {
await component.execute(interaction);
} catch (error) {
log.error(error);
await interaction.reply({ content: 'There was an error while executing this component!', ephemeral: true }).catch((error) => {
log.error(`Failed to inform user of error: ${error}`);
});;
}
break;
}
});
client.on('guildMemberAdd', async member => {
const [deletion] = await pool.query('SELECT * FROM discord_deletions WHERE discordId = ?', [member.id]);
if (deletion) {
await pool.query('DELETE FROM discord_deletions WHERE discordId = ?', [member.id]);
log.info(`User ${member.id} rejoined, removing deletion`);
}
});
client.on('guildMemberRemove', async member => {
const [deletion] = await pool.query('SELECT * FROM discord_deletions WHERE discordId = ?', [member.id]);
const [user] = await pool.query('SELECT * FROM discord_users WHERE discordId = ?', [member.id]);
if (!user) return;
if (!deletion) {
const deleteAt = new Date(Date.now() + 60 * 60 * 1000); // 1 hour in the future
await pool.query('INSERT INTO discord_deletions (discordId, extension, deleteAt) VALUES (?, ?, ?)', [member.id, user.extension, deleteAt]);
log.info(`User ${member.id} left and had an extension, marking for deletion`);
}
});
if (fs.existsSync("./import.json")) {
const importData = JSON.parse(fs.readFileSync("./import.json", "utf8"));
const insertData = async () => {
try {
const conn = await pool.getConnection();
for (const ext in importData) {
const discordId = importData[ext];
await conn.query("INSERT INTO discord_users (extension, discordId) VALUES (?, ?)", [ext, discordId]);
}
conn.release();
log.success("Data imported successfully.");
} catch (error) {
log.error(`Failed to import data: ${error}`);
}
};
insertData();
}
// Startup
require("./migrations")(pool).then(() => {
log.success("Database migrations complete.");
log.info("Starting Discord client...");
client.login(process.env.DISCORD_TOKEN);
}).catch((err) => {
log.error(`Database migrations failed: ${err}`);
process.exit(1);
});