Revert "converted import syntax to commonJS"

This reverts commit 5ab0d62b
This commit is contained in:
Aster Fialla
2026-02-17 17:25:18 -05:00
parent 321fe7f0a9
commit 35b454bc80
8 changed files with 801 additions and 769 deletions

View File

@@ -1,9 +1,9 @@
const {messageHelper} = require('./helpers/messageHelper.js'); import { Client, Events } from '@fluxerjs/core';
const {enums} = require('enums.js'); import { messageHelper } from "./helpers/messageHelper.js";
const {commands} = require('commands.js'); import {enums} from "./enums.js";
const {webhookHelper} = require('helpers/webhookHelper.js'); import {commands} from "./commands.js";
const {Client, Events } = require('@fluxerjs/core'); import {webhookHelper} from "./helpers/webhookHelper.js";
const {env} = require('dotenv'); import * as env from 'dotenv';
env.config(); env.config();
@@ -26,7 +26,7 @@ client.on(Events.MessageCreate, async (message) => {
// If message doesn't start with the bot prefix, it could still be a message with a proxy tag. If it's not, return. // If message doesn't start with the bot prefix, it could still be a message with a proxy tag. If it's not, return.
if (!content.startsWith(messageHelper.prefix)) { if (!content.startsWith(messageHelper.prefix)) {
await webhookHelper.sendMessageAsMember(client, message).catch((e) => { await webhookHelper.sendMessageAsMember(client, message, content).catch((e) => {
throw e throw e
}); });
return; return;

View File

@@ -1,13 +1,12 @@
const {messageHelper} = require('helpers/messageHelper.js') import {messageHelper} from "./helpers/messageHelper.js";
const {enums} = require('enums.js') import {enums} from "./enums.js";
const {memberHelper} = require('helpers/memberHelper.js') import {memberHelper} from "./helpers/memberHelper.js";
const {importHelper} = require('helpers/importHelper.js'); import {EmbedBuilder} from "@fluxerjs/core";
const {EmbedBuilder} = require('@fluxerjs/core'); import {importHelper} from "./import.js";
const cmds = new Map();
let commands = new Map(); cmds.set('member', {
commands.set('member', {
description: enums.help.SHORT_DESC_MEMBER, description: enums.help.SHORT_DESC_MEMBER,
async execute(message, client, args) { async execute(message, client, args) {
const authorFull = `${message.author.username}#${message.author.discriminator}` const authorFull = `${message.author.username}#${message.author.discriminator}`
@@ -24,10 +23,10 @@ commands.set('member', {
} }
}) })
commands.set('help', { cmds.set('help', {
description: enums.help.SHORT_DESC_HELP, description: enums.help.SHORT_DESC_HELP,
async execute(message) { async execute(message) {
const fields = [...commands.entries()].map(([name, cmd]) => ({ const fields = [...cmds.entries()].map(([name, cmd]) => ({
name: `${messageHelper.prefix}${name}`, name: `${messageHelper.prefix}${name}`,
value: cmd.description, value: cmd.description,
inline: true, inline: true,
@@ -44,7 +43,7 @@ commands.set('help', {
}, },
}) })
commands.set('import', { cmds.set('import', {
description: enums.help.SHORT_DESC_IMPORT, description: enums.help.SHORT_DESC_IMPORT,
async execute(message) { async execute(message) {
if (message.content.includes('--help')) { if (message.content.includes('--help')) {
@@ -71,4 +70,4 @@ commands.set('import', {
} }
}) })
module.exports = commands; export const commands = cmds;

View File

@@ -1,5 +1,5 @@
const {DataTypes, sequelize, Sequelize} = require('sequelize'); import {DataTypes, Sequelize} from 'sequelize';
const {env} = require('dotenv'); import * as env from 'dotenv';
env.config(); env.config();
@@ -10,17 +10,18 @@ if (!password) {
process.exit(1); process.exit(1);
} }
const database = { const db = {};
sequelize: new Sequelize('postgres', 'postgres', password, { const sequelize = new Sequelize('postgres', 'postgres', password, {
host: 'localhost', host: 'localhost',
logging: false, logging: false,
dialect: 'postgres' dialect: 'postgres'
}), });
Sequelize: Sequelize, db.sequelize = sequelize;
db.Sequelize = Sequelize;
members: sequelize.define('Member', { db.members = sequelize.define('Member', {
userid: { userid: {
type: DataTypes.STRING, type: DataTypes.STRING,
allowNull: false, allowNull: false,
@@ -38,9 +39,9 @@ const database = {
proxy: { proxy: {
type: DataTypes.STRING, type: DataTypes.STRING,
} }
}), });
systems: sequelize.define('System', { db.systems = sequelize.define('System', {
userid: { userid: {
type: DataTypes.STRING, type: DataTypes.STRING,
}, },
@@ -53,32 +54,31 @@ const database = {
autoproxy: { autoproxy: {
type: DataTypes.BOOLEAN, type: DataTypes.BOOLEAN,
} }
}), })
/** /**
* Checks Sequelize database connection. * Checks Sequelize database connection.
*/ */
check_connection: async function () { db.check_connection = async function() {
await sequelize.authenticate().then(async () => { await sequelize.authenticate().then(async () => {
console.log('Connection has been established successfully.'); console.log('Connection has been established successfully.');
await this.syncModels(); await syncModels();
}).catch(err => { }).catch(err => {
console.error('Unable to connect to the database:', err); console.error('Unable to connect to the database:', err);
process.exit(1); process.exit(1);
}); });
}, }
/** /**
* Syncs Sequelize models. * Syncs Sequelize models.
*/ */
async syncModels() { async function syncModels() {
await this.sequelize.sync().then(() => { await sequelize.sync().then(() => {
console.log('Models synced successfully.'); console.log('Models synced successfully.');
}).catch((err) => { }).catch((err) => {
console.error('Syncing models did not work', err); console.error('Syncing models did not work', err);
process.exit(1); process.exit(1);
}); });
} }
};
module.exports = database; export const database = db;

View File

@@ -1,5 +1,6 @@
const enums = { const helperEnums = {};
err: {
helperEnums.err = {
NO_MEMBER: "No such member was found.", NO_MEMBER: "No such member was found.",
NO_NAME_PROVIDED: "No member name was provided for", NO_NAME_PROVIDED: "No member name was provided for",
NO_VALUE: "has not been set for this member. Please provide a value.", NO_VALUE: "has not been set for this member. Please provide a value.",
@@ -19,9 +20,9 @@ const enums = {
NOT_JSON_FILE: "Please attach a valid JSON file.", NOT_JSON_FILE: "Please attach a valid JSON file.",
NO_MEMBERS_IMPORTED: 'No members were imported.', NO_MEMBERS_IMPORTED: 'No members were imported.',
IMPORT_ERROR: "Please see attached file for logs on the member import process.", IMPORT_ERROR: "Please see attached file for logs on the member import process.",
}, }
help: { helperEnums.help = {
SHORT_DESC_HELP: "Lists available commands.", SHORT_DESC_HELP: "Lists available commands.",
SHORT_DESC_MEMBER: "Accesses subcommands related to proxy members.", SHORT_DESC_MEMBER: "Accesses subcommands related to proxy members.",
SHORT_DESC_IMPORT: "Imports from PluralKit.", SHORT_DESC_IMPORT: "Imports from PluralKit.",
@@ -36,11 +37,10 @@ const enums = {
PROXY: "Updates the proxy tag for a specific member based on their name. The proxy must be formatted with the tags surrounding the word 'text', for example: `pf;member jane proxy Jane:text` or `pf;member amal proxy [text]` This is so the bot can detect what the proxy tags are. Only one proxy can be set per member currently.", PROXY: "Updates the proxy tag for a specific member based on their name. The proxy must be formatted with the tags surrounding the word 'text', for example: `pf;member jane proxy Jane:text` or `pf;member amal proxy [text]` This is so the bot can detect what the proxy tags are. Only one proxy can be set per member currently.",
PROPIC: "Updates the profile picture for the member. Must be in JPG, PNG, or WEBP format and less than 10MB. The two options are:\n1. Pass in a direct remote image URL, for example: `pf;member jane propic <https://cdn.pixabay.com/photo/2020/05/02/02/54/animal-5119676_1280.jpg>`. You can upload images on sites like <https://imgbb.com/>.\n2. Upload an attachment directly.\n\n**NOTE:** Fluxer does not save your attachments forever, so option #1 is recommended.", PROPIC: "Updates the profile picture for the member. Must be in JPG, PNG, or WEBP format and less than 10MB. The two options are:\n1. Pass in a direct remote image URL, for example: `pf;member jane propic <https://cdn.pixabay.com/photo/2020/05/02/02/54/animal-5119676_1280.jpg>`. You can upload images on sites like <https://imgbb.com/>.\n2. Upload an attachment directly.\n\n**NOTE:** Fluxer does not save your attachments forever, so option #1 is recommended.",
IMPORT: "Imports from PluralKit using the JSON file provided by their export command. Importing from other proxy bots is TBD. `pf;import` and attach your JSON file to the message. This will only save the fields that are present in the bot currently (the stuff above), not anything else like birthdays or system handles (yet?)." IMPORT: "Imports from PluralKit using the JSON file provided by their export command. Importing from other proxy bots is TBD. `pf;import` and attach your JSON file to the message. This will only save the fields that are present in the bot currently (the stuff above), not anything else like birthdays or system handles (yet?)."
}, }
misc: { helperEnums.misc = {
ATTACHMENT_SENT_BY: "Attachment sent by:" ATTACHMENT_SENT_BY: "Attachment sent by:"
} }
};
module.exports = enums; export const enums = helperEnums;

View File

@@ -1,13 +1,12 @@
const { database } = require('../db.js') import {database} from '../db.js';
const { enums} = require('../enums.js'); import {enums} from "../enums.js";
const {EmptyResultError, Op} = require('sequelize'); import {EmptyResultError, Op} from "sequelize";
const {EmbedBuilder} = require('@fluxerjs/core'); import {EmbedBuilder} from "@fluxerjs/core";
const memberHelper = {
const mh = {};
// Has an empty "command" to parse the help message properly // Has an empty "command" to parse the help message properly
commandList: ['--help', 'new', 'remove', 'name', 'list', 'displayName', 'proxy', 'propic', ''], const commandList = ['--help', 'new', 'remove', 'name', 'list', 'displayName', 'proxy', 'propic', ''];
/** /**
* Parses through the subcommands that come after "pf;member" and calls functions accordingly. * Parses through the subcommands that come after "pf;member" and calls functions accordingly.
@@ -21,19 +20,23 @@ const memberHelper = {
* @returns {Promise<string> | Promise <EmbedBuilder>} A message, or an informational embed. * @returns {Promise<string> | Promise <EmbedBuilder>} A message, or an informational embed.
* @throws {Error} * @throws {Error}
*/ */
async parseMemberCommand (authorId, authorFull, args, attachmentUrl = null, attachmentExpiration = null){ mh.parseMemberCommand = async function (authorId, authorFull, args, attachmentUrl = null, attachmentExpiration = null) {
let member; let member;
// checks whether command is in list, otherwise assumes it's a name // checks whether command is in list, otherwise assumes it's a name
if(!this.commandList.includes(args[0])) { if (!commandList.includes(args[0])) {
member = await this.getMemberInfo(authorId, args[0]); member = await mh.getMemberInfo(authorId, args[0]);
} }
switch (args[0]) { switch (args[0]) {
case '--help': case '--help':
return enums.help.MEMBER; return enums.help.MEMBER;
case 'new': case 'new':
return await this.addNewMember(authorId, args).catch((e) =>{throw e}); return await mh.addNewMember(authorId, args).catch((e) => {
throw e
});
case 'remove': case 'remove':
return await this.removeMember(authorId, args).catch((e) =>{throw e}); return await mh.removeMember(authorId, args).catch((e) => {
throw e
});
case 'name': case 'name':
return enums.help.NAME; return enums.help.NAME;
case 'displayname': case 'displayname':
@@ -46,24 +49,36 @@ const memberHelper = {
if (args[1] && args[1] === "--help") { if (args[1] && args[1] === "--help") {
return enums.help.LIST; return enums.help.LIST;
} }
return await this.getAllMembersInfo(authorId, authorFull).catch((e) =>{throw e}); return await mh.getAllMembersInfo(authorId, authorFull).catch((e) => {
throw e
});
case '': case '':
return enums.help.MEMBER; return enums.help.MEMBER;
} }
switch (args[1]) { switch (args[1]) {
case 'name': case 'name':
return await this.updateName(authorId, args).catch((e) =>{throw e}); return await mh.updateName(authorId, args).catch((e) => {
throw e
});
case 'displayname': case 'displayname':
return await this.updateDisplayName(authorId, args).catch((e) =>{throw e}); return await mh.updateDisplayName(authorId, args).catch((e) => {
throw e
});
case 'proxy': case 'proxy':
if (!args[2]) return await this.getProxyByMember(authorId, args[0]).catch((e) => {throw e}); if (!args[2]) return await mh.getProxyByMember(authorId, args[0]).catch((e) => {
return await this.updateProxy(authorId, args).catch((e) =>{throw e}); throw e
});
return await mh.updateProxy(authorId, args).catch((e) => {
throw e
});
case 'propic': case 'propic':
return await this.updatePropic(authorId, args, attachmentUrl, attachmentExpiration).catch((e) =>{throw e}); return await mh.updatePropic(authorId, args, attachmentUrl, attachmentExpiration).catch((e) => {
throw e
});
default: default:
return member; return member;
} }
}, }
/** /**
* Adds a member. * Adds a member.
@@ -74,21 +89,21 @@ const memberHelper = {
* @returns {Promise<string>} A successful addition. * @returns {Promise<string>} A successful addition.
* @throws {Error} When the member exists, or creating a member doesn't work. * @throws {Error} When the member exists, or creating a member doesn't work.
*/ */
async addNewMember (authorId, args) { mh.addNewMember = async function (authorId, args) {
if (args[1] && args[1] === "--help" || !args[1]) { if (args[1] && args[1] === "--help" || !args[1]) {
return enums.help.NEW; return enums.help.NEW;
} }
const memberName = args[1]; const memberName = args[1];
const displayName = args[2]; const displayName = args[2];
return await this.addFullMember(authorId, memberName, displayName).then((member) => { return await mh.addFullMember(authorId, memberName, displayName).then((member) => {
let success = `Member was successfully added.\nName: ${member.dataValues.name}` let success = `Member was successfully added.\nName: ${member.dataValues.name}`
success += displayName ? `\nDisplay name: ${member.dataValues.displayname}` : ""; success += displayName ? `\nDisplay name: ${member.dataValues.displayname}` : "";
return success; return success;
}).catch(e => { }).catch(e => {
throw e; throw e;
}) })
}, }
/** /**
* Updates the name for a member. * Updates the name for a member.
@@ -99,7 +114,7 @@ const memberHelper = {
* @returns {Promise<string>} A successful update. * @returns {Promise<string>} A successful update.
* @throws {RangeError} When the name doesn't exist. * @throws {RangeError} When the name doesn't exist.
*/ */
async updateName (authorId, args) { mh.updateName = async function (authorId, args) {
if (args[1] && args[1] === "--help" || !args[1]) { if (args[1] && args[1] === "--help" || !args[1]) {
return enums.help.DISPLAY_NAME; return enums.help.DISPLAY_NAME;
} }
@@ -109,8 +124,10 @@ const memberHelper = {
if (!name || trimmedName === null) { if (!name || trimmedName === null) {
throw new RangeError(`Display name ${enums.err.NO_VALUE}`); throw new RangeError(`Display name ${enums.err.NO_VALUE}`);
} }
return await this.updateMemberField(authorId, args).catch((e) =>{throw e}); return await mh.updateMemberField(authorId, args).catch((e) => {
}, throw e
});
}
/** /**
* Updates the display name for a member. * Updates the display name for a member.
@@ -121,7 +138,7 @@ const memberHelper = {
* @returns {Promise<string>} A successful update. * @returns {Promise<string>} A successful update.
* @throws {RangeError} When the display name is too long or doesn't exist. * @throws {RangeError} When the display name is too long or doesn't exist.
*/ */
async updateDisplayName (authorId, args) { mh.updateDisplayName = async function (authorId, args) {
if (args[1] && args[1] === "--help" || !args[1]) { if (args[1] && args[1] === "--help" || !args[1]) {
return enums.help.DISPLAY_NAME; return enums.help.DISPLAY_NAME;
} }
@@ -131,20 +148,20 @@ const memberHelper = {
const trimmedName = displayName ? displayName.trim() : null; const trimmedName = displayName ? displayName.trim() : null;
if (!displayName || trimmedName === null) { if (!displayName || trimmedName === null) {
return await this.getMemberByName(authorId, memberName).then((member) => { return await mh.getMemberByName(authorId, memberName).then((member) => {
if (member && member.displayname) { if (member && member.displayname) {
return `Display name for ${memberName} is: \"${member.displayname}\".`; return `Display name for ${memberName} is: \"${member.displayname}\".`;
} } else if (member) {
else if (member) {
throw new RangeError(`Display name ${enums.err.NO_VALUE}`); throw new RangeError(`Display name ${enums.err.NO_VALUE}`);
} }
}); });
} } else if (displayName.length > 32) {
else if (displayName.length > 32) {
throw new RangeError(enums.err.DISPLAY_NAME_TOO_LONG); throw new RangeError(enums.err.DISPLAY_NAME_TOO_LONG);
} }
return await this.updateMemberField(authorId, args).catch((e) =>{throw e}); return await mh.updateMemberField(authorId, args).catch((e) => {
}, throw e
});
}
/** /**
* Updates the proxy for a member, first checking that no other members attached to the author have the tag. * Updates the proxy for a member, first checking that no other members attached to the author have the tag.
@@ -155,17 +172,21 @@ const memberHelper = {
* @returns {Promise<string> } A successful update. * @returns {Promise<string> } A successful update.
* @throws {RangeError | Error} When an empty proxy was provided, or no proxy exists. * @throws {RangeError | Error} When an empty proxy was provided, or no proxy exists.
*/ */
async updateProxy (authorId, args) { mh.updateProxy = async function (authorId, args) {
if (args[2] && args[2] === "--help") { if (args[2] && args[2] === "--help") {
return enums.help.PROXY; return enums.help.PROXY;
} }
const proxyExists = await this.checkIfProxyExists(authorId, args[2]).then((proxyExists) => { const proxyExists = await mh.checkIfProxyExists(authorId, args[2]).then((proxyExists) => {
return proxyExists; return proxyExists;
}).catch((e) =>{throw e}); }).catch((e) => {
throw e
});
if (!proxyExists) { if (!proxyExists) {
return await this.updateMemberField(authorId, args).catch((e) =>{throw e}); return await mh.updateMemberField(authorId, args).catch((e) => {
throw e
});
}
} }
},
/** /**
* Updates the profile pic for a member, based on either the attachment or the args provided. * Updates the profile pic for a member, based on either the attachment or the args provided.
@@ -178,7 +199,7 @@ const memberHelper = {
* @returns {Promise<string>} A successful update. * @returns {Promise<string>} A successful update.
* @throws {Error} When loading the profile picture from a URL doesn't work. * @throws {Error} When loading the profile picture from a URL doesn't work.
*/ */
async updatePropic (authorId, args, attachmentUrl, attachmentExpiry= null) { mh.updatePropic = async function (authorId, args, attachmentUrl, attachmentExpiry = null) {
if (args[1] && args[1] === "--help") { if (args[1] && args[1] === "--help") {
return enums.help.PROPIC; return enums.help.PROPIC;
} }
@@ -193,11 +214,15 @@ const memberHelper = {
if (updatedArgs[2]) { if (updatedArgs[2]) {
img = updatedArgs[2]; img = updatedArgs[2];
} }
const isValidImage = await this.checkImageFormatValidity(img).catch((e) =>{throw e}); const isValidImage = await mh.checkImageFormatValidity(img).catch((e) => {
throw e
});
if (isValidImage) { if (isValidImage) {
return await this.updateMemberField(authorId, updatedArgs).catch((e) =>{throw e}); return await mh.updateMemberField(authorId, updatedArgs).catch((e) => {
throw e
});
}
} }
},
/** /**
* Checks if an uploaded picture is in the right format. * Checks if an uploaded picture is in the right format.
@@ -207,7 +232,7 @@ const memberHelper = {
* @returns {Promise<boolean>} - If the image is a valid format. * @returns {Promise<boolean>} - If the image is a valid format.
* @throws {Error} When loading the profile picture from a URL doesn't work, or it fails requirements. * @throws {Error} When loading the profile picture from a URL doesn't work, or it fails requirements.
*/ */
async checkImageFormatValidity (imageUrl) { mh.checkImageFormatValidity = async function (imageUrl) {
const acceptableImages = ['image/png', 'image/jpg', 'image/jpeg', 'image/webp']; const acceptableImages = ['image/png', 'image/jpg', 'image/jpeg', 'image/webp'];
return await fetch(imageUrl).then(r => r.blob()).then(blobFile => { return await fetch(imageUrl).then(r => r.blob()).then(blobFile => {
if (blobFile.size > 1000000 || !acceptableImages.includes(blobFile.type)) throw new Error(enums.err.PROPIC_FAILS_REQUIREMENTS); if (blobFile.size > 1000000 || !acceptableImages.includes(blobFile.type)) throw new Error(enums.err.PROPIC_FAILS_REQUIREMENTS);
@@ -215,7 +240,7 @@ const memberHelper = {
}).catch((error) => { }).catch((error) => {
throw new Error(`${enums.err.PROPIC_CANNOT_LOAD}: ${error.message}`); throw new Error(`${enums.err.PROPIC_CANNOT_LOAD}: ${error.message}`);
}); });
}, }
/** /**
* Removes a member. * Removes a member.
@@ -226,19 +251,24 @@ const memberHelper = {
* @returns {Promise<string>} A successful removal. * @returns {Promise<string>} A successful removal.
* @throws {EmptyResultError} When there is no member to remove. * @throws {EmptyResultError} When there is no member to remove.
*/ */
async removeMember (authorId, args) { mh.removeMember = async function (authorId, args) {
if (args[1] && args[1] === "--help" || !args[1]) { if (args[1] && args[1] === "--help" || !args[1]) {
return enums.help.REMOVE; return enums.help.REMOVE;
} }
const memberName = args[1]; const memberName = args[1];
return await database.members.destroy({ where: { name: {[Op.iLike]: memberName}, userid: authorId } }).then((result) => { return await database.members.destroy({
where: {
name: {[Op.iLike]: memberName},
userid: authorId
}
}).then((result) => {
if (result) { if (result) {
return `Member "${memberName}" has been deleted.`; return `Member "${memberName}" has been deleted.`;
} }
throw new EmptyResultError(`${enums.err.NO_MEMBER}`); throw new EmptyResultError(`${enums.err.NO_MEMBER}`);
}) })
}, }
/*======Non-Subcommands======*/ /*======Non-Subcommands======*/
@@ -251,12 +281,12 @@ const memberHelper = {
* @param {string | null} displayName - The display name of the member. * @param {string | null} displayName - The display name of the member.
* @param {string | null} proxy - The proxy tag of the member. * @param {string | null} proxy - The proxy tag of the member.
* @param {string | null} propic - The profile picture URL of the member. * @param {string | null} propic - The profile picture URL of the member.
* @param {boolean} isImport - Whether calling from the import or not. * @param {boolean} isImport - Whether calling from the import function or not.
* @returns {Promise<model>} A successful addition. * @returns {Promise<model>} A successful addition.
* @throws {Error | RangeError} When the member already exists, there are validation errors, or adding a member doesn't work. * @throws {Error | RangeError} When the member already exists, there are validation errors, or adding a member doesn't work.
*/ */
async addFullMember (authorId, memberName, displayName = null, proxy = null, propic= null, isImport = false) { mh.addFullMember = async function (authorId, memberName, displayName = null, proxy = null, propic = null, isImport = false) {
await this.getMemberByName(authorId, memberName).then((member) => { await mh.getMemberByName(authorId, memberName).then((member) => {
if (member) { if (member) {
throw new Error(`Can't add ${memberName}. ${enums.err.MEMBER_EXISTS}`); throw new Error(`Can't add ${memberName}. ${enums.err.MEMBER_EXISTS}`);
} }
@@ -268,11 +298,13 @@ const memberHelper = {
} }
} }
if (proxy) { if (proxy) {
await this.checkIfProxyExists(authorId, proxy).catch((e) =>{throw e}); await mh.checkIfProxyExists(authorId, proxy).catch((e) => {
throw e
});
} }
let validPropic; let validPropic;
if (propic) { if (propic) {
validPropic = await this.checkImageFormatValidity(propic).then((valid) => { validPropic = await mh.checkImageFormatValidity(propic).then((valid) => {
return valid; return valid;
}).catch((e) => { }).catch((e) => {
if (!isImport) { if (!isImport) {
@@ -283,16 +315,12 @@ const memberHelper = {
} }
const member = await database.members.create({ const member = await database.members.create({
name: memberName, name: memberName, userid: authorId, displayname: displayName, proxy: proxy, propic: validPropic ? propic : null,
userid: authorId,
displayname: displayName,
proxy: proxy,
propic: validPropic ? propic : null,
}); });
if (!member) { if (!member) {
new Error(`${enums.err.ADD_ERROR}`); new Error(`${enums.err.ADD_ERROR}`);
} }
}, }
/** /**
* Updates one fields for a member in the database. * Updates one fields for a member in the database.
@@ -303,7 +331,7 @@ const memberHelper = {
* @returns {Promise<string>} A successful update. * @returns {Promise<string>} A successful update.
* @throws {EmptyResultError | Error} When the member is not found, or catchall error. * @throws {EmptyResultError | Error} When the member is not found, or catchall error.
*/ */
async updateMemberField (authorId, args) { mh.updateMemberField = async function (authorId, args) {
const memberName = args[0]; const memberName = args[0];
const columnName = args[1]; const columnName = args[1];
const value = args[2]; const value = args[2];
@@ -311,19 +339,23 @@ const memberHelper = {
// indicates that an attachment was uploaded on Fluxer directly // indicates that an attachment was uploaded on Fluxer directly
if (columnName === "propic" && args[3]) { if (columnName === "propic" && args[3]) {
fluxerPropicWarning = this.setExpirationWarning(args[3]); fluxerPropicWarning = mh.setExpirationWarning(args[3]);
} }
return await database.members.update({[columnName]: value}, { where: { name: {[Op.iLike]: memberName}, userid: authorId } }).then(() => { return await database.members.update({[columnName]: value}, {
where: {
name: {[Op.iLike]: memberName},
userid: authorId
}
}).then(() => {
return `Updated ${columnName} for ${memberName} to ${value}${fluxerPropicWarning ?? ''}.`; return `Updated ${columnName} for ${memberName} to ${value}${fluxerPropicWarning ?? ''}.`;
}).catch(e => { }).catch(e => {
if (e === EmptyResultError) { if (e === EmptyResultError) {
throw new EmptyResultError(`Can't update ${memberName}. ${enums.err.NO_MEMBER}: ${e.message}`); throw new EmptyResultError(`Can't update ${memberName}. ${enums.err.NO_MEMBER}: ${e.message}`);
} } else {
else {
throw new Error(`Can't update ${memberName}. ${e.message}`); throw new Error(`Can't update ${memberName}. ${e.message}`);
} }
}); });
}, }
/** /**
* Sets the warning for an expiration date. * Sets the warning for an expiration date.
@@ -331,13 +363,13 @@ const memberHelper = {
* @param {string} expirationString - An expiration date string. * @param {string} expirationString - An expiration date string.
* @returns {string} A description of the expiration, interpolating the expiration string. * @returns {string} A description of the expiration, interpolating the expiration string.
*/ */
setExpirationWarning(expirationString) { mh.setExpirationWarning = function (expirationString) {
let expirationDate = new Date(expirationString); let expirationDate = new Date(expirationString);
if (!isNaN(expirationDate.valueOf())) { if (!isNaN(expirationDate.valueOf())) {
expirationDate = expirationDate.toDateString(); expirationDate = expirationDate.toDateString();
return `\n**NOTE:** Because this profile picture was uploaded via Fluxer, it will currently expire on *${expirationDate}*. To avoid this, upload the picture to another website like <https://imgbb.com/> and link to it directly` return `\n**NOTE:** Because this profile picture was uploaded via Fluxer, it will currently expire on *${expirationDate}*. To avoid this, upload the picture to another website like <https://imgbb.com/> and link to it directly`
} }
}, }
/** /**
* Gets the details for a member. * Gets the details for a member.
@@ -347,20 +379,21 @@ const memberHelper = {
* @param {string} memberName - The message arguments * @param {string} memberName - The message arguments
* @returns {Promise<EmbedBuilder>} The member's info. * @returns {Promise<EmbedBuilder>} The member's info.
*/ */
async getMemberInfo (authorId, memberName) { mh.getMemberInfo = async function (authorId, memberName) {
return await this.getMemberByName(authorId, memberName).then((member) => { return await mh.getMemberByName(authorId, memberName).then((member) => {
if (member) { if (member) {
return new EmbedBuilder() return new EmbedBuilder()
.setTitle(member.name) .setTitle(member.name)
.setDescription(`Details for ${member.name}`) .setDescription(`Details for ${member.name}`)
.addFields( .addFields({
{name: 'Display name: ', value: member.displayname ?? 'unset', inline: true}, name: 'Display name: ',
{name: 'Proxy tag: ', value: member.proxy ?? 'unset', inline: true}, value: member.displayname ?? 'unset',
) inline: true
}, {name: 'Proxy tag: ', value: member.proxy ?? 'unset', inline: true},)
.setImage(member.propic); .setImage(member.propic);
} }
}); });
}, }
/** /**
* Gets all members for an author. * Gets all members for an author.
@@ -371,18 +404,16 @@ const memberHelper = {
* @returns {Promise<EmbedBuilder>} The info for all members. * @returns {Promise<EmbedBuilder>} The info for all members.
* @throws {Error} When there are no members for an author. * @throws {Error} When there are no members for an author.
*/ */
async getAllMembersInfo (authorId, authorName) { mh.getAllMembersInfo = async function (authorId, authorName) {
const members = await this.getMembersByAuthor(authorId); const members = await mh.getMembersByAuthor(authorId);
if (members == null) throw Error(enums.err.USER_NO_MEMBERS); if (members == null) throw Error(enums.err.USER_NO_MEMBERS);
const fields = [...members.entries()].map(([name, member]) => ({ const fields = [...members.entries()].map(([name, member]) => ({
name: member.name, name: member.name, value: `(Proxy: \`${member.proxy ?? "unset"}\`)`, inline: true,
value: `(Proxy: \`${member.proxy ?? "unset"}\`)`,
inline: true,
})); }));
return new EmbedBuilder() return new EmbedBuilder()
.setTitle(`${fields > 25 ? "First 25 m" : "M"}embers for ${authorName}`) .setTitle(`${fields > 25 ? "First 25 m" : "M"}embers for ${authorName}`)
.addFields(...fields); .addFields(...fields);
}, }
/** /**
* Gets a member based on the author and proxy tag. * Gets a member based on the author and proxy tag.
@@ -393,9 +424,9 @@ const memberHelper = {
* @returns {Promise<model>} The member object. * @returns {Promise<model>} The member object.
* @throws { EmptyResultError } When the member is not found. * @throws { EmptyResultError } When the member is not found.
*/ */
async getMemberByName (authorId, memberName) { mh.getMemberByName = async function (authorId, memberName) {
return await database.members.findOne({where: {userid: authorId, name: {[Op.iLike]: memberName}}}); return await database.members.findOne({where: {userid: authorId, name: {[Op.iLike]: memberName}}});
}, }
/** /**
* Gets a member based on the author and proxy tag. * Gets a member based on the author and proxy tag.
@@ -403,17 +434,29 @@ const memberHelper = {
* @async * @async
* @param {string} authorId - The author of the message. * @param {string} authorId - The author of the message.
* @param {string} memberName - The member's name. * @param {string} memberName - The member's name.
* @returns {Promise<model>} The member object. * @returns {Promise<string>} The member object.
* @throws { EmptyResultError } When the member is not found. * @throws { EmptyResultError } When the member is not found.
*/ */
async getProxyByMember (authorId, memberName) { mh.getProxyByMember = async function (authorId, memberName) {
return await this.getMemberByName(authorId, memberName).then((member) => { return await mh.getMemberByName(authorId, memberName).then((member) => {
if (member) { if (member) {
return member.dataValues.proxy; return member.dataValues.proxy;
} }
throw new EmptyResultError(enums.err.NO_MEMBER); throw new EmptyResultError(enums.err.NO_MEMBER);
}) })
}, }
/**
* Gets a member based on the author and proxy tag.
*
* @async
* @param {string} authorId - The author of the message
* @param {string} proxy - The proxy tag
* @returns {Promise<model>} The member object.
*/
mh.getMemberByProxy = async function (authorId, proxy) {
return await db.members.findOne({where: {userid: authorId, proxy: proxy}});
}
/** /**
* Gets all members belonging to the author. * Gets all members belonging to the author.
@@ -422,9 +465,9 @@ const memberHelper = {
* @param {string} authorId - The author of the message * @param {string} authorId - The author of the message
* @returns {Promise<model[] | null>} The member object array. * @returns {Promise<model[] | null>} The member object array.
*/ */
async getMembersByAuthor (authorId) { mh.getMembersByAuthor = async function (authorId) {
return await database.members.findAll({where: {userid: authorId}}); return await database.members.findAll({where: {userid: authorId}});
}, }
/** /**
@@ -435,22 +478,23 @@ const memberHelper = {
* @returns {Promise<boolean> } Whether the proxy exists. * @returns {Promise<boolean> } Whether the proxy exists.
* @throws {Error} When an empty proxy was provided, or no proxy exists. * @throws {Error} When an empty proxy was provided, or no proxy exists.
*/ */
async checkIfProxyExists (authorId, proxy) { mh.checkIfProxyExists = async function (authorId, proxy) {
if (proxy) { if (proxy) {
const splitProxy = proxy.trim().split("text"); const splitProxy = proxy.trim().split("text");
if (splitProxy.length < 2) throw new Error(enums.err.NO_TEXT_FOR_PROXY); if (splitProxy.length < 2) throw new Error(enums.err.NO_TEXT_FOR_PROXY);
if (!splitProxy[0] && !splitProxy[1]) throw new Error(enums.err.NO_PROXY_WRAPPER); if (!splitProxy[0] && !splitProxy[1]) throw new Error(enums.err.NO_PROXY_WRAPPER);
await this.getMembersByAuthor(authorId).then((memberList) => { await mh.getMembersByAuthor(authorId).then((memberList) => {
const proxyExists = memberList.some(member => member.proxy === proxy); const proxyExists = memberList.some(member => member.proxy === proxy);
if (proxyExists) { if (proxyExists) {
throw new Error(enums.err.PROXY_EXISTS); throw new Error(enums.err.PROXY_EXISTS);
} }
}).catch(e =>{throw e}); }).catch(e => {
throw e
});
} }
} }
}
module.exports = memberHelper; export const memberHelper = mh;

View File

@@ -1,15 +1,15 @@
const {memberHelper} = require('memberHelper.js'); import {memberHelper} from "./memberHelper.js";
const {fs} = require('fs') import {enums} from "../enums.js";
const {tmp, setGracefulCleanup } = require('tmp') import tmp, {setGracefulCleanup} from "tmp";
const {enums} = require('../enums.js') import fs from 'fs';
const {Message} = require('@fluxerjs/core'); import {Message} from "@fluxerjs/core";
const msgh = {};
msgh.prefix = "pf;"
setGracefulCleanup(); setGracefulCleanup();
const messageHelper = {
prefix: "pf;",
/** /**
* Parses and slices up message arguments, retaining quoted strings. * Parses and slices up message arguments, retaining quoted strings.
* *
@@ -17,8 +17,8 @@ const messageHelper = {
* @param {string} commandName - The command name. * @param {string} commandName - The command name.
* @returns {string[]} An array of arguments. * @returns {string[]} An array of arguments.
*/ */
parseCommandArgs(content, commandName) { msgh.parseCommandArgs = function(content, commandName) {
const message = content.slice(this.prefix.length + commandName.length).trim(); const message = content.slice(msgh.prefix.length + commandName.length).trim();
return message.match(/\\?.|^$/g).reduce((accumulator, chara) => { return message.match(/\\?.|^$/g).reduce((accumulator, chara) => {
if (chara === '"') { if (chara === '"') {
@@ -33,7 +33,7 @@ const messageHelper = {
} }
return accumulator; return accumulator;
}, {array: ['']}).array // initial array with empty string for the reducer }, {array: ['']}).array // initial array with empty string for the reducer
}, }
/** /**
* Parses messages to see if any part of the text matches the tags of any member belonging to an author. * Parses messages to see if any part of the text matches the tags of any member belonging to an author.
@@ -44,7 +44,7 @@ const messageHelper = {
* @returns {Object} The proxy message object. * @returns {Object} The proxy message object.
* @throws {Error} If a proxy message is sent with no message within it. * @throws {Error} If a proxy message is sent with no message within it.
*/ */
async parseProxyTags(authorId, content, attachmentUrl = null) { msgh.parseProxyTags = async function (authorId, content, attachmentUrl= null){
const members = await memberHelper.getMembersByAuthor(authorId); const members = await memberHelper.getMembersByAuthor(authorId);
// If an author has no members, no sense in searching for proxy // If an author has no members, no sense in searching for proxy
if (members.length === 0) { if (members.length === 0) {
@@ -69,7 +69,7 @@ const messageHelper = {
} }
}) })
return proxyMessage; return proxyMessage;
}, }
/** /**
* Sends a message as an attachment if it's too long.NOT CURRENTLY IN USE * Sends a message as an attachment if it's too long.NOT CURRENTLY IN USE
@@ -80,7 +80,7 @@ const messageHelper = {
* @throws {Error} If a proxy message is sent with no message within it. * @throws {Error} If a proxy message is sent with no message within it.
* *
*/ */
async sendMessageAsAttachment(text, message) { msgh.sendMessageAsAttachment = async function(text, message) {
if (text.length > 2000) { if (text.length > 2000) {
tmp.file(async (err, path, fd, cleanupCallback) => { tmp.file(async (err, path, fd, cleanupCallback) => {
fs.writeFile(path, text, (err) => { fs.writeFile(path, text, (err) => {
@@ -91,6 +91,5 @@ const messageHelper = {
}); });
} }
} }
};
module.exports = messageHelper; export const messageHelper = msgh;

View File

@@ -1,21 +1,20 @@
const {messageHelper} = require('messageHelper.js'); import {messageHelper} from "./messageHelper.js";
const {enums} = require('../enums.js'); import {Webhook, Channel, Message} from '@fluxerjs/core';
const {Client, Message, Webhook, Channel} = require('@fluxerjs/core'); import {enums} from "../enums.js";
const wh = {};
const name = 'PluralFlux Proxy Webhook'; const name = 'PluralFlux Proxy Webhook';
const webhookHelper = {
/** /**
* Replaces a proxied message with a webhook using the member information. * Replaces a proxied message with a webhook using the member information.
* @param {Client} client - The fluxer.js client. * @param {Client} client - The fluxer.js client.
* @param {Message} message - The full message object. * @param {Message} message - The full message object.
* @throws {Error} When the proxy message is not in a server. * @throws {Error} When the proxy message is not in a server.
*/ */
async sendMessageAsMember(client, message) { wh.sendMessageAsMember = async function(client, message) {
const attachmentUrl = message.attachments.size > 0 ? message.attachments.first().url : null; const attachmentUrl = message.attachments.size > 0 ? message.attachments.first().url : null;
const proxyMatch = await messageHelper.parseProxyTags(message.author.id, message.content, attachmentUrl).catch(e => { const proxyMatch = await messageHelper.parseProxyTags(message.author.id, message.content, attachmentUrl).catch(e =>{throw e});
throw e
});
// If the message doesn't match a proxy, just return. // If the message doesn't match a proxy, just return.
if (!proxyMatch.member) { if (!proxyMatch.member) {
return; return;
@@ -28,10 +27,8 @@ const webhookHelper = {
if (proxyMatch.message === enums.misc.ATTACHMENT_SENT_BY) { if (proxyMatch.message === enums.misc.ATTACHMENT_SENT_BY) {
return await message.reply(`${enums.misc.ATTACHMENT_SENT_BY} ${proxyMatch.member.displayname}`) return await message.reply(`${enums.misc.ATTACHMENT_SENT_BY} ${proxyMatch.member.displayname}`)
} }
await this.replaceMessage(client, message, proxyMatch.message, proxyMatch.member).catch(e => { await replaceMessage(client, message, proxyMatch.message, proxyMatch.member).catch(e =>{throw e});
throw e }
});
},
/** /**
* Replaces a proxied message with a webhook using the member information. * Replaces a proxied message with a webhook using the member information.
@@ -41,19 +38,18 @@ const webhookHelper = {
* @param {model} member - A member object from the database. * @param {model} member - A member object from the database.
* @throws {Error} When there's no message to send. * @throws {Error} When there's no message to send.
*/ */
async replaceMessage(client, message, text, member) { async function replaceMessage(client, message, text, member) {
if (text.length > 0 || message.attachments.size > 0) { if (text.length > 0 || message.attachments.size > 0) {
const channel = client.channels.get(message.channelId); const channel = client.channels.get(message.channelId);
const webhook = await this.getOrCreateWebhook(client, channel).catch((e) => { const webhook = await getOrCreateWebhook(client, channel).catch((e) =>{throw e});
throw e
});
const username = member.displayname ?? member.name; const username = member.displayname ?? member.name;
await webhook.send({content: text, username: username, avatar_url: member.propic}); await webhook.send({content: text, username: username, avatar_url: member.propic});
await message.delete(); await message.delete();
} else { }
else {
throw new Error(enums.err.NO_MESSAGE_SENT_WITH_PROXY); throw new Error(enums.err.NO_MESSAGE_SENT_WITH_PROXY);
} }
}, }
/** /**
* Gets or creates a webhook. * Gets or creates a webhook.
@@ -63,17 +59,15 @@ const webhookHelper = {
* @returns {Webhook} A webhook object. * @returns {Webhook} A webhook object.
* @throws {Error} When no webhooks are allowed in the channel. * @throws {Error} When no webhooks are allowed in the channel.
*/ */
async getOrCreateWebhook(client, channel) { async function getOrCreateWebhook(client, channel) {
// If channel doesn't allow webhooks // If channel doesn't allow webhooks
if (!channel?.createWebhook) throw new Error(enums.err.NO_WEBHOOKS_ALLOWED); if (!channel?.createWebhook) throw new Error(enums.err.NO_WEBHOOKS_ALLOWED);
let webhook = await this.getWebhook(client, channel).catch((e) => { let webhook = await getWebhook(client, channel).catch((e) =>{throw e});
throw e
});
if (!webhook) { if (!webhook) {
webhook = await channel.createWebhook({name: name}); webhook = await channel.createWebhook({name: name});
} }
return webhook; return webhook;
}, }
/** /**
* Gets an existing webhook. * Gets an existing webhook.
@@ -82,7 +76,7 @@ const webhookHelper = {
* @param {Channel} channel - The channel the message was sent in. * @param {Channel} channel - The channel the message was sent in.
* @returns {Webhook} A webhook object. * @returns {Webhook} A webhook object.
*/ */
async getWebhook(client, channel) { async function getWebhook(client, channel) {
const channelWebhooks = await channel?.fetchWebhooks() ?? []; const channelWebhooks = await channel?.fetchWebhooks() ?? [];
if (channelWebhooks.length === 0) { if (channelWebhooks.length === 0) {
return; return;
@@ -95,7 +89,5 @@ const webhookHelper = {
}) })
return pf_webhook; return pf_webhook;
} }
}
export const webhookHelper = wh;
module.exports = webhookHelper;

View File

@@ -1,7 +1,7 @@
const {enums} = require("../enums.js"); import {enums} from "./enums.js";
const {memberHelper} = require("memberHelper.js"); import {memberHelper} from "./helpers/memberHelper.js";
const importHelper = { const ih = {};
/** /**
* Tries to import from Pluralkit. * Tries to import from Pluralkit.
@@ -12,7 +12,7 @@ const importHelper = {
* @returns {string} A successful addition of all members. * @returns {string} A successful addition of all members.
* @throws {Error} When the member exists, or creating a member doesn't work. * @throws {Error} When the member exists, or creating a member doesn't work.
*/ */
async pluralKitImport(authorId, attachmentUrl) { ih.pluralKitImport = async function (authorId, attachmentUrl) {
if (!attachmentUrl) { if (!attachmentUrl) {
throw new Error(enums.err.NOT_JSON_FILE); throw new Error(enums.err.NOT_JSON_FILE);
} }
@@ -28,8 +28,7 @@ const importHelper = {
errors.push(`${pkMember.name}: ${e.message}`); errors.push(`${pkMember.name}: ${e.message}`);
}); });
await memberHelper.checkImageFormatValidity(pkMember.avatar_url).catch(e => { await memberHelper.checkImageFormatValidity(pkMember.avatar_url).catch(e => {
errors.push(`${pkMember.name}: ${e.message}`) errors.push(`${pkMember.name}: ${e.message}`)});
});
} }
const aggregatedText = addedMembers.length > 0 ? `Successfully added members: ${addedMembers.join(', ')}` : enums.err.NO_MEMBERS_IMPORTED; const aggregatedText = addedMembers.length > 0 ? `Successfully added members: ${addedMembers.join(', ')}` : enums.err.NO_MEMBERS_IMPORTED;
if (errors.length > 0) { if (errors.length > 0) {
@@ -38,6 +37,5 @@ const importHelper = {
return aggregatedText; return aggregatedText;
}); });
} }
};
module.exports = importHelper; export const importHelper = ih;