198 lines
6.5 KiB
JavaScript
198 lines
6.5 KiB
JavaScript
require("dotenv").config();
|
|
const { DISCORD_TOKEN, MATRIX_BASE_URL, MATRIX_SERVER_NAME, MATRIX_ADMIN_TOKEN } = process.env;
|
|
const colors = require("colors");
|
|
const Path = require("path")
|
|
const Discord = require("discord.js");
|
|
const Client = new Discord.Client({
|
|
intents: []
|
|
});
|
|
const {
|
|
REST,
|
|
Routes
|
|
} = require('discord.js');
|
|
|
|
const rest = new REST({
|
|
version: '10'
|
|
}).setToken(DISCORD_TOKEN);
|
|
|
|
var whoami;
|
|
|
|
var matrixHeaders = {
|
|
"Authorization": `Bearer ${MATRIX_ADMIN_TOKEN}`
|
|
};
|
|
|
|
Client.on("ready", async () => {
|
|
console.log(`${colors.cyan("[Info]")} Logged in as ${Client.user.displayName}`);
|
|
|
|
const commands = [
|
|
{
|
|
"name": "matrix-register",
|
|
"description": "Create an account on matrix.litenet.tel",
|
|
"type": 1,
|
|
"options": [
|
|
{
|
|
"name": "username",
|
|
"description": "@<username>:litenet.tel. Be warned, you can't change this once it's set.",
|
|
"type": Discord.ApplicationCommandOptionType.String,
|
|
"required": true
|
|
}
|
|
]
|
|
}
|
|
]
|
|
|
|
//Register commands
|
|
await (async () => {
|
|
try {
|
|
console.log(`${colors.cyan("[Info]")} Registering Commands...`)
|
|
//Global
|
|
await rest.put(Routes.applicationCommands(Client.user.id), { body: commands })
|
|
console.log(`${colors.cyan("[Info]")} Successfully registered commands.`);
|
|
} catch (error) {
|
|
console.error(error);
|
|
}
|
|
})();
|
|
|
|
fetch(`${MATRIX_BASE_URL}/_matrix/client/v3/account/whoami`, {
|
|
headers: matrixHeaders
|
|
}).then(async (response) => {
|
|
whoami = await response.json();
|
|
})
|
|
});
|
|
const usernameFilter = /^[a-z0-9._=\-\/+]+$/;
|
|
|
|
const formatUsername = (input) => {
|
|
if (!usernameFilter.test(input)) throw new Error("Username does not match allowed characters");
|
|
return `@${input}:${MATRIX_SERVER_NAME}`
|
|
}
|
|
|
|
function generatePassword(length) {
|
|
// Define the character set
|
|
const characters = 'abcdefghijklmnopqrstuvwxyz0123456789._=-/+';
|
|
|
|
// Ensure the length is valid
|
|
if (length <= 0) {
|
|
throw new Error('Password length must be greater than 0');
|
|
}
|
|
|
|
let password = '';
|
|
|
|
// Generate the password
|
|
for (let i = 0; i < length; i++) {
|
|
const randomIndex = Math.floor(Math.random() * characters.length);
|
|
password += characters[randomIndex];
|
|
}
|
|
|
|
return password;
|
|
}
|
|
|
|
async function uploadMediaToMatrix(url, filename, mimetype) {
|
|
var data = await fetch(url);
|
|
const response = await fetch(`${MATRIX_BASE_URL}/_matrix/media/v3/upload?filename=${filename}`, {
|
|
method: "POST",
|
|
headers: {
|
|
"Authorization": `Bearer ${MATRIX_ADMIN_TOKEN}`,
|
|
"Content-Type": mimetype
|
|
},
|
|
body: await data.arrayBuffer()
|
|
});
|
|
const json = await response.json();
|
|
return json;
|
|
}
|
|
|
|
Client.on("interactionCreate", async (interaction) => {
|
|
if (!interaction.isCommand()) return;
|
|
switch (interaction.commandName) {
|
|
case "matrix-register":
|
|
const inputUsername = interaction.options.getString("username");
|
|
if (!usernameFilter.test(inputUsername)) return interaction.reply({ephemeral: true, content: "Your username contains invalid characters.\nYour username MUST contain only the characters `a-z`, `0-9`, `.`, `_`, `=`, `-`, `/`, and `+`."});
|
|
|
|
const mxid = formatUsername(inputUsername);
|
|
console.log(`${colors.cyan('[Info]')} ${interaction.user.displayName} (${interaction.user.id}) is trying to make account ${mxid}`)
|
|
// Check if the user exists
|
|
const userCheck = await fetch(`${MATRIX_BASE_URL}/_synapse/admin/v2/users/${mxid}`, {
|
|
headers: {
|
|
"Authorization": `Bearer ${MATRIX_ADMIN_TOKEN}`
|
|
}
|
|
});
|
|
if (userCheck.ok) return interaction.reply({ephemeral: true, content: "That username is taken! Please choose a different one."});
|
|
|
|
// Check if user already has a matrix account
|
|
const dataStoreCheck = await fetch(`${MATRIX_BASE_URL}/_matrix/client/v3/user/${whoami.user_id}/account_data/tel.litenet.discordids.${interaction.user.id}`,{
|
|
headers: matrixHeaders
|
|
})
|
|
if(dataStoreCheck.status !== 404) return interaction.reply({ephemeral: true, content: `You already have an account dingus! It's \`${(await dataStoreCheck.json()).matrix_id}\`\nIf you believe this is an error, please contact an admin!`});
|
|
const newPassword = generatePassword(32);
|
|
|
|
// Emma@Rory&: Upload avatar to matrix:
|
|
const avatar = interaction.user.displayAvatarURL({size: 4096});
|
|
var filename = Path.basename(avatar);
|
|
var mimetype;
|
|
switch (filename.split(".").pop()) {
|
|
case "png":
|
|
mimetype = "image/png";
|
|
break;
|
|
case "jpg":
|
|
case "jpeg":
|
|
mimetype = "image/jpeg";
|
|
break;
|
|
case "gif":
|
|
mimetype = "image/gif";
|
|
break;
|
|
case "webp":
|
|
mimetype = "image/webp";
|
|
break;
|
|
default:
|
|
mimetype = "image/png";
|
|
break;
|
|
}
|
|
|
|
let mxcUri = undefined;
|
|
await uploadMediaToMatrix(avatar, filename, mimetype).then((response) => {
|
|
mxcUri = response.content_uri;
|
|
}).catch((error) => {
|
|
console.error("Error while uploading discord avatar to matrix:", error);
|
|
});
|
|
|
|
|
|
// Create the user
|
|
const createUser = await fetch(`${MATRIX_BASE_URL}/_synapse/admin/v2/users/${mxid}`, {
|
|
method: "PUT",
|
|
headers: {
|
|
"Authorization": `Bearer ${MATRIX_ADMIN_TOKEN}`
|
|
},
|
|
body: JSON.stringify({
|
|
"password": newPassword,
|
|
"displayname": interaction.user.displayName,
|
|
avatar_url: mxcUri
|
|
})
|
|
});
|
|
|
|
if (!userCheck.status.toString() == "201") {
|
|
const createUserError = await createUser.json()
|
|
return interaction.reply({
|
|
ephemeral: true,
|
|
content: `An error has occured!\n${createUserError.errcode}: ${createUserError.error}`
|
|
})
|
|
}
|
|
|
|
// Send the user their credentials
|
|
interaction.user.send({content: `Your matrix account has been created!\nUsername: \`${mxid}\`\nPassword: ||\`${newPassword}\`||\nServer: ${MATRIX_SERVER_NAME}\n\nYou can find a list of Matrix clients [here!](https://matrix.org/ecosystem/clients/)`}).then(() => {
|
|
interaction.reply({ephemeral: true, content: "User created! Check your DMs!"});
|
|
}).catch((error) => {
|
|
interaction.reply({ephemeral: true, content: `Your matrix account has been created!\nUsername: \`${mxid}\`\nPassword: ||\`${newPassword}\`||\nServer: ${MATRIX_SERVER_NAME}\n\nYou can find a list of Matrix clients [here!](https://matrix.org/ecosystem/clients/)\n\nYour DMs were disabled, so we weren't able to send you these credentials!\n***MAKE SURE YOU SAVE THEM***`});
|
|
})
|
|
|
|
// Store the discord id and matrix id
|
|
fetch(`${MATRIX_BASE_URL}/_matrix/client/v3/user/${whoami.user_id}/account_data/tel.litenet.discordids.${interaction.user.id}`,{
|
|
headers: matrixHeaders,
|
|
body: JSON.stringify({
|
|
matrix_id: mxid,
|
|
discord_id: interaction.user.id
|
|
}),
|
|
method: "PUT"
|
|
})
|
|
break;
|
|
}
|
|
})
|
|
|
|
Client.login(DISCORD_TOKEN); |