mirror of
https://github.com/pieartsy/PluralFlux.git
synced 2026-04-14 20:15:28 +10:00
Revert "converted import syntax to commonJS"
This reverts commit 5ab0d62b
This commit is contained in:
14
src/bot.js
14
src/bot.js
@@ -1,9 +1,9 @@
|
||||
const {messageHelper} = require('./helpers/messageHelper.js');
|
||||
const {enums} = require('enums.js');
|
||||
const {commands} = require('commands.js');
|
||||
const {webhookHelper} = require('helpers/webhookHelper.js');
|
||||
const {Client, Events } = require('@fluxerjs/core');
|
||||
const {env} = require('dotenv');
|
||||
import { Client, Events } from '@fluxerjs/core';
|
||||
import { messageHelper } from "./helpers/messageHelper.js";
|
||||
import {enums} from "./enums.js";
|
||||
import {commands} from "./commands.js";
|
||||
import {webhookHelper} from "./helpers/webhookHelper.js";
|
||||
import * as env from 'dotenv';
|
||||
|
||||
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 (!content.startsWith(messageHelper.prefix)) {
|
||||
await webhookHelper.sendMessageAsMember(client, message).catch((e) => {
|
||||
await webhookHelper.sendMessageAsMember(client, message, content).catch((e) => {
|
||||
throw e
|
||||
});
|
||||
return;
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
const {messageHelper} = require('helpers/messageHelper.js')
|
||||
const {enums} = require('enums.js')
|
||||
const {memberHelper} = require('helpers/memberHelper.js')
|
||||
const {importHelper} = require('helpers/importHelper.js');
|
||||
const {EmbedBuilder} = require('@fluxerjs/core');
|
||||
import {messageHelper} from "./helpers/messageHelper.js";
|
||||
import {enums} from "./enums.js";
|
||||
import {memberHelper} from "./helpers/memberHelper.js";
|
||||
import {EmbedBuilder} from "@fluxerjs/core";
|
||||
import {importHelper} from "./import.js";
|
||||
|
||||
const cmds = new Map();
|
||||
|
||||
let commands = new Map();
|
||||
|
||||
commands.set('member', {
|
||||
cmds.set('member', {
|
||||
description: enums.help.SHORT_DESC_MEMBER,
|
||||
async execute(message, client, args) {
|
||||
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,
|
||||
async execute(message) {
|
||||
const fields = [...commands.entries()].map(([name, cmd]) => ({
|
||||
const fields = [...cmds.entries()].map(([name, cmd]) => ({
|
||||
name: `${messageHelper.prefix}${name}`,
|
||||
value: cmd.description,
|
||||
inline: true,
|
||||
@@ -44,7 +43,7 @@ commands.set('help', {
|
||||
},
|
||||
})
|
||||
|
||||
commands.set('import', {
|
||||
cmds.set('import', {
|
||||
description: enums.help.SHORT_DESC_IMPORT,
|
||||
async execute(message) {
|
||||
if (message.content.includes('--help')) {
|
||||
@@ -71,4 +70,4 @@ commands.set('import', {
|
||||
}
|
||||
})
|
||||
|
||||
module.exports = commands;
|
||||
export const commands = cmds;
|
||||
122
src/db.js
122
src/db.js
@@ -1,5 +1,5 @@
|
||||
const {DataTypes, sequelize, Sequelize} = require('sequelize');
|
||||
const {env} = require('dotenv');
|
||||
import {DataTypes, Sequelize} from 'sequelize';
|
||||
import * as env from 'dotenv';
|
||||
|
||||
env.config();
|
||||
|
||||
@@ -10,75 +10,75 @@ if (!password) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const database = {
|
||||
const db = {};
|
||||
|
||||
sequelize: new Sequelize('postgres', 'postgres', password, {
|
||||
host: 'localhost',
|
||||
logging: false,
|
||||
dialect: 'postgres'
|
||||
}),
|
||||
const sequelize = new Sequelize('postgres', 'postgres', password, {
|
||||
host: 'localhost',
|
||||
logging: false,
|
||||
dialect: 'postgres'
|
||||
});
|
||||
|
||||
Sequelize: Sequelize,
|
||||
db.sequelize = sequelize;
|
||||
db.Sequelize = Sequelize;
|
||||
|
||||
members: sequelize.define('Member', {
|
||||
userid: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
displayname: {
|
||||
type: DataTypes.STRING,
|
||||
},
|
||||
propic: {
|
||||
type: DataTypes.STRING,
|
||||
},
|
||||
proxy: {
|
||||
type: DataTypes.STRING,
|
||||
}
|
||||
}),
|
||||
db.members = sequelize.define('Member', {
|
||||
userid: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
displayname: {
|
||||
type: DataTypes.STRING,
|
||||
},
|
||||
propic: {
|
||||
type: DataTypes.STRING,
|
||||
},
|
||||
proxy: {
|
||||
type: DataTypes.STRING,
|
||||
}
|
||||
});
|
||||
|
||||
systems: sequelize.define('System', {
|
||||
userid: {
|
||||
type: DataTypes.STRING,
|
||||
},
|
||||
fronter: {
|
||||
type: DataTypes.STRING
|
||||
},
|
||||
grouptag: {
|
||||
type: DataTypes.STRING
|
||||
},
|
||||
autoproxy: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
}
|
||||
}),
|
||||
db.systems = sequelize.define('System', {
|
||||
userid: {
|
||||
type: DataTypes.STRING,
|
||||
},
|
||||
fronter: {
|
||||
type: DataTypes.STRING
|
||||
},
|
||||
grouptag: {
|
||||
type: DataTypes.STRING
|
||||
},
|
||||
autoproxy: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* Checks Sequelize database connection.
|
||||
*/
|
||||
check_connection: async function () {
|
||||
/**
|
||||
* Checks Sequelize database connection.
|
||||
*/
|
||||
db.check_connection = async function() {
|
||||
await sequelize.authenticate().then(async () => {
|
||||
console.log('Connection has been established successfully.');
|
||||
await this.syncModels();
|
||||
await syncModels();
|
||||
}).catch(err => {
|
||||
console.error('Unable to connect to the database:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Syncs Sequelize models.
|
||||
*/
|
||||
async syncModels() {
|
||||
await this.sequelize.sync().then(() => {
|
||||
console.log('Models synced successfully.');
|
||||
}).catch((err) => {
|
||||
console.error('Syncing models did not work', err);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Syncs Sequelize models.
|
||||
*/
|
||||
async function syncModels() {
|
||||
await sequelize.sync().then(() => {
|
||||
console.log('Models synced successfully.');
|
||||
}).catch((err) => {
|
||||
console.error('Syncing models did not work', err);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = database;
|
||||
export const database = db;
|
||||
86
src/enums.js
86
src/enums.js
@@ -1,46 +1,46 @@
|
||||
const enums = {
|
||||
err: {
|
||||
NO_MEMBER: "No such member was found.",
|
||||
NO_NAME_PROVIDED: "No member name was provided for",
|
||||
NO_VALUE: "has not been set for this member. Please provide a value.",
|
||||
ADD_ERROR: "Error adding member.",
|
||||
MEMBER_EXISTS: "A member with that name already exists. Please pick a unique name.",
|
||||
USER_NO_MEMBERS: "You have no members created.",
|
||||
DISPLAY_NAME_TOO_LONG: "The display name is too long. Please limit it to 32 characters or less.",
|
||||
PROXY_EXISTS: "A duplicate proxy already exists for one of your members. Please pick a new one, or change the old one first.",
|
||||
NO_SUCH_COMMAND: "No such command exists.",
|
||||
PROPIC_FAILS_REQUIREMENTS: "Profile picture must be in JPG, PNG, or WEBP format and less than 10MB.",
|
||||
PROPIC_CANNOT_LOAD: "Profile picture could not be loaded from URL.",
|
||||
NO_WEBHOOKS_ALLOWED: "Channel does not support webhooks.",
|
||||
NOT_IN_SERVER: "You can only proxy in a server.",
|
||||
NO_MESSAGE_SENT_WITH_PROXY: 'Proxied message has no content.',
|
||||
NO_TEXT_FOR_PROXY: "You need the word 'text' for the bot to detect proxy tags with.\nCorrect usage examples: `pf;member jane proxy J:text`, `pf;member jane [text]`",
|
||||
NO_PROXY_WRAPPER: "You need at least one proxy tag surrounding 'text', either before or after.\nCorrect usage examples: `pf;member jane proxy J:text`, `pf;member jane [text]`",
|
||||
NOT_JSON_FILE: "Please attach a valid JSON file.",
|
||||
NO_MEMBERS_IMPORTED: 'No members were imported.',
|
||||
IMPORT_ERROR: "Please see attached file for logs on the member import process.",
|
||||
},
|
||||
const helperEnums = {};
|
||||
|
||||
help: {
|
||||
SHORT_DESC_HELP: "Lists available commands.",
|
||||
SHORT_DESC_MEMBER: "Accesses subcommands related to proxy members.",
|
||||
SHORT_DESC_IMPORT: "Imports from PluralKit.",
|
||||
SHORT_DESC_PLURALFLUX: "PluralFlux is a proxybot akin to PluralKit and Tupperbot, but for Fluxer. All commands are prefixed by `pf;`. Type `pf;help` for info on the bot itself.",
|
||||
PLURALFLUX: "PluralFlux is a proxybot akin to PluralKit and Tupperbot, but for Fluxer. All commands are prefixed by `pf;`. Add ` --help` to the end of a command to find out more about it, or just send it without arguments.",
|
||||
MEMBER: "Accesses the sub-commands related to editing proxy members. The available subcommands are `list`, `new`, `remove`, `displayname`, `proxy`, and `propic`. Add ` --help` to the end of a subcommand to find out more about it, or just send it without arguments.",
|
||||
NEW: "Creates a new member to proxy with, for example: `pf;member new jane`. The member name should ideally be short so you can write other commands with it easily. \n\nYou can optionally add a display name after the member name, for example: `pf;member new jane \"Jane Doe | ze/hir\"`. If it has spaces, put it in __double quotes__. The length limit is 32 characters.",
|
||||
REMOVE: "Removes a member based on their name, for example: `pf;member remove jane`.",
|
||||
LIST: "Lists members in the system. Currently only lists the first 25.",
|
||||
NAME: "Updates the name for a specific member based on their current name, for ex: `pf;member john name jane`. The member name should ideally be short so you can write other commands with it easily.",
|
||||
DISPLAY_NAME: "Updates the display name for a specific member based on their name, for example: `pf;member jane \"Jane Doe | ze/hir\"`.This can be up to 32 characters long. If it has spaces, put it in __double quotes__.",
|
||||
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.",
|
||||
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?)."
|
||||
},
|
||||
helperEnums.err = {
|
||||
NO_MEMBER: "No such member was found.",
|
||||
NO_NAME_PROVIDED: "No member name was provided for",
|
||||
NO_VALUE: "has not been set for this member. Please provide a value.",
|
||||
ADD_ERROR: "Error adding member.",
|
||||
MEMBER_EXISTS: "A member with that name already exists. Please pick a unique name.",
|
||||
USER_NO_MEMBERS: "You have no members created.",
|
||||
DISPLAY_NAME_TOO_LONG: "The display name is too long. Please limit it to 32 characters or less.",
|
||||
PROXY_EXISTS: "A duplicate proxy already exists for one of your members. Please pick a new one, or change the old one first.",
|
||||
NO_SUCH_COMMAND: "No such command exists.",
|
||||
PROPIC_FAILS_REQUIREMENTS: "Profile picture must be in JPG, PNG, or WEBP format and less than 10MB.",
|
||||
PROPIC_CANNOT_LOAD: "Profile picture could not be loaded from URL.",
|
||||
NO_WEBHOOKS_ALLOWED: "Channel does not support webhooks.",
|
||||
NOT_IN_SERVER: "You can only proxy in a server.",
|
||||
NO_MESSAGE_SENT_WITH_PROXY: 'Proxied message has no content.',
|
||||
NO_TEXT_FOR_PROXY: "You need the word 'text' for the bot to detect proxy tags with.\nCorrect usage examples: `pf;member jane proxy J:text`, `pf;member jane [text]`",
|
||||
NO_PROXY_WRAPPER: "You need at least one proxy tag surrounding 'text', either before or after.\nCorrect usage examples: `pf;member jane proxy J:text`, `pf;member jane [text]`",
|
||||
NOT_JSON_FILE: "Please attach a valid JSON file.",
|
||||
NO_MEMBERS_IMPORTED: 'No members were imported.',
|
||||
IMPORT_ERROR: "Please see attached file for logs on the member import process.",
|
||||
}
|
||||
|
||||
misc: {
|
||||
ATTACHMENT_SENT_BY: "Attachment sent by:"
|
||||
}
|
||||
};
|
||||
helperEnums.help = {
|
||||
SHORT_DESC_HELP: "Lists available commands.",
|
||||
SHORT_DESC_MEMBER: "Accesses subcommands related to proxy members.",
|
||||
SHORT_DESC_IMPORT: "Imports from PluralKit.",
|
||||
SHORT_DESC_PLURALFLUX: "PluralFlux is a proxybot akin to PluralKit and Tupperbot, but for Fluxer. All commands are prefixed by `pf;`. Type `pf;help` for info on the bot itself.",
|
||||
PLURALFLUX: "PluralFlux is a proxybot akin to PluralKit and Tupperbot, but for Fluxer. All commands are prefixed by `pf;`. Add ` --help` to the end of a command to find out more about it, or just send it without arguments.",
|
||||
MEMBER: "Accesses the sub-commands related to editing proxy members. The available subcommands are `list`, `new`, `remove`, `displayname`, `proxy`, and `propic`. Add ` --help` to the end of a subcommand to find out more about it, or just send it without arguments.",
|
||||
NEW: "Creates a new member to proxy with, for example: `pf;member new jane`. The member name should ideally be short so you can write other commands with it easily. \n\nYou can optionally add a display name after the member name, for example: `pf;member new jane \"Jane Doe | ze/hir\"`. If it has spaces, put it in __double quotes__. The length limit is 32 characters.",
|
||||
REMOVE: "Removes a member based on their name, for example: `pf;member remove jane`.",
|
||||
LIST: "Lists members in the system. Currently only lists the first 25.",
|
||||
NAME: "Updates the name for a specific member based on their current name, for ex: `pf;member john name jane`. The member name should ideally be short so you can write other commands with it easily.",
|
||||
DISPLAY_NAME: "Updates the display name for a specific member based on their name, for example: `pf;member jane \"Jane Doe | ze/hir\"`.This can be up to 32 characters long. If it has spaces, put it in __double quotes__.",
|
||||
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.",
|
||||
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?)."
|
||||
}
|
||||
|
||||
module.exports = enums;
|
||||
helperEnums.misc = {
|
||||
ATTACHMENT_SENT_BY: "Attachment sent by:"
|
||||
}
|
||||
|
||||
export const enums = helperEnums;
|
||||
@@ -1,456 +1,500 @@
|
||||
const { database } = require('../db.js')
|
||||
const { enums} = require('../enums.js');
|
||||
const {EmptyResultError, Op} = require('sequelize');
|
||||
const {EmbedBuilder} = require('@fluxerjs/core');
|
||||
import {database} from '../db.js';
|
||||
import {enums} from "../enums.js";
|
||||
import {EmptyResultError, Op} from "sequelize";
|
||||
import {EmbedBuilder} from "@fluxerjs/core";
|
||||
|
||||
const memberHelper = {
|
||||
const mh = {};
|
||||
|
||||
// Has an empty "command" to parse the help message properly
|
||||
const commandList = ['--help', 'new', 'remove', 'name', 'list', 'displayName', 'proxy', 'propic', ''];
|
||||
|
||||
// Has an empty "command" to parse the help message properly
|
||||
commandList: ['--help', 'new', 'remove', 'name', 'list', 'displayName', 'proxy', 'propic', ''],
|
||||
|
||||
/**
|
||||
* Parses through the subcommands that come after "pf;member" and calls functions accordingly.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The id of the message author
|
||||
* @param {string} authorFull - The username and discriminator of the message author
|
||||
* @param {string[]} args - The message arguments
|
||||
* @param {string | null} attachmentUrl - The message attachment url.
|
||||
* @param {string | null} attachmentExpiration - The message attachment expiration (if uploaded via Fluxer)
|
||||
* @returns {Promise<string> | Promise <EmbedBuilder>} A message, or an informational embed.
|
||||
* @throws {Error}
|
||||
*/
|
||||
async parseMemberCommand (authorId, authorFull, args, attachmentUrl = null, attachmentExpiration = null){
|
||||
let member;
|
||||
// checks whether command is in list, otherwise assumes it's a name
|
||||
if(!this.commandList.includes(args[0])) {
|
||||
member = await this.getMemberInfo(authorId, args[0]);
|
||||
}
|
||||
switch(args[0]) {
|
||||
case '--help':
|
||||
return enums.help.MEMBER;
|
||||
case 'new':
|
||||
return await this.addNewMember(authorId, args).catch((e) =>{throw e});
|
||||
case 'remove':
|
||||
return await this.removeMember(authorId, args).catch((e) =>{throw e});
|
||||
case 'name':
|
||||
return enums.help.NAME;
|
||||
case 'displayname':
|
||||
return enums.help.DISPLAY_NAME;
|
||||
case 'proxy':
|
||||
return enums.help.PROXY;
|
||||
case 'propic':
|
||||
return enums.help.PROPIC;
|
||||
case 'list':
|
||||
if (args[1] && args[1] === "--help") {
|
||||
return enums.help.LIST;
|
||||
}
|
||||
return await this.getAllMembersInfo(authorId, authorFull).catch((e) =>{throw e});
|
||||
case '':
|
||||
return enums.help.MEMBER;
|
||||
}
|
||||
switch(args[1]) {
|
||||
case 'name':
|
||||
return await this.updateName(authorId, args).catch((e) =>{throw e});
|
||||
case 'displayname':
|
||||
return await this.updateDisplayName(authorId, args).catch((e) =>{throw e});
|
||||
case 'proxy':
|
||||
if (!args[2]) return await this.getProxyByMember(authorId, args[0]).catch((e) => {throw e});
|
||||
return await this.updateProxy(authorId, args).catch((e) =>{throw e});
|
||||
case 'propic':
|
||||
return await this.updatePropic(authorId, args, attachmentUrl, attachmentExpiration).catch((e) =>{throw e});
|
||||
default:
|
||||
return member;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a member.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The author of the message
|
||||
* @param {string[]} args - The message arguments
|
||||
* @returns {Promise<string>} A successful addition.
|
||||
* @throws {Error} When the member exists, or creating a member doesn't work.
|
||||
*/
|
||||
async addNewMember (authorId, args) {
|
||||
if (args[1] && args[1] === "--help" || !args[1]) {
|
||||
return enums.help.NEW;
|
||||
}
|
||||
const memberName = args[1];
|
||||
const displayName = args[2];
|
||||
|
||||
return await this.addFullMember(authorId, memberName, displayName).then((member) => {
|
||||
let success = `Member was successfully added.\nName: ${member.dataValues.name}`
|
||||
success += displayName ? `\nDisplay name: ${member.dataValues.displayname}` : "";
|
||||
return success;
|
||||
}).catch(e => {
|
||||
throw e;
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the name for a member.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The author of the message
|
||||
* @param {string[]} args - The message arguments
|
||||
* @returns {Promise<string>} A successful update.
|
||||
* @throws {RangeError} When the name doesn't exist.
|
||||
*/
|
||||
async updateName (authorId, args) {
|
||||
if (args[1] && args[1] === "--help" || !args[1]) {
|
||||
return enums.help.DISPLAY_NAME;
|
||||
}
|
||||
|
||||
const name = args[2];
|
||||
const trimmedName = name ? name.trim() : null;
|
||||
if (!name || trimmedName === null) {
|
||||
throw new RangeError(`Display name ${enums.err.NO_VALUE}`);
|
||||
}
|
||||
return await this.updateMemberField(authorId, args).catch((e) =>{throw e});
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the display name for a member.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The author of the message
|
||||
* @param {string[]} args - The message arguments
|
||||
* @returns {Promise<string>} A successful update.
|
||||
* @throws {RangeError} When the display name is too long or doesn't exist.
|
||||
*/
|
||||
async updateDisplayName (authorId, args) {
|
||||
if (args[1] && args[1] === "--help" || !args[1]) {
|
||||
return enums.help.DISPLAY_NAME;
|
||||
}
|
||||
|
||||
const memberName = args[0];
|
||||
const displayName = args[2];
|
||||
const trimmedName = displayName ? displayName.trim() : null;
|
||||
|
||||
if (!displayName || trimmedName === null ) {
|
||||
return await this.getMemberByName(authorId, memberName).then((member) => {
|
||||
if (member && member.displayname) {
|
||||
return `Display name for ${memberName} is: \"${member.displayname}\".`;
|
||||
}
|
||||
else if (member) {
|
||||
throw new RangeError(`Display name ${enums.err.NO_VALUE}`);
|
||||
}
|
||||
/**
|
||||
* Parses through the subcommands that come after "pf;member" and calls functions accordingly.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The id of the message author
|
||||
* @param {string} authorFull - The username and discriminator of the message author
|
||||
* @param {string[]} args - The message arguments
|
||||
* @param {string | null} attachmentUrl - The message attachment url.
|
||||
* @param {string | null} attachmentExpiration - The message attachment expiration (if uploaded via Fluxer)
|
||||
* @returns {Promise<string> | Promise <EmbedBuilder>} A message, or an informational embed.
|
||||
* @throws {Error}
|
||||
*/
|
||||
mh.parseMemberCommand = async function (authorId, authorFull, args, attachmentUrl = null, attachmentExpiration = null) {
|
||||
let member;
|
||||
// checks whether command is in list, otherwise assumes it's a name
|
||||
if (!commandList.includes(args[0])) {
|
||||
member = await mh.getMemberInfo(authorId, args[0]);
|
||||
}
|
||||
switch (args[0]) {
|
||||
case '--help':
|
||||
return enums.help.MEMBER;
|
||||
case 'new':
|
||||
return await mh.addNewMember(authorId, args).catch((e) => {
|
||||
throw e
|
||||
});
|
||||
}
|
||||
else if (displayName.length > 32) {
|
||||
throw new RangeError(enums.err.DISPLAY_NAME_TOO_LONG);
|
||||
}
|
||||
return await this.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.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The author of the message
|
||||
* @param {string[]} args - The message arguments
|
||||
* @returns {Promise<string> } A successful update.
|
||||
* @throws {RangeError | Error} When an empty proxy was provided, or no proxy exists.
|
||||
*/
|
||||
async updateProxy (authorId, args) {
|
||||
if (args[2] && args[2] === "--help") {
|
||||
case 'remove':
|
||||
return await mh.removeMember(authorId, args).catch((e) => {
|
||||
throw e
|
||||
});
|
||||
case 'name':
|
||||
return enums.help.NAME;
|
||||
case 'displayname':
|
||||
return enums.help.DISPLAY_NAME;
|
||||
case 'proxy':
|
||||
return enums.help.PROXY;
|
||||
}
|
||||
const proxyExists = await this.checkIfProxyExists(authorId, args[2]).then((proxyExists) => {
|
||||
return proxyExists;
|
||||
}).catch((e) =>{throw e});
|
||||
if (!proxyExists) {
|
||||
return await this.updateMemberField(authorId, args).catch((e) =>{throw e});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the profile pic for a member, based on either the attachment or the args provided.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The author of the message
|
||||
* @param {string[]} args - The message arguments
|
||||
* @param {string} attachmentUrl - The url of the first attachment in the message
|
||||
* @param {string | null} attachmentExpiry - The expiration date of the first attachment in the message (if uploaded to Fluxer)
|
||||
* @returns {Promise<string>} A successful update.
|
||||
* @throws {Error} When loading the profile picture from a URL doesn't work.
|
||||
*/
|
||||
async updatePropic (authorId, args, attachmentUrl, attachmentExpiry= null) {
|
||||
if (args[1] && args[1] === "--help") {
|
||||
case 'propic':
|
||||
return enums.help.PROPIC;
|
||||
}
|
||||
let img;
|
||||
const updatedArgs = args;
|
||||
if (!updatedArgs[1] && !attachmentUrl) {
|
||||
return enums.help.PROPIC;
|
||||
} else if (attachmentUrl) {
|
||||
updatedArgs[2] = attachmentUrl;
|
||||
updatedArgs[3] = attachmentExpiry;
|
||||
}
|
||||
if (updatedArgs[2]) {
|
||||
img = updatedArgs[2];
|
||||
}
|
||||
const isValidImage = await this.checkImageFormatValidity(img).catch((e) =>{throw e});
|
||||
if (isValidImage) {
|
||||
return await this.updateMemberField(authorId, updatedArgs).catch((e) =>{throw e});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks if an uploaded picture is in the right format.
|
||||
*
|
||||
* @async
|
||||
* @param {string} imageUrl - The url of the image
|
||||
* @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.
|
||||
*/
|
||||
async checkImageFormatValidity (imageUrl) {
|
||||
const acceptableImages = ['image/png', 'image/jpg', 'image/jpeg', 'image/webp'];
|
||||
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);
|
||||
return true;
|
||||
}).catch((error) => {
|
||||
throw new Error(`${enums.err.PROPIC_CANNOT_LOAD}: ${error.message}`);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes a member.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The author of the message
|
||||
* @param {string[]} args - The message arguments
|
||||
* @returns {Promise<string>} A successful removal.
|
||||
* @throws {EmptyResultError} When there is no member to remove.
|
||||
*/
|
||||
async removeMember (authorId, args) {
|
||||
if (args[1] && args[1] === "--help" || !args[1]) {
|
||||
return enums.help.REMOVE;
|
||||
}
|
||||
|
||||
const memberName = args[1];
|
||||
return await database.members.destroy({ where: { name: {[Op.iLike]: memberName}, userid: authorId } }).then((result) => {
|
||||
if (result) {
|
||||
return `Member "${memberName}" has been deleted.`;
|
||||
case 'list':
|
||||
if (args[1] && args[1] === "--help") {
|
||||
return enums.help.LIST;
|
||||
}
|
||||
throw new EmptyResultError(`${enums.err.NO_MEMBER}`);
|
||||
})
|
||||
},
|
||||
|
||||
/*======Non-Subcommands======*/
|
||||
|
||||
/**
|
||||
* Adds a member with full details, first checking that there is no member of that name associated with the author.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The author of the message
|
||||
* @param {string} memberName - The 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} propic - The profile picture URL of the member.
|
||||
* @param {boolean} isImport - Whether calling from the import or not.
|
||||
* @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.
|
||||
*/
|
||||
async addFullMember (authorId, memberName, displayName = null, proxy = null, propic= null, isImport = false) {
|
||||
await this.getMemberByName(authorId, memberName).then((member) => {
|
||||
if (member) {
|
||||
throw new Error(`Can't add ${memberName}. ${enums.err.MEMBER_EXISTS}`);
|
||||
}
|
||||
});
|
||||
if (displayName) {
|
||||
const trimmedName = displayName ? displayName.trim() : null;
|
||||
if (trimmedName && trimmedName.length > 32) {
|
||||
throw new RangeError(`Can't add ${memberName}. ${enums.err.DISPLAY_NAME_TOO_LONG}`);
|
||||
}
|
||||
}
|
||||
if (proxy) {
|
||||
await this.checkIfProxyExists(authorId, proxy).catch((e) =>{throw e});
|
||||
}
|
||||
let validPropic;
|
||||
if (propic) {
|
||||
validPropic = await this.checkImageFormatValidity(propic).then((valid) => {
|
||||
return valid;
|
||||
}).catch((e) =>{
|
||||
if (!isImport) {
|
||||
throw (e);
|
||||
}
|
||||
return false;
|
||||
return await mh.getAllMembersInfo(authorId, authorFull).catch((e) => {
|
||||
throw e
|
||||
});
|
||||
}
|
||||
|
||||
const member = await database.members.create({
|
||||
name: memberName,
|
||||
userid: authorId,
|
||||
displayname: displayName,
|
||||
proxy: proxy,
|
||||
propic: validPropic ? propic : null,
|
||||
});
|
||||
if (!member) {
|
||||
new Error(`${enums.err.ADD_ERROR}`);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates one fields for a member in the database.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The author of the message
|
||||
* @param {string[]} args - The message arguments
|
||||
* @returns {Promise<string>} A successful update.
|
||||
* @throws {EmptyResultError | Error} When the member is not found, or catchall error.
|
||||
*/
|
||||
async updateMemberField (authorId, args) {
|
||||
const memberName = args[0];
|
||||
const columnName = args[1];
|
||||
const value = args[2];
|
||||
let fluxerPropicWarning;
|
||||
|
||||
// indicates that an attachment was uploaded on Fluxer directly
|
||||
if (columnName === "propic" && args[3]) {
|
||||
fluxerPropicWarning = this.setExpirationWarning(args[3]);
|
||||
}
|
||||
return await database.members.update({[columnName]: value}, { where: { name: {[Op.iLike]: memberName}, userid: authorId } }).then(() => {
|
||||
return `Updated ${columnName} for ${memberName} to ${value}${fluxerPropicWarning ?? ''}.`;
|
||||
}).catch(e => {
|
||||
if (e === EmptyResultError) {
|
||||
throw new EmptyResultError(`Can't update ${memberName}. ${enums.err.NO_MEMBER}: ${e.message}`);
|
||||
}
|
||||
else {
|
||||
throw new Error(`Can't update ${memberName}. ${e.message}`);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the warning for an expiration date.
|
||||
*
|
||||
* @param {string} expirationString - An expiration date string.
|
||||
* @returns {string} A description of the expiration, interpolating the expiration string.
|
||||
*/
|
||||
setExpirationWarning(expirationString) {
|
||||
let expirationDate = new Date(expirationString);
|
||||
if (!isNaN(expirationDate.valueOf())) {
|
||||
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`
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the details for a member.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The author of the message
|
||||
* @param {string} memberName - The message arguments
|
||||
* @returns {Promise<EmbedBuilder>} The member's info.
|
||||
*/
|
||||
async getMemberInfo (authorId, memberName) {
|
||||
return await this.getMemberByName(authorId, memberName).then((member) => {
|
||||
if (member) {
|
||||
return new EmbedBuilder()
|
||||
.setTitle(member.name)
|
||||
.setDescription(`Details for ${member.name}`)
|
||||
.addFields(
|
||||
{name: 'Display name: ', value: member.displayname ?? 'unset', inline: true},
|
||||
{name: 'Proxy tag: ', value: member.proxy ?? 'unset', inline: true},
|
||||
)
|
||||
.setImage(member.propic);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets all members for an author.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The id of the message author
|
||||
* @param {string} authorName - The id name the message author
|
||||
* @returns {Promise<EmbedBuilder>} The info for all members.
|
||||
* @throws {Error} When there are no members for an author.
|
||||
*/
|
||||
async getAllMembersInfo (authorId, authorName) {
|
||||
const members = await this.getMembersByAuthor(authorId);
|
||||
if (members == null) throw Error(enums.err.USER_NO_MEMBERS);
|
||||
const fields = [...members.entries()].map(([name, member]) => ({
|
||||
name: member.name,
|
||||
value: `(Proxy: \`${member.proxy ?? "unset"}\`)`,
|
||||
inline: true,
|
||||
}));
|
||||
return new EmbedBuilder()
|
||||
.setTitle(`${fields > 25 ? "First 25 m" : "M"}embers for ${authorName}`)
|
||||
.addFields(...fields);
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets a member based on the author and proxy tag.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The author of the message.
|
||||
* @param {string} memberName - The member's name.
|
||||
* @returns {Promise<model>} The member object.
|
||||
* @throws { EmptyResultError } When the member is not found.
|
||||
*/
|
||||
async getMemberByName (authorId, memberName) {
|
||||
return await database.members.findOne({ where: { userid: authorId, name: {[Op.iLike]: memberName}}});
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets a member based on the author and proxy tag.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The author of the message.
|
||||
* @param {string} memberName - The member's name.
|
||||
* @returns {Promise<model>} The member object.
|
||||
* @throws { EmptyResultError } When the member is not found.
|
||||
*/
|
||||
async getProxyByMember (authorId, memberName) {
|
||||
return await this.getMemberByName(authorId, memberName).then((member) => {
|
||||
if (member) {
|
||||
return member.dataValues.proxy;
|
||||
}
|
||||
throw new EmptyResultError(enums.err.NO_MEMBER);
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets all members belonging to the author.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The author of the message
|
||||
* @returns {Promise<model[] | null>} The member object array.
|
||||
*/
|
||||
async getMembersByAuthor (authorId) {
|
||||
return await database.members.findAll({ where: { userid: authorId } });
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Checks if proxy exists for a member.
|
||||
*
|
||||
* @param {string} authorId - The author of the message
|
||||
* @param {string} proxy - The proxy tag.
|
||||
* @returns {Promise<boolean> } Whether the proxy exists.
|
||||
* @throws {Error} When an empty proxy was provided, or no proxy exists.
|
||||
*/
|
||||
async checkIfProxyExists (authorId, proxy) {
|
||||
if (proxy) {
|
||||
const splitProxy = proxy.trim().split("text");
|
||||
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);
|
||||
|
||||
await this.getMembersByAuthor(authorId).then((memberList) => {
|
||||
const proxyExists = memberList.some(member => member.proxy === proxy);
|
||||
if (proxyExists) {
|
||||
throw new Error(enums.err.PROXY_EXISTS);
|
||||
}
|
||||
}).catch(e =>{throw e});
|
||||
}
|
||||
|
||||
case '':
|
||||
return enums.help.MEMBER;
|
||||
}
|
||||
switch (args[1]) {
|
||||
case 'name':
|
||||
return await mh.updateName(authorId, args).catch((e) => {
|
||||
throw e
|
||||
});
|
||||
case 'displayname':
|
||||
return await mh.updateDisplayName(authorId, args).catch((e) => {
|
||||
throw e
|
||||
});
|
||||
case 'proxy':
|
||||
if (!args[2]) return await mh.getProxyByMember(authorId, args[0]).catch((e) => {
|
||||
throw e
|
||||
});
|
||||
return await mh.updateProxy(authorId, args).catch((e) => {
|
||||
throw e
|
||||
});
|
||||
case 'propic':
|
||||
return await mh.updatePropic(authorId, args, attachmentUrl, attachmentExpiration).catch((e) => {
|
||||
throw e
|
||||
});
|
||||
default:
|
||||
return member;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a member.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The author of the message
|
||||
* @param {string[]} args - The message arguments
|
||||
* @returns {Promise<string>} A successful addition.
|
||||
* @throws {Error} When the member exists, or creating a member doesn't work.
|
||||
*/
|
||||
mh.addNewMember = async function (authorId, args) {
|
||||
if (args[1] && args[1] === "--help" || !args[1]) {
|
||||
return enums.help.NEW;
|
||||
}
|
||||
const memberName = args[1];
|
||||
const displayName = args[2];
|
||||
|
||||
module.exports = memberHelper;
|
||||
return await mh.addFullMember(authorId, memberName, displayName).then((member) => {
|
||||
let success = `Member was successfully added.\nName: ${member.dataValues.name}`
|
||||
success += displayName ? `\nDisplay name: ${member.dataValues.displayname}` : "";
|
||||
return success;
|
||||
}).catch(e => {
|
||||
throw e;
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the name for a member.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The author of the message
|
||||
* @param {string[]} args - The message arguments
|
||||
* @returns {Promise<string>} A successful update.
|
||||
* @throws {RangeError} When the name doesn't exist.
|
||||
*/
|
||||
mh.updateName = async function (authorId, args) {
|
||||
if (args[1] && args[1] === "--help" || !args[1]) {
|
||||
return enums.help.DISPLAY_NAME;
|
||||
}
|
||||
|
||||
const name = args[2];
|
||||
const trimmedName = name ? name.trim() : null;
|
||||
if (!name || trimmedName === null) {
|
||||
throw new RangeError(`Display name ${enums.err.NO_VALUE}`);
|
||||
}
|
||||
return await mh.updateMemberField(authorId, args).catch((e) => {
|
||||
throw e
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the display name for a member.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The author of the message
|
||||
* @param {string[]} args - The message arguments
|
||||
* @returns {Promise<string>} A successful update.
|
||||
* @throws {RangeError} When the display name is too long or doesn't exist.
|
||||
*/
|
||||
mh.updateDisplayName = async function (authorId, args) {
|
||||
if (args[1] && args[1] === "--help" || !args[1]) {
|
||||
return enums.help.DISPLAY_NAME;
|
||||
}
|
||||
|
||||
const memberName = args[0];
|
||||
const displayName = args[2];
|
||||
const trimmedName = displayName ? displayName.trim() : null;
|
||||
|
||||
if (!displayName || trimmedName === null) {
|
||||
return await mh.getMemberByName(authorId, memberName).then((member) => {
|
||||
if (member && member.displayname) {
|
||||
return `Display name for ${memberName} is: \"${member.displayname}\".`;
|
||||
} else if (member) {
|
||||
throw new RangeError(`Display name ${enums.err.NO_VALUE}`);
|
||||
}
|
||||
});
|
||||
} else if (displayName.length > 32) {
|
||||
throw new RangeError(enums.err.DISPLAY_NAME_TOO_LONG);
|
||||
}
|
||||
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.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The author of the message
|
||||
* @param {string[]} args - The message arguments
|
||||
* @returns {Promise<string> } A successful update.
|
||||
* @throws {RangeError | Error} When an empty proxy was provided, or no proxy exists.
|
||||
*/
|
||||
mh.updateProxy = async function (authorId, args) {
|
||||
if (args[2] && args[2] === "--help") {
|
||||
return enums.help.PROXY;
|
||||
}
|
||||
const proxyExists = await mh.checkIfProxyExists(authorId, args[2]).then((proxyExists) => {
|
||||
return proxyExists;
|
||||
}).catch((e) => {
|
||||
throw e
|
||||
});
|
||||
if (!proxyExists) {
|
||||
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.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The author of the message
|
||||
* @param {string[]} args - The message arguments
|
||||
* @param {string} attachmentUrl - The url of the first attachment in the message
|
||||
* @param {string | null} attachmentExpiry - The expiration date of the first attachment in the message (if uploaded to Fluxer)
|
||||
* @returns {Promise<string>} A successful update.
|
||||
* @throws {Error} When loading the profile picture from a URL doesn't work.
|
||||
*/
|
||||
mh.updatePropic = async function (authorId, args, attachmentUrl, attachmentExpiry = null) {
|
||||
if (args[1] && args[1] === "--help") {
|
||||
return enums.help.PROPIC;
|
||||
}
|
||||
let img;
|
||||
const updatedArgs = args;
|
||||
if (!updatedArgs[1] && !attachmentUrl) {
|
||||
return enums.help.PROPIC;
|
||||
} else if (attachmentUrl) {
|
||||
updatedArgs[2] = attachmentUrl;
|
||||
updatedArgs[3] = attachmentExpiry;
|
||||
}
|
||||
if (updatedArgs[2]) {
|
||||
img = updatedArgs[2];
|
||||
}
|
||||
const isValidImage = await mh.checkImageFormatValidity(img).catch((e) => {
|
||||
throw e
|
||||
});
|
||||
if (isValidImage) {
|
||||
return await mh.updateMemberField(authorId, updatedArgs).catch((e) => {
|
||||
throw e
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an uploaded picture is in the right format.
|
||||
*
|
||||
* @async
|
||||
* @param {string} imageUrl - The url of the image
|
||||
* @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.
|
||||
*/
|
||||
mh.checkImageFormatValidity = async function (imageUrl) {
|
||||
const acceptableImages = ['image/png', 'image/jpg', 'image/jpeg', 'image/webp'];
|
||||
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);
|
||||
return true;
|
||||
}).catch((error) => {
|
||||
throw new Error(`${enums.err.PROPIC_CANNOT_LOAD}: ${error.message}`);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a member.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The author of the message
|
||||
* @param {string[]} args - The message arguments
|
||||
* @returns {Promise<string>} A successful removal.
|
||||
* @throws {EmptyResultError} When there is no member to remove.
|
||||
*/
|
||||
mh.removeMember = async function (authorId, args) {
|
||||
if (args[1] && args[1] === "--help" || !args[1]) {
|
||||
return enums.help.REMOVE;
|
||||
}
|
||||
|
||||
const memberName = args[1];
|
||||
return await database.members.destroy({
|
||||
where: {
|
||||
name: {[Op.iLike]: memberName},
|
||||
userid: authorId
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
return `Member "${memberName}" has been deleted.`;
|
||||
}
|
||||
throw new EmptyResultError(`${enums.err.NO_MEMBER}`);
|
||||
})
|
||||
}
|
||||
|
||||
/*======Non-Subcommands======*/
|
||||
|
||||
/**
|
||||
* Adds a member with full details, first checking that there is no member of that name associated with the author.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The author of the message
|
||||
* @param {string} memberName - The 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} propic - The profile picture URL of the member.
|
||||
* @param {boolean} isImport - Whether calling from the import function or not.
|
||||
* @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.
|
||||
*/
|
||||
mh.addFullMember = async function (authorId, memberName, displayName = null, proxy = null, propic = null, isImport = false) {
|
||||
await mh.getMemberByName(authorId, memberName).then((member) => {
|
||||
if (member) {
|
||||
throw new Error(`Can't add ${memberName}. ${enums.err.MEMBER_EXISTS}`);
|
||||
}
|
||||
});
|
||||
if (displayName) {
|
||||
const trimmedName = displayName ? displayName.trim() : null;
|
||||
if (trimmedName && trimmedName.length > 32) {
|
||||
throw new RangeError(`Can't add ${memberName}. ${enums.err.DISPLAY_NAME_TOO_LONG}`);
|
||||
}
|
||||
}
|
||||
if (proxy) {
|
||||
await mh.checkIfProxyExists(authorId, proxy).catch((e) => {
|
||||
throw e
|
||||
});
|
||||
}
|
||||
let validPropic;
|
||||
if (propic) {
|
||||
validPropic = await mh.checkImageFormatValidity(propic).then((valid) => {
|
||||
return valid;
|
||||
}).catch((e) => {
|
||||
if (!isImport) {
|
||||
throw (e);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
const member = await database.members.create({
|
||||
name: memberName, userid: authorId, displayname: displayName, proxy: proxy, propic: validPropic ? propic : null,
|
||||
});
|
||||
if (!member) {
|
||||
new Error(`${enums.err.ADD_ERROR}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates one fields for a member in the database.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The author of the message
|
||||
* @param {string[]} args - The message arguments
|
||||
* @returns {Promise<string>} A successful update.
|
||||
* @throws {EmptyResultError | Error} When the member is not found, or catchall error.
|
||||
*/
|
||||
mh.updateMemberField = async function (authorId, args) {
|
||||
const memberName = args[0];
|
||||
const columnName = args[1];
|
||||
const value = args[2];
|
||||
let fluxerPropicWarning;
|
||||
|
||||
// indicates that an attachment was uploaded on Fluxer directly
|
||||
if (columnName === "propic" && args[3]) {
|
||||
fluxerPropicWarning = mh.setExpirationWarning(args[3]);
|
||||
}
|
||||
return await database.members.update({[columnName]: value}, {
|
||||
where: {
|
||||
name: {[Op.iLike]: memberName},
|
||||
userid: authorId
|
||||
}
|
||||
}).then(() => {
|
||||
return `Updated ${columnName} for ${memberName} to ${value}${fluxerPropicWarning ?? ''}.`;
|
||||
}).catch(e => {
|
||||
if (e === EmptyResultError) {
|
||||
throw new EmptyResultError(`Can't update ${memberName}. ${enums.err.NO_MEMBER}: ${e.message}`);
|
||||
} else {
|
||||
throw new Error(`Can't update ${memberName}. ${e.message}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the warning for an expiration date.
|
||||
*
|
||||
* @param {string} expirationString - An expiration date string.
|
||||
* @returns {string} A description of the expiration, interpolating the expiration string.
|
||||
*/
|
||||
mh.setExpirationWarning = function (expirationString) {
|
||||
let expirationDate = new Date(expirationString);
|
||||
if (!isNaN(expirationDate.valueOf())) {
|
||||
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`
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the details for a member.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The author of the message
|
||||
* @param {string} memberName - The message arguments
|
||||
* @returns {Promise<EmbedBuilder>} The member's info.
|
||||
*/
|
||||
mh.getMemberInfo = async function (authorId, memberName) {
|
||||
return await mh.getMemberByName(authorId, memberName).then((member) => {
|
||||
if (member) {
|
||||
return new EmbedBuilder()
|
||||
.setTitle(member.name)
|
||||
.setDescription(`Details for ${member.name}`)
|
||||
.addFields({
|
||||
name: 'Display name: ',
|
||||
value: member.displayname ?? 'unset',
|
||||
inline: true
|
||||
}, {name: 'Proxy tag: ', value: member.proxy ?? 'unset', inline: true},)
|
||||
.setImage(member.propic);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all members for an author.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The id of the message author
|
||||
* @param {string} authorName - The id name the message author
|
||||
* @returns {Promise<EmbedBuilder>} The info for all members.
|
||||
* @throws {Error} When there are no members for an author.
|
||||
*/
|
||||
mh.getAllMembersInfo = async function (authorId, authorName) {
|
||||
const members = await mh.getMembersByAuthor(authorId);
|
||||
if (members == null) throw Error(enums.err.USER_NO_MEMBERS);
|
||||
const fields = [...members.entries()].map(([name, member]) => ({
|
||||
name: member.name, value: `(Proxy: \`${member.proxy ?? "unset"}\`)`, inline: true,
|
||||
}));
|
||||
return new EmbedBuilder()
|
||||
.setTitle(`${fields > 25 ? "First 25 m" : "M"}embers for ${authorName}`)
|
||||
.addFields(...fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a member based on the author and proxy tag.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The author of the message.
|
||||
* @param {string} memberName - The member's name.
|
||||
* @returns {Promise<model>} The member object.
|
||||
* @throws { EmptyResultError } When the member is not found.
|
||||
*/
|
||||
mh.getMemberByName = async function (authorId, memberName) {
|
||||
return await database.members.findOne({where: {userid: authorId, name: {[Op.iLike]: memberName}}});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a member based on the author and proxy tag.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The author of the message.
|
||||
* @param {string} memberName - The member's name.
|
||||
* @returns {Promise<string>} The member object.
|
||||
* @throws { EmptyResultError } When the member is not found.
|
||||
*/
|
||||
mh.getProxyByMember = async function (authorId, memberName) {
|
||||
return await mh.getMemberByName(authorId, memberName).then((member) => {
|
||||
if (member) {
|
||||
return member.dataValues.proxy;
|
||||
}
|
||||
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.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The author of the message
|
||||
* @returns {Promise<model[] | null>} The member object array.
|
||||
*/
|
||||
mh.getMembersByAuthor = async function (authorId) {
|
||||
return await database.members.findAll({where: {userid: authorId}});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if proxy exists for a member.
|
||||
*
|
||||
* @param {string} authorId - The author of the message
|
||||
* @param {string} proxy - The proxy tag.
|
||||
* @returns {Promise<boolean> } Whether the proxy exists.
|
||||
* @throws {Error} When an empty proxy was provided, or no proxy exists.
|
||||
*/
|
||||
mh.checkIfProxyExists = async function (authorId, proxy) {
|
||||
if (proxy) {
|
||||
const splitProxy = proxy.trim().split("text");
|
||||
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);
|
||||
|
||||
await mh.getMembersByAuthor(authorId).then((memberList) => {
|
||||
const proxyExists = memberList.some(member => member.proxy === proxy);
|
||||
if (proxyExists) {
|
||||
throw new Error(enums.err.PROXY_EXISTS);
|
||||
}
|
||||
}).catch(e => {
|
||||
throw e
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
export const memberHelper = mh;
|
||||
@@ -1,96 +1,95 @@
|
||||
const {memberHelper} = require('memberHelper.js');
|
||||
const {fs} = require('fs')
|
||||
const {tmp, setGracefulCleanup } = require('tmp')
|
||||
const {enums} = require('../enums.js')
|
||||
const {Message} = require('@fluxerjs/core');
|
||||
import {memberHelper} from "./memberHelper.js";
|
||||
import {enums} from "../enums.js";
|
||||
import tmp, {setGracefulCleanup} from "tmp";
|
||||
import fs from 'fs';
|
||||
import {Message} from "@fluxerjs/core";
|
||||
|
||||
const msgh = {};
|
||||
|
||||
msgh.prefix = "pf;"
|
||||
|
||||
setGracefulCleanup();
|
||||
|
||||
const messageHelper = {
|
||||
/**
|
||||
* Parses and slices up message arguments, retaining quoted strings.
|
||||
*
|
||||
* @param {string} content - The full message content.
|
||||
* @param {string} commandName - The command name.
|
||||
* @returns {string[]} An array of arguments.
|
||||
*/
|
||||
msgh.parseCommandArgs = function(content, commandName) {
|
||||
const message = content.slice(msgh.prefix.length + commandName.length).trim();
|
||||
|
||||
prefix: "pf;",
|
||||
|
||||
/**
|
||||
* Parses and slices up message arguments, retaining quoted strings.
|
||||
*
|
||||
* @param {string} content - The full message content.
|
||||
* @param {string} commandName - The command name.
|
||||
* @returns {string[]} An array of arguments.
|
||||
*/
|
||||
parseCommandArgs(content, commandName) {
|
||||
const message = content.slice(this.prefix.length + commandName.length).trim();
|
||||
|
||||
return message.match(/\\?.|^$/g).reduce((accumulator, chara) => {
|
||||
if (chara === '"') {
|
||||
// checks whether string is within quotes or not
|
||||
accumulator.quote ^= 1;
|
||||
} else if (!accumulator.quote && chara === ' ') {
|
||||
// if not currently in quoted string, push empty string to start word
|
||||
accumulator.array.push('');
|
||||
} else {
|
||||
// accumulates characters to the last string in the array and removes escape characters
|
||||
accumulator.array[accumulator.array.length - 1] += chara.replace(/\\(.)/, "$1");
|
||||
}
|
||||
return accumulator;
|
||||
}, {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.
|
||||
*
|
||||
* @param {string} authorId - The author of the message.
|
||||
* @param {string} content - The full message content
|
||||
* @param {string | null} attachmentUrl - The url for an attachment to the message, if any exists.
|
||||
* @returns {Object} The proxy message object.
|
||||
* @throws {Error} If a proxy message is sent with no message within it.
|
||||
*/
|
||||
async parseProxyTags(authorId, content, attachmentUrl = null) {
|
||||
const members = await memberHelper.getMembersByAuthor(authorId);
|
||||
// If an author has no members, no sense in searching for proxy
|
||||
if (members.length === 0) {
|
||||
return;
|
||||
return message.match(/\\?.|^$/g).reduce((accumulator, chara) => {
|
||||
if (chara === '"') {
|
||||
// checks whether string is within quotes or not
|
||||
accumulator.quote ^= 1;
|
||||
} else if (!accumulator.quote && chara === ' '){
|
||||
// if not currently in quoted string, push empty string to start word
|
||||
accumulator.array.push('');
|
||||
} else {
|
||||
// accumulates characters to the last string in the array and removes escape characters
|
||||
accumulator.array[accumulator.array.length-1] += chara.replace(/\\(.)/,"$1");
|
||||
}
|
||||
return accumulator;
|
||||
}, {array: ['']}).array // initial array with empty string for the reducer
|
||||
}
|
||||
|
||||
const proxyMessage = {}
|
||||
members.forEach(member => {
|
||||
if (member.proxy) {
|
||||
const splitProxy = member.proxy.split("text");
|
||||
if (content.startsWith(splitProxy[0]) && content.endsWith(splitProxy[1])) {
|
||||
proxyMessage.member = member;
|
||||
if (attachmentUrl) return proxyMessage.message = enums.misc.ATTACHMENT_SENT_BY;
|
||||
|
||||
let escapedPrefix = splitProxy[0].replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
let escapedSuffix = splitProxy[1].replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
escapedPrefix = new RegExp("^" + escapedPrefix);
|
||||
escapedSuffix = new RegExp(escapedSuffix + "$")
|
||||
proxyMessage.message = content.replace(escapedPrefix, "").replace(escapedSuffix, "");
|
||||
if (proxyMessage.message.length === 0) throw new Error(enums.err.NO_MESSAGE_SENT_WITH_PROXY);
|
||||
}
|
||||
}
|
||||
})
|
||||
return proxyMessage;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sends a message as an attachment if it's too long.NOT CURRENTLY IN USE
|
||||
*
|
||||
* @async
|
||||
* @param {string} text - The text of the message.
|
||||
* @param {Message} message - The message object.
|
||||
* @throws {Error} If a proxy message is sent with no message within it.
|
||||
*
|
||||
*/
|
||||
async sendMessageAsAttachment(text, message) {
|
||||
if (text.length > 2000) {
|
||||
tmp.file(async (err, path, fd, cleanupCallback) => {
|
||||
fs.writeFile(path, text, (err) => {
|
||||
if (err) throw err;
|
||||
})
|
||||
if (err) throw err;
|
||||
await message.reply({content: enums.err.IMPORT_ERROR, attachments: [path]});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Parses messages to see if any part of the text matches the tags of any member belonging to an author.
|
||||
*
|
||||
* @param {string} authorId - The author of the message.
|
||||
* @param {string} content - The full message content
|
||||
* @param {string | null} attachmentUrl - The url for an attachment to the message, if any exists.
|
||||
* @returns {Object} The proxy message object.
|
||||
* @throws {Error} If a proxy message is sent with no message within it.
|
||||
*/
|
||||
msgh.parseProxyTags = async function (authorId, content, attachmentUrl= null){
|
||||
const members = await memberHelper.getMembersByAuthor(authorId);
|
||||
// If an author has no members, no sense in searching for proxy
|
||||
if (members.length === 0) {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = messageHelper;
|
||||
const proxyMessage = {}
|
||||
members.forEach(member => {
|
||||
if (member.proxy) {
|
||||
const splitProxy = member.proxy.split("text");
|
||||
if(content.startsWith(splitProxy[0]) && content.endsWith(splitProxy[1])) {
|
||||
proxyMessage.member = member;
|
||||
if (attachmentUrl) return proxyMessage.message = enums.misc.ATTACHMENT_SENT_BY;
|
||||
|
||||
let escapedPrefix = splitProxy[0].replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
let escapedSuffix = splitProxy[1].replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
escapedPrefix = new RegExp("^" + escapedPrefix);
|
||||
escapedSuffix = new RegExp(escapedSuffix + "$")
|
||||
proxyMessage.message = content.replace(escapedPrefix, "").replace(escapedSuffix, "");
|
||||
if (proxyMessage.message.length === 0) throw new Error(enums.err.NO_MESSAGE_SENT_WITH_PROXY);
|
||||
}
|
||||
}
|
||||
})
|
||||
return proxyMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message as an attachment if it's too long.NOT CURRENTLY IN USE
|
||||
*
|
||||
* @async
|
||||
* @param {string} text - The text of the message.
|
||||
* @param {Message} message - The message object.
|
||||
* @throws {Error} If a proxy message is sent with no message within it.
|
||||
*
|
||||
*/
|
||||
msgh.sendMessageAsAttachment = async function(text, message) {
|
||||
if (text.length > 2000) {
|
||||
tmp.file(async (err, path, fd, cleanupCallback) => {
|
||||
fs.writeFile(path, text, (err) => {
|
||||
if (err) throw err;
|
||||
})
|
||||
if (err) throw err;
|
||||
await message.reply({content: enums.err.IMPORT_ERROR, attachments: [path]});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const messageHelper = msgh;
|
||||
|
||||
@@ -1,101 +1,93 @@
|
||||
const {messageHelper} = require('messageHelper.js');
|
||||
const {enums} = require('../enums.js');
|
||||
const {Client, Message, Webhook, Channel} = require('@fluxerjs/core');
|
||||
import {messageHelper} from "./messageHelper.js";
|
||||
import {Webhook, Channel, Message} from '@fluxerjs/core';
|
||||
import {enums} from "../enums.js";
|
||||
|
||||
const wh = {};
|
||||
|
||||
const name = 'PluralFlux Proxy Webhook';
|
||||
|
||||
const webhookHelper = {
|
||||
/**
|
||||
* Replaces a proxied message with a webhook using the member information.
|
||||
* @param {Client} client - The fluxer.js client.
|
||||
* @param {Message} message - The full message object.
|
||||
* @throws {Error} When the proxy message is not in a server.
|
||||
*/
|
||||
async sendMessageAsMember(client, message) {
|
||||
const attachmentUrl = message.attachments.size > 0 ? message.attachments.first().url : null;
|
||||
const proxyMatch = await messageHelper.parseProxyTags(message.author.id, message.content, attachmentUrl).catch(e => {
|
||||
throw e
|
||||
});
|
||||
// If the message doesn't match a proxy, just return.
|
||||
if (!proxyMatch.member) {
|
||||
return;
|
||||
}
|
||||
// If the message does match a proxy but is not in a guild server (ex: in the Bot's DMs
|
||||
if (!message.guildId) {
|
||||
throw new Error(enums.err.NOT_IN_SERVER);
|
||||
}
|
||||
/**
|
||||
* Replaces a proxied message with a webhook using the member information.
|
||||
* @param {Client} client - The fluxer.js client.
|
||||
* @param {Message} message - The full message object.
|
||||
* @throws {Error} When the proxy message is not in a server.
|
||||
*/
|
||||
wh.sendMessageAsMember = async function(client, message) {
|
||||
const attachmentUrl = message.attachments.size > 0 ? message.attachments.first().url : null;
|
||||
const proxyMatch = await messageHelper.parseProxyTags(message.author.id, message.content, attachmentUrl).catch(e =>{throw e});
|
||||
// If the message doesn't match a proxy, just return.
|
||||
if (!proxyMatch.member) {
|
||||
return;
|
||||
}
|
||||
// If the message does match a proxy but is not in a guild server (ex: in the Bot's DMs
|
||||
if (!message.guildId) {
|
||||
throw new Error(enums.err.NOT_IN_SERVER);
|
||||
}
|
||||
|
||||
if (proxyMatch.message === enums.misc.ATTACHMENT_SENT_BY) {
|
||||
return await message.reply(`${enums.misc.ATTACHMENT_SENT_BY} ${proxyMatch.member.displayname}`)
|
||||
}
|
||||
await this.replaceMessage(client, message, proxyMatch.message, proxyMatch.member).catch(e => {
|
||||
throw e
|
||||
});
|
||||
},
|
||||
if (proxyMatch.message === enums.misc.ATTACHMENT_SENT_BY) {
|
||||
return await message.reply(`${enums.misc.ATTACHMENT_SENT_BY} ${proxyMatch.member.displayname}`)
|
||||
}
|
||||
await replaceMessage(client, message, proxyMatch.message, proxyMatch.member).catch(e =>{throw e});
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces a proxied message with a webhook using the member information.
|
||||
* @param {Client} client - The fluxer.js client.
|
||||
* @param {Message} message - The message to be deleted.
|
||||
* @param {string} text - The text to send via the webhook.
|
||||
* @param {model} member - A member object from the database.
|
||||
* @throws {Error} When there's no message to send.
|
||||
*/
|
||||
async replaceMessage(client, message, text, member) {
|
||||
if (text.length > 0 || message.attachments.size > 0) {
|
||||
const channel = client.channels.get(message.channelId);
|
||||
const webhook = await this.getOrCreateWebhook(client, channel).catch((e) => {
|
||||
throw e
|
||||
});
|
||||
const username = member.displayname ?? member.name;
|
||||
await webhook.send({content: text, username: username, avatar_url: member.propic});
|
||||
await message.delete();
|
||||
} else {
|
||||
throw new Error(enums.err.NO_MESSAGE_SENT_WITH_PROXY);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets or creates a webhook.
|
||||
*
|
||||
* @param {Client} client - The fluxer.js client.
|
||||
* @param {Channel} channel - The channel the message was sent in.
|
||||
* @returns {Webhook} A webhook object.
|
||||
* @throws {Error} When no webhooks are allowed in the channel.
|
||||
*/
|
||||
async getOrCreateWebhook(client, channel) {
|
||||
// If channel doesn't allow webhooks
|
||||
if (!channel?.createWebhook) throw new Error(enums.err.NO_WEBHOOKS_ALLOWED);
|
||||
let webhook = await this.getWebhook(client, channel).catch((e) => {
|
||||
throw e
|
||||
});
|
||||
if (!webhook) {
|
||||
webhook = await channel.createWebhook({name: name});
|
||||
}
|
||||
return webhook;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets an existing webhook.
|
||||
*
|
||||
* @param {Client} client - The fluxer.js client.
|
||||
* @param {Channel} channel - The channel the message was sent in.
|
||||
* @returns {Webhook} A webhook object.
|
||||
*/
|
||||
async getWebhook(client, channel) {
|
||||
const channelWebhooks = await channel?.fetchWebhooks() ?? [];
|
||||
if (channelWebhooks.length === 0) {
|
||||
return;
|
||||
}
|
||||
let pf_webhook;
|
||||
channelWebhooks.forEach((webhook) => {
|
||||
if (webhook.name === name) {
|
||||
pf_webhook = webhook;
|
||||
}
|
||||
})
|
||||
return pf_webhook;
|
||||
/**
|
||||
* Replaces a proxied message with a webhook using the member information.
|
||||
* @param {Client} client - The fluxer.js client.
|
||||
* @param {Message} message - The message to be deleted.
|
||||
* @param {string} text - The text to send via the webhook.
|
||||
* @param {model} member - A member object from the database.
|
||||
* @throws {Error} When there's no message to send.
|
||||
*/
|
||||
async function replaceMessage(client, message, text, member) {
|
||||
if (text.length > 0 || message.attachments.size > 0) {
|
||||
const channel = client.channels.get(message.channelId);
|
||||
const webhook = await getOrCreateWebhook(client, channel).catch((e) =>{throw e});
|
||||
const username = member.displayname ?? member.name;
|
||||
await webhook.send({content: text, username: username, avatar_url: member.propic});
|
||||
await message.delete();
|
||||
}
|
||||
else {
|
||||
throw new Error(enums.err.NO_MESSAGE_SENT_WITH_PROXY);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets or creates a webhook.
|
||||
*
|
||||
* @param {Client} client - The fluxer.js client.
|
||||
* @param {Channel} channel - The channel the message was sent in.
|
||||
* @returns {Webhook} A webhook object.
|
||||
* @throws {Error} When no webhooks are allowed in the channel.
|
||||
*/
|
||||
async function getOrCreateWebhook(client, channel) {
|
||||
// If channel doesn't allow webhooks
|
||||
if (!channel?.createWebhook) throw new Error(enums.err.NO_WEBHOOKS_ALLOWED);
|
||||
let webhook = await getWebhook(client, channel).catch((e) =>{throw e});
|
||||
if (!webhook) {
|
||||
webhook = await channel.createWebhook({name: name});
|
||||
}
|
||||
return webhook;
|
||||
}
|
||||
|
||||
module.exports = webhookHelper;
|
||||
/**
|
||||
* Gets an existing webhook.
|
||||
*
|
||||
* @param {Client} client - The fluxer.js client.
|
||||
* @param {Channel} channel - The channel the message was sent in.
|
||||
* @returns {Webhook} A webhook object.
|
||||
*/
|
||||
async function getWebhook(client, channel) {
|
||||
const channelWebhooks = await channel?.fetchWebhooks() ?? [];
|
||||
if (channelWebhooks.length === 0) {
|
||||
return;
|
||||
}
|
||||
let pf_webhook;
|
||||
channelWebhooks.forEach((webhook) => {
|
||||
if (webhook.name === name) {
|
||||
pf_webhook = webhook;
|
||||
}
|
||||
})
|
||||
return pf_webhook;
|
||||
}
|
||||
|
||||
export const webhookHelper = wh;
|
||||
@@ -1,22 +1,22 @@
|
||||
const {enums} = require("../enums.js");
|
||||
const {memberHelper} = require("memberHelper.js");
|
||||
import {enums} from "./enums.js";
|
||||
import {memberHelper} from "./helpers/memberHelper.js";
|
||||
|
||||
const importHelper = {
|
||||
const ih = {};
|
||||
|
||||
/**
|
||||
* Tries to import from Pluralkit.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The author of the message
|
||||
* @param {string} attachmentUrl - The attached JSON url.
|
||||
* @returns {string} A successful addition of all members.
|
||||
* @throws {Error} When the member exists, or creating a member doesn't work.
|
||||
*/
|
||||
async pluralKitImport(authorId, attachmentUrl) {
|
||||
if (!attachmentUrl) {
|
||||
throw new Error(enums.err.NOT_JSON_FILE);
|
||||
}
|
||||
return fetch(attachmentUrl).then((res) => res.json()).then(async (pkData) => {
|
||||
/**
|
||||
* Tries to import from Pluralkit.
|
||||
*
|
||||
* @async
|
||||
* @param {string} authorId - The author of the message
|
||||
* @param {string} attachmentUrl - The attached JSON url.
|
||||
* @returns {string} A successful addition of all members.
|
||||
* @throws {Error} When the member exists, or creating a member doesn't work.
|
||||
*/
|
||||
ih.pluralKitImport = async function (authorId, attachmentUrl) {
|
||||
if (!attachmentUrl) {
|
||||
throw new Error(enums.err.NOT_JSON_FILE);
|
||||
}
|
||||
return fetch(attachmentUrl).then((res) => res.json()).then(async(pkData) => {
|
||||
const pkMembers = pkData.members;
|
||||
const errors = [];
|
||||
const addedMembers = [];
|
||||
@@ -28,8 +28,7 @@ const importHelper = {
|
||||
errors.push(`${pkMember.name}: ${e.message}`);
|
||||
});
|
||||
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;
|
||||
if (errors.length > 0) {
|
||||
@@ -37,7 +36,6 @@ const importHelper = {
|
||||
}
|
||||
return aggregatedText;
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = importHelper;
|
||||
export const importHelper = ih;
|
||||
Reference in New Issue
Block a user