Files
bot_Tamiseur/src/commands/salonpostam/freebox.ts
2024-08-07 01:09:05 +02:00

151 lines
7.2 KiB
TypeScript

import { SlashCommandBuilder, ChatInputCommandInteraction, EmbedBuilder, Message, inlineCode } from 'discord.js'
import * as Freebox from '../../utils/freebox'
import dbGuild from '../../schemas/guild'
import crypto from 'crypto'
import https from 'https'
//import path from 'path'
//import fs from 'fs'
interface ReturnMsgData {
status: string
error_code?: string
Title?: string
Message?: string
}
function returnMsg(result: ReturnMsgData) {
if (result.status === 'fail') return `La commande a échouée !\n${inlineCode(`${result.Title}: ${result.Message}`)}`
if (result.status === 'error') return `Y'a eu une erreur !\n${inlineCode(`${result.error_code}`)}`
}
export default {
data: new SlashCommandBuilder().setName('freebox').setDescription("Accéder à l'API FreeboxOS !")
.addSubcommand(subcommand => subcommand.setName('import').setDescription("Envoyer un fichier d'autorité de certification."))
.addSubcommand(subcommand => subcommand.setName('version').setDescription("Afficher la version de l'API."))
.addSubcommand(subcommand => subcommand.setName('init').setDescription("Créer une app sur la Freebox pour s'authentifier."))
.addSubcommandGroup(subcommandGroup => subcommandGroup.setName('get').setDescription('Récupérer des données.')
.addSubcommand(subcommand => subcommand.setName('connection').setDescription('Récupérer les informations de connexion.'))
),
async execute(interaction: ChatInputCommandInteraction) {
let guildProfile = await dbGuild.findOne({ guildId: interaction?.guild?.id })
if (!guildProfile) return interaction.reply({ content: `Database data for **${interaction.guild?.name}** does not exist, please initialize with \`/database init\` !` })
let dbData = guildProfile.get('guildFbx')
if (!dbData?.enabled) return interaction.reply({ content: `Freebox module is disabled for **${interaction.guild?.name}**, please activate with \`/database edit guildFbx.enabled True\` !` })
let host = dbData.host as string
if (!host) return interaction.reply({ content: `Freebox host is not set for **${interaction.guild?.name}**, please set with \`/database edit guildFbx.host <host>\` !` })
let version = dbData.version as number
if (!version) return interaction.reply({ content: `Freebox API version is not set for **${interaction.guild?.name}**, please set with \`/database edit guildFbx.version <version>\` !` })
let httpsOptions = {}
//let caCrt = fs.readFileSync(path.resolve(__dirname, '../../static/freebox-ecc-root-ca.crt'))
// MIME Type : application/x-x509-ca-cert
//if (caCrt) httpsOptions = { ca: caCrt }
let httpsAgent = new https.Agent(httpsOptions)
if (interaction.options.getSubcommand() === 'import') {
let filter = (m: Message) => m.author.id === interaction.user.id
await interaction.reply({ content: 'Please send another message with the CA file attached, you have one minute.', fetchReply: true }).then(async () => {
console.log('waiting for message')
await interaction.channel?.awaitMessages({ filter, time: 60_000, errors: ['time'] }).then(async collected => {
console.log(collected)
let message = collected.first()
if (!message?.attachments.size) return interaction.followUp('No file was sent in your message!')
let attachment = message.attachments.first()
console.log(attachment)
// Save the file to the database // TODO
interaction.followUp(`File saved, you can now interact with your Freebox!`)
}).catch(() => interaction.followUp('No message was sent before the time limit!'))
})
}
else if (interaction.options.getSubcommand() === 'version') {
let result = await Freebox.Core.Version(host, httpsAgent)
if (result.status === 'success') {
let embed = new EmbedBuilder()
embed.setTitle('FreeboxOS API Version')
embed.setDescription(`Version: ${result.data.api_version}`)
return await interaction.reply({ embeds: [embed] })
}
else if (result.status === 'fail') return await interaction.reply({ content: `Failed to retrieve the API version: ${result.data}`, ephemeral: true })
else if (result.status === 'error') return await interaction.reply({ content: `An error occurred while retrieving the API version: ${result.data}`, ephemeral: true })
}
else if (interaction.options.getSubcommand() === 'init') {
await interaction.deferReply({ ephemeral: true })
let app = {
app_id: 'fr.angels.bot_tamiseur',
app_name: 'Bot Tamiseur',
app_version: '2.3.0',
device_name: 'Bot Discord NodeJS'
}
let result = await Freebox.Core.Init(host, version, httpsAgent, app, '')
if (result.status === 'success') {
let appToken = result.data.app_token
let trackId = result.data.track_id
let initCheck = setInterval(async () => {
let result = await Freebox.Core.Init(host, version, httpsAgent, app, trackId)
if (result.status !== 'success') return await interaction.followUp(returnMsg(result) as string)
let status = result.data.status
if (status === 'granted') {
clearInterval(initCheck)
let password_salt = result.data.password_salt
if (!dbData) return
dbData['appToken'] = appToken
dbData['password_salt'] = password_salt
if (!guildProfile) return
guildProfile.set('guildFbx', dbData)
guildProfile.markModified('guildFbx')
await guildProfile.save().catch(console.error)
return await interaction.followUp('Done !')
}
else if (status === 'denied') {
clearInterval(initCheck)
return await interaction.followUp('The user denied the app access to the Freebox.')
}
else if (status === 'pending') return
}, 2000)
} else return await interaction.followUp({ content: returnMsg(result) as string, ephemeral: true })
}
else if (interaction.options.getSubcommandGroup() === 'get') {
let appToken = dbData.appToken as string
if (!appToken) return await interaction.reply({ content: `Freebox appToken is not set for **${interaction.guild?.name}**, please init the app with \`/freebox init\` !` })
console.log(appToken)
let challengeData = await Freebox.Login.Challenge(host, version, httpsAgent)
if (!challengeData) return await interaction.reply({ content: `Failed to retrieve the challenge for **${interaction.guild?.name}** !` })
let challenge = challengeData.data.challenge
console.log(challenge)
let password = crypto.createHmac('sha1', appToken).update(challenge).digest('hex')
console.log(password)
let session = await Freebox.Login.Session(host, version, httpsAgent, 'fr.angels.bot_tamiseur', password)
if (!session) return await interaction.reply({ content: `Failed to retrieve the session for **${interaction.guild?.name}** !` })
let sessionToken = dbData['sessionToken'] = session.data.session_token
guildProfile.set('guildFbx', dbData)
guildProfile.markModified('guildFbx')
await guildProfile.save().catch(console.error)
if (interaction.options.getSubcommand() === 'connection') {
let connection = await Freebox.Get.Connection(host, version, httpsAgent, sessionToken)
if (!connection) return await interaction.reply({ content: `Failed to retrieve the connection details for **${interaction.guild?.name}** !` })
return await interaction.reply({ content: `Connection details for **${interaction.guild?.name}**:\n${inlineCode(JSON.stringify(connection))}` })
}
}
}
}