forked from PluralFlux/PluralFlux
Compare commits
2 Commits
LaikaBzko-
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| c2a88804ad | |||
| 2b31cc2ae9 |
49
.gitea/workflows/build-dev.yml
Normal file
49
.gitea/workflows/build-dev.yml
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
name: Build Dev instance
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: ["develop", "Develop"]
|
||||||
|
pull_request:
|
||||||
|
branches: ["develop", "Develop"]
|
||||||
|
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Docker BuildX
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: login to gitea registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ gitea.server_url }}
|
||||||
|
username: ${{ gitea.actor }}
|
||||||
|
password: ${{ secrets.GITEA }}
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
engineering.sanya.gay/pluralflux/pluralflux-dev:latest
|
||||||
|
|
||||||
|
- name: Deploy bot
|
||||||
|
uses: appleboy/ssh-action@v1.0.3
|
||||||
|
with:
|
||||||
|
host: ${{ secrets.SSH_HOST }}
|
||||||
|
username: ${{ secrets.SSH_USER }}
|
||||||
|
key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||||
|
port: 22
|
||||||
|
script: |
|
||||||
|
cd ${{ secrets.BOT_DIRECTORY }}
|
||||||
|
docker compose pull
|
||||||
|
docker compose up -d pluralflux-dev
|
||||||
49
.gitea/workflows/build-main.yml
Normal file
49
.gitea/workflows/build-main.yml
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
name: nodeJS remote worker
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: ["main"]
|
||||||
|
pull_request:
|
||||||
|
branches: ["main"]
|
||||||
|
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Docker BuildX
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: login to gitea registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ gitea.server_url }}
|
||||||
|
username: ${{ gitea.actor }}
|
||||||
|
password: ${{ secrets.GITEA }}
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
engineering.sanya.gay/pluralflux/pluralflux:latest
|
||||||
|
|
||||||
|
- name: Deploy bot
|
||||||
|
uses: appleboy/ssh-action@v1.0.3
|
||||||
|
with:
|
||||||
|
host: ${{ secrets.SSH_HOST }}
|
||||||
|
username: ${{ secrets.SSH_USER }}
|
||||||
|
key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||||
|
port: 22
|
||||||
|
script: |
|
||||||
|
cd ${{ secrets.BOT_DIRECTORY }}
|
||||||
|
docker compose pull
|
||||||
|
docker compose up -d pluralflux-prod
|
||||||
26
.gitea/workflows/sync-from-mirror.yaml
Normal file
26
.gitea/workflows/sync-from-mirror.yaml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
name: Auto-Sync from Mirror
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
repository: "Pluralflux/Pluralflux"
|
||||||
|
branches: [main,develop]
|
||||||
|
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
sync:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout Fork
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
token: ${{ secrets.GITEA_TOKEN }}
|
||||||
|
|
||||||
|
- name: Pull from Mirror
|
||||||
|
run: |
|
||||||
|
git remote add upstream https://engineering.sanya.gay/PluralFlux/PluralFlux.git
|
||||||
|
git fetch upstream --prune
|
||||||
|
git reset --hard origin/main
|
||||||
|
git push origin "refs/remotes/upstream/*:refs/heads/*" --force-with-lease
|
||||||
|
git merge upstream/main -m "Syncing from github"
|
||||||
|
git push origin main
|
||||||
11
.gitignore
vendored
11
.gitignore
vendored
@@ -1,8 +1,13 @@
|
|||||||
node_modules
|
node_modules/
|
||||||
|
build/
|
||||||
|
tmp/
|
||||||
|
temp/
|
||||||
.idea
|
.idea
|
||||||
secrets/
|
secrets/
|
||||||
config.json
|
|
||||||
coverage
|
coverage
|
||||||
|
config.json
|
||||||
log.txt
|
log.txt
|
||||||
.env
|
.env
|
||||||
oya.png
|
oya.png
|
||||||
|
variables.env
|
||||||
|
.env.production
|
||||||
@@ -7,4 +7,4 @@ FROM node:20-alpine
|
|||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=builder /app/node_modules ./node_modules
|
COPY --from=builder /app/node_modules ./node_modules
|
||||||
COPY . .
|
COPY . .
|
||||||
CMD ["node", "src/bot.js"]
|
CMD ["npm", "start"]
|
||||||
@@ -7,8 +7,6 @@ PluralFlux is a proxybot akin to PluralKit and Tupperbox, but for [Fluxer](https
|
|||||||
|
|
||||||
[Sponsor the project](https://github.com/sponsors/pieartsy)
|
[Sponsor the project](https://github.com/sponsors/pieartsy)
|
||||||
|
|
||||||
If it's not running at the moment, it's because my computer crashed or something. I'm looking to move running it to a somewhat more permanent solution.
|
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
All commands are prefixed by `pf;`. Currently only a few are implemented.
|
All commands are prefixed by `pf;`. Currently only a few are implemented.
|
||||||
|
|
||||||
|
|||||||
36
compose.yaml
36
compose.yaml
@@ -1,46 +1,26 @@
|
|||||||
services:
|
services:
|
||||||
main:
|
main:
|
||||||
build: .
|
image: engineering.sanya.gay/pluralflux/pluralflux
|
||||||
container_name: pluralflux
|
container_name: pluralflux
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
networks:
|
env_file: "variables.env"
|
||||||
- pluralflux-net
|
|
||||||
postgres:
|
postgres:
|
||||||
image: postgres:latest
|
image: postgres:latest
|
||||||
container_name: pluralflux-postgres
|
env_file: "variables.env"
|
||||||
environment:
|
|
||||||
POSTGRES_PASSWORD_FILE: /run/secrets/postgres_pwd
|
|
||||||
secrets:
|
|
||||||
- postgres_pwd
|
|
||||||
volumes:
|
volumes:
|
||||||
- pgdata:/var/lib/postgresql
|
- pgdata:/var/lib/postgresql
|
||||||
|
- ./pgBackup:/mnt/pgBackup
|
||||||
ports:
|
ports:
|
||||||
- "5432:5432"
|
- "5432:5432"
|
||||||
networks:
|
|
||||||
- pluralflux-net
|
|
||||||
pgadmin:
|
pgadmin:
|
||||||
image: dpage/pgadmin4:latest
|
image: dpage/pgadmin4:latest
|
||||||
container_name: pluralflux-pgadmin
|
|
||||||
ports:
|
ports:
|
||||||
- "5050:80"
|
- "5050:80"
|
||||||
environment:
|
env_file: "variables.env"
|
||||||
PGADMIN_DEFAULT_EMAIL: code@asterfialla.com
|
|
||||||
PGADMIN_DEFAULT_PASSWORD_FILE: /run/secrets/postgres_pwd
|
|
||||||
PGADMIN_CONFIG_SERVER_MODE: 'False'
|
|
||||||
PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED: 'False'
|
|
||||||
secrets:
|
|
||||||
- postgres_pwd
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- postgres
|
- postgres
|
||||||
networks:
|
volumes:
|
||||||
- pluralflux-net
|
- pgadmindata:/var/lib/pgadmin
|
||||||
|
|
||||||
networks:
|
|
||||||
pluralflux-net:
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
pgdata:
|
pgdata:
|
||||||
|
pgadmindata:
|
||||||
secrets:
|
|
||||||
postgres_pwd:
|
|
||||||
file: ./secrets/postgres-password.txt
|
|
||||||
26
database/data-source.ts
Normal file
26
database/data-source.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import "reflect-metadata"
|
||||||
|
import { DataSource } from "typeorm"
|
||||||
|
import * as env from 'dotenv';
|
||||||
|
import * as path from "path";
|
||||||
|
|
||||||
|
env.config();
|
||||||
|
|
||||||
|
export const AppDataSource = new DataSource({
|
||||||
|
type: "postgres",
|
||||||
|
host: process.env.POSTGRES_ENDPOINT,
|
||||||
|
port: 5432,
|
||||||
|
username: "postgres",
|
||||||
|
password: process.env.POSTGRES_PASSWORD,
|
||||||
|
database: "postgres",
|
||||||
|
synchronize: false,
|
||||||
|
logging: false,
|
||||||
|
entities: [path.join(__dirname, "./entity/*.{ts,js}")],
|
||||||
|
migrations: [path.join(__dirname, "./migrations/*.{ts,js}")],
|
||||||
|
migrationsRun: true,
|
||||||
|
migrationsTableName: 'migrations',
|
||||||
|
migrationsTransactionMode: 'all',
|
||||||
|
invalidWhereValuesBehavior: {
|
||||||
|
null: "sql-null",
|
||||||
|
undefined: "throw",
|
||||||
|
},
|
||||||
|
});
|
||||||
40
database/entity/Member.ts
Normal file
40
database/entity/Member.ts
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import {Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, Unique} from "typeorm"
|
||||||
|
|
||||||
|
@Entity({name: "Member", synchronize: true})
|
||||||
|
@Unique("UQ_Member_userid_name", ['userid', 'name'])
|
||||||
|
export class Member {
|
||||||
|
|
||||||
|
@PrimaryGeneratedColumn()
|
||||||
|
id: number
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
userid: string
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
length: 100
|
||||||
|
})
|
||||||
|
name: string
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: "varchar",
|
||||||
|
nullable: true,
|
||||||
|
length: 100
|
||||||
|
})
|
||||||
|
displayname: string
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
proxy: string
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
propic: string
|
||||||
|
|
||||||
|
@CreateDateColumn({ type: 'timestamptz' })
|
||||||
|
createdAt: Date
|
||||||
|
|
||||||
|
@UpdateDateColumn({ type: 'timestamptz' })
|
||||||
|
updatedAt: Date
|
||||||
|
}
|
||||||
14
database/migrations/1772417745487-update.ts
Normal file
14
database/migrations/1772417745487-update.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class Update1772417745487 implements MigrationInterface {
|
||||||
|
name = 'Update1772417745487'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`CREATE TABLE "Member" ("id" SERIAL NOT NULL, "userid" character varying NOT NULL, "name" character varying(100) NOT NULL, "displayname" character varying(100), "proxy" character varying, "propic" character varying, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), CONSTRAINT "PK_235428a1d87c5f639ef7b7cf170" PRIMARY KEY ("id"))`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`DROP TABLE "Member"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
12
database/migrations/1772419448503-add-data.ts
Normal file
12
database/migrations/1772419448503-add-data.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class AddData1772419448503 implements MigrationInterface {
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`INSERT INTO "Member"(id, userid, name,displayname, proxy, propic, "createdAt", "updatedAt") SELECT id,userid, name,displayname, proxy, propic, "createdAt", "updatedAt" FROM "Members";`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`TRUNCATE TABLE "Member"`);
|
||||||
|
}
|
||||||
|
}
|
||||||
17
database/migrations/1772825438973-delete-duplicates.ts
Normal file
17
database/migrations/1772825438973-delete-duplicates.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class DeleteDuplicates1772825438973 implements MigrationInterface {
|
||||||
|
name= "DeleteDuplicates1772825438973"
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`DELETE
|
||||||
|
FROM "Member" a USING "Member" b
|
||||||
|
WHERE a.id
|
||||||
|
> b.id
|
||||||
|
AND a.name = b.name
|
||||||
|
AND a.userid = b.userid;`)
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
14
database/migrations/1772830252670-update.ts
Normal file
14
database/migrations/1772830252670-update.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class Update1772830252670 implements MigrationInterface {
|
||||||
|
name = 'Update1772830252670'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "Member" ADD CONSTRAINT "UQ_Member_userid_name" UNIQUE ("userid", "name")`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "Member" DROP CONSTRAINT "UQ_Member_userid_name"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
1961
package-lock.json
generated
1961
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
20
package.json
20
package.json
@@ -7,26 +7,36 @@
|
|||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/pieartsy/PluralFlux.git"
|
"url": "https://github.com/pieartsy/PluralFlux.git"
|
||||||
},
|
},
|
||||||
|
"type": "commonjs",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fluxerjs/core": "^1.2.2",
|
"@fluxerjs/core": "^1.2.2",
|
||||||
"dotenv": "^17.3.1",
|
"dotenv": "^17.3.1",
|
||||||
"pg": "^8.18.0",
|
"pg": "^8.19.0",
|
||||||
"pg-hstore": "^2.3.4",
|
"pg-hstore": "^2.3.4",
|
||||||
"pm2": "^6.0.14",
|
"pm2": "^6.0.14",
|
||||||
"sequelize": "^6.37.7",
|
"psql": "^0.0.1",
|
||||||
"tmp": "^0.2.5"
|
"reflect-metadata": "^0.2.2",
|
||||||
|
"tmp": "^0.2.5",
|
||||||
|
"typeorm": "^0.3.28"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.29.0",
|
"@babel/core": "^7.29.0",
|
||||||
"@babel/plugin-transform-modules-commonjs": "^7.28.6",
|
"@babel/plugin-transform-modules-commonjs": "^7.28.6",
|
||||||
"@babel/preset-env": "^7.29.0",
|
"@babel/preset-env": "^7.29.0",
|
||||||
"@fetch-mock/jest": "^0.2.20",
|
"@fetch-mock/jest": "^0.2.20",
|
||||||
|
"@types/node": "^25.3.3",
|
||||||
"babel-jest": "^30.2.0",
|
"babel-jest": "^30.2.0",
|
||||||
"fetch-mock": "^12.6.0",
|
"fetch-mock": "^12.6.0",
|
||||||
"jest": "^30.2.0"
|
"jest": "^30.2.0",
|
||||||
|
"ts-node": "^10.9.2",
|
||||||
|
"typescript": "^5.9.3"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "jest"
|
"test": "jest",
|
||||||
|
"start": "ts-node src/bot.js",
|
||||||
|
"new-migration": "typeorm-ts-node-commonjs migration:create database/migrations/update",
|
||||||
|
"generate-db": "typeorm-ts-node-commonjs migration:generate -d database/data-source.ts database/migrations/update",
|
||||||
|
"run-migration": "typeorm-ts-node-commonjs migration:run -d database/data-source.ts"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
35
src/bot.js
35
src/bot.js
@@ -1,12 +1,13 @@
|
|||||||
import { Client, Events, Message } from '@fluxerjs/core';
|
const {Client, Events, Message} = require('@fluxerjs/core');
|
||||||
import { messageHelper } from "./helpers/messageHelper.js";
|
const {messageHelper} = require("./helpers/messageHelper.js");
|
||||||
import {enums} from "./enums.js";
|
const {enums} = require("./enums.js");
|
||||||
import {commands} from "./commands.js";
|
const {commands} = require("./commands.js");
|
||||||
import {webhookHelper} from "./helpers/webhookHelper.js";
|
const {webhookHelper} = require("./helpers/webhookHelper.js");
|
||||||
import env from 'dotenv';
|
const env = require('dotenv');
|
||||||
import {utils} from "./helpers/utils.js";
|
const {utils} = require("./helpers/utils.js");
|
||||||
|
const { AppDataSource } = require("../database/data-source");
|
||||||
|
|
||||||
env.config({path: './.env'});
|
env.config();
|
||||||
|
|
||||||
const token = process.env.FLUXER_BOT_TOKEN;
|
const token = process.env.FLUXER_BOT_TOKEN;
|
||||||
|
|
||||||
@@ -15,10 +16,12 @@ if (!token) {
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const client = new Client({ intents: 0 });
|
client = new Client({ intents: 0 });
|
||||||
|
|
||||||
|
module.exports.client = client;
|
||||||
|
|
||||||
client.on(Events.MessageCreate, async (message) => {
|
client.on(Events.MessageCreate, async (message) => {
|
||||||
await handleMessageCreate(message);
|
await module.exports.handleMessageCreate(message);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,7 +31,7 @@ client.on(Events.MessageCreate, async (message) => {
|
|||||||
* @param {Message} message - The message object
|
* @param {Message} message - The message object
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
export const handleMessageCreate = async function(message) {
|
module.exports.handleMessageCreate = async function(message) {
|
||||||
try {
|
try {
|
||||||
// Ignore bots
|
// Ignore bots
|
||||||
if (message.author.bot) return;
|
if (message.author.bot) return;
|
||||||
@@ -79,12 +82,14 @@ function printGuilds() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const debouncePrintGuilds = utils.debounce(printGuilds, 2000);
|
const debouncePrintGuilds = utils.debounce(printGuilds, 2000);
|
||||||
export const debounceLogin = utils.debounce(client.login, 60000);
|
// export const debounceLogin = utils.debounce(client.login, 60000);
|
||||||
|
|
||||||
export const login = async function() {
|
module.exports.login = async function() {
|
||||||
try {
|
try {
|
||||||
|
if (!AppDataSource.isInitialized) {
|
||||||
|
await AppDataSource.initialize();
|
||||||
|
}
|
||||||
await client.login(token);
|
await client.login(token);
|
||||||
// await db.check_connection();
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Login failed:', err);
|
console.error('Login failed:', err);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
@@ -93,7 +98,7 @@ export const login = async function() {
|
|||||||
|
|
||||||
function main()
|
function main()
|
||||||
{
|
{
|
||||||
login();
|
exports.login();
|
||||||
}
|
}
|
||||||
|
|
||||||
main();
|
main();
|
||||||
@@ -1,20 +1,20 @@
|
|||||||
import {messageHelper} from "./helpers/messageHelper.js";
|
const {messageHelper} = require("./helpers/messageHelper.js");
|
||||||
import {enums} from "./enums.js";
|
const {enums} = require("./enums.js");
|
||||||
import {memberHelper} from "./helpers/memberHelper.js";
|
const {memberHelper} = require("./helpers/memberHelper.js");
|
||||||
import {EmbedBuilder} from "@fluxerjs/core";
|
const {EmbedBuilder} = require("@fluxerjs/core");
|
||||||
import {importHelper} from "./helpers/importHelper.js";
|
const {importHelper} = require("./helpers/importHelper.js");
|
||||||
|
|
||||||
const cmds = {
|
const commands = {
|
||||||
commandsMap: new Map(),
|
commandsMap: new Map(),
|
||||||
aliasesMap: new Map()
|
aliasesMap: new Map()
|
||||||
};
|
};
|
||||||
|
|
||||||
cmds.aliasesMap.set('m', {command: 'member'})
|
commands.aliasesMap.set('m', {command: 'member'})
|
||||||
|
|
||||||
cmds.commandsMap.set('member', {
|
commands.commandsMap.set('member', {
|
||||||
description: enums.help.SHORT_DESC_MEMBER,
|
description: enums.help.SHORT_DESC_MEMBER,
|
||||||
async execute(message, args) {
|
async execute(message, args) {
|
||||||
await cmds.memberCommand(message, args)
|
await commands.memberCommand(message, args)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ cmds.commandsMap.set('member', {
|
|||||||
* @param {string[]} args - The parsed arguments
|
* @param {string[]} args - The parsed arguments
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
cmds.memberCommand = async function (message, args) {
|
commands.memberCommand = async function (message, args) {
|
||||||
const authorFull = `${message.author.username}#${message.author.discriminator}`
|
const authorFull = `${message.author.username}#${message.author.discriminator}`
|
||||||
const attachmentUrl = message.attachments.size > 0 ? message.attachments.first().url : null;
|
const attachmentUrl = message.attachments.size > 0 ? message.attachments.first().url : null;
|
||||||
const attachmentExpires = message.attachments.size > 0 ? message.attachments.first().expires_at : null;
|
const attachmentExpires = message.attachments.size > 0 ? message.attachments.first().expires_at : null;
|
||||||
@@ -53,10 +53,10 @@ cmds.memberCommand = async function (message, args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cmds.commandsMap.set('help', {
|
commands.commandsMap.set('help', {
|
||||||
description: enums.help.SHORT_DESC_HELP,
|
description: enums.help.SHORT_DESC_HELP,
|
||||||
async execute(message) {
|
async execute(message) {
|
||||||
const fields = [...cmds.commandsMap.entries()].map(([name, cmd]) => ({
|
const fields = [...commands.commandsMap.entries()].map(([name, cmd]) => ({
|
||||||
name: `${messageHelper.prefix}${name}`,
|
name: `${messageHelper.prefix}${name}`,
|
||||||
value: cmd.description,
|
value: cmd.description,
|
||||||
inline: true,
|
inline: true,
|
||||||
@@ -73,10 +73,10 @@ cmds.commandsMap.set('help', {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
cmds.commandsMap.set('import', {
|
commands.commandsMap.set('import', {
|
||||||
description: enums.help.SHORT_DESC_IMPORT,
|
description: enums.help.SHORT_DESC_IMPORT,
|
||||||
async execute(message, args) {
|
async execute(message, args) {
|
||||||
await cmds.importCommand(message, args);
|
await commands.importCommand(message, args);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ cmds.commandsMap.set('import', {
|
|||||||
* @param {string[]} args - The parsed arguments
|
* @param {string[]} args - The parsed arguments
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
cmds.importCommand = async function (message, args) {
|
commands.importCommand = async function (message, args) {
|
||||||
const attachmentUrl = message.attachments.size > 0 ? message.attachments.first().url : null;
|
const attachmentUrl = message.attachments.size > 0 ? message.attachments.first().url : null;
|
||||||
if ((message.content.includes('--help') || (args[0] === '' && args.length === 1)) && !attachmentUrl) {
|
if ((message.content.includes('--help') || (args[0] === '' && args.length === 1)) && !attachmentUrl) {
|
||||||
return await message.reply(enums.help.IMPORT);
|
return await message.reply(enums.help.IMPORT);
|
||||||
@@ -119,4 +119,4 @@ cmds.importCommand = async function (message, args) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const commands = cmds;
|
module.exports.commands = commands;
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
import {DataTypes, Sequelize} from 'sequelize';
|
|
||||||
import * as env from 'dotenv';
|
|
||||||
|
|
||||||
env.config();
|
|
||||||
|
|
||||||
const password = process.env.POSTGRES_PASSWORD;
|
|
||||||
|
|
||||||
if (!password) {
|
|
||||||
console.error("Missing POSTGRES_PASSWORD environment variable.");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const db = {};
|
|
||||||
|
|
||||||
const sequelize = new Sequelize('postgres', 'postgres', password, {
|
|
||||||
host: 'localhost',
|
|
||||||
logging: false,
|
|
||||||
dialect: 'postgres'
|
|
||||||
});
|
|
||||||
|
|
||||||
db.sequelize = sequelize;
|
|
||||||
db.Sequelize = Sequelize;
|
|
||||||
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
db.check_connection = async function () {
|
|
||||||
try {
|
|
||||||
await sequelize.authenticate();
|
|
||||||
console.log('Connection has been established successfully.');
|
|
||||||
await syncModels();
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Unable to connect to the database:', err);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Syncs Sequelize models.
|
|
||||||
*/
|
|
||||||
async function syncModels() {
|
|
||||||
try {
|
|
||||||
await sequelize.sync()
|
|
||||||
console.log('Models synced successfully.');
|
|
||||||
} catch(err) {
|
|
||||||
console.error('Syncing models did not work', err);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const database = db;
|
|
||||||
10
src/enums.js
10
src/enums.js
@@ -1,6 +1,6 @@
|
|||||||
const helperEnums = {};
|
const enums = {};
|
||||||
|
|
||||||
helperEnums.err = {
|
enums.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.",
|
NO_VALUE: "has not been set for this member.",
|
||||||
@@ -26,7 +26,7 @@ helperEnums.err = {
|
|||||||
CANNOT_FETCH_RESOURCE: "Could not download the file at this time."
|
CANNOT_FETCH_RESOURCE: "Could not download the file at this time."
|
||||||
}
|
}
|
||||||
|
|
||||||
helperEnums.help = {
|
enums.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.",
|
||||||
@@ -43,11 +43,11 @@ helperEnums.help = {
|
|||||||
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, not anything else like birthdays or system handles (yet?). **Only one proxy can be set per member currently.**\n\n**PRO TIP**: For privacy reasons, try DMing the bot with this command and your JSON file--it should still work the same."
|
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, not anything else like birthdays or system handles (yet?). **Only one proxy can be set per member currently.**\n\n**PRO TIP**: For privacy reasons, try DMing the bot with this command and your JSON file--it should still work the same."
|
||||||
}
|
}
|
||||||
|
|
||||||
helperEnums.misc = {
|
enums.misc = {
|
||||||
ATTACHMENT_SENT_BY: "Attachment sent by:",
|
ATTACHMENT_SENT_BY: "Attachment sent by:",
|
||||||
ATTACHMENT_EXPIRATION_WARNING: "**NOTE:** Because this profile picture is hosted on Fluxer, it will expire. To avoid this, upload the picture to another website like <https://imgbb.com/> and link to it directly.",
|
ATTACHMENT_EXPIRATION_WARNING: "**NOTE:** Because this profile picture is hosted on Fluxer, it will expire. To avoid this, upload the picture to another website like <https://imgbb.com/> and link to it directly.",
|
||||||
FLUXER_ATTACHMENT_URL: "https://fluxerusercontent.com/attachments/"
|
FLUXER_ATTACHMENT_URL: "https://fluxerusercontent.com/attachments/"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const enums = helperEnums;
|
module.exports.enums = enums;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import {enums} from "../enums.js";
|
const {enums} = require("../enums.js");
|
||||||
import {memberHelper} from "./memberHelper.js";
|
const {memberHelper} = require("./memberHelper.js");
|
||||||
|
|
||||||
const ih = {};
|
const importHelper = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tries to import from Pluralkit.
|
* Tries to import from Pluralkit.
|
||||||
@@ -12,7 +12,7 @@ const ih = {};
|
|||||||
* @returns {Promise<string>} A successful addition of all members.
|
* @returns {Promise<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.
|
||||||
*/
|
*/
|
||||||
ih.pluralKitImport = async function (authorId, attachmentUrl= null) {
|
importHelper.pluralKitImport = async function (authorId, attachmentUrl= null) {
|
||||||
let fetchResult, pkData;
|
let fetchResult, pkData;
|
||||||
if (!attachmentUrl) {
|
if (!attachmentUrl) {
|
||||||
throw new Error(enums.err.NOT_JSON_FILE);
|
throw new Error(enums.err.NOT_JSON_FILE);
|
||||||
@@ -55,4 +55,4 @@ ih.pluralKitImport = async function (authorId, attachmentUrl= null) {
|
|||||||
return aggregatedText;
|
return aggregatedText;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const importHelper = ih;
|
exports.importHelper = importHelper;
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
import {database} from '../database.js';
|
const {enums} = require("../enums.js");
|
||||||
import {enums} from "../enums.js";
|
const {EmbedBuilder} = require("@fluxerjs/core");
|
||||||
import {Op} from "sequelize";
|
const {utils} = require("./utils.js");
|
||||||
import {EmbedBuilder} from "@fluxerjs/core";
|
const {memberRepo} = require("../repositories/memberRepo.js");
|
||||||
import {utils} from "./utils.js";
|
|
||||||
|
|
||||||
const mh = {};
|
const memberHelper = {};
|
||||||
|
|
||||||
const commandList = ['new', 'remove', 'name', 'list', 'displayname', 'proxy', 'propic'];
|
const commandList = ['new', 'remove', 'name', 'list', 'displayname', 'proxy', 'propic'];
|
||||||
const newAndRemoveCommands = ['new', 'remove'];
|
const newAndRemoveCommands = ['new', 'remove'];
|
||||||
@@ -23,14 +22,14 @@ const newAndRemoveCommands = ['new', 'remove'];
|
|||||||
* @returns {Promise <EmbedBuilder>} A list of member commands and descriptions.
|
* @returns {Promise <EmbedBuilder>} A list of member commands and descriptions.
|
||||||
* @returns {Promise<{EmbedBuilder, string[], string}>} A member info embed + info/errors.
|
* @returns {Promise<{EmbedBuilder, string[], string}>} A member info embed + info/errors.
|
||||||
*/
|
*/
|
||||||
mh.parseMemberCommand = async function (authorId, authorFull, args, attachmentUrl = null, attachmentExpiration = null) {
|
memberHelper.parseMemberCommand = async function (authorId, authorFull, args, attachmentUrl = null, attachmentExpiration = null) {
|
||||||
let memberName, command, isHelp = false;
|
let memberName, command, isHelp = false;
|
||||||
// checks whether command is in list, otherwise assumes it's a name
|
// checks whether command is in list, otherwise assumes it's a name
|
||||||
|
|
||||||
// ex: pf;member remove, pf;member remove --help
|
// ex: pf;member remove, pf;member remove --help
|
||||||
// ex: pf;member, pf;member --help
|
// ex: pf;member, pf;member --help
|
||||||
if (args.length === 0 || args[0] === '--help' || args[0] === '') {
|
if (args.length === 0 || args[0] === '--help' || args[0] === '') {
|
||||||
return mh.getMemberCommandInfo();
|
return memberHelper.getMemberCommandInfo();
|
||||||
}
|
}
|
||||||
// ex: pf;member remove somePerson
|
// ex: pf;member remove somePerson
|
||||||
if (commandList.includes(args[0])) {
|
if (commandList.includes(args[0])) {
|
||||||
@@ -52,7 +51,7 @@ mh.parseMemberCommand = async function (authorId, authorFull, args, attachmentUr
|
|||||||
isHelp = true;
|
isHelp = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return await mh.memberArgumentHandler(authorId, authorFull, isHelp, command, memberName, args, attachmentUrl, attachmentExpiration)
|
return await memberHelper.memberArgumentHandler(authorId, authorFull, isHelp, command, memberName, args, attachmentUrl, attachmentExpiration);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,17 +70,18 @@ mh.parseMemberCommand = async function (authorId, authorFull, args, attachmentUr
|
|||||||
* @returns {Promise <EmbedBuilder>} A list of 25 members as an embed.
|
* @returns {Promise <EmbedBuilder>} A list of 25 members as an embed.
|
||||||
* @returns {Promise <EmbedBuilder>} A list of member commands and descriptions.
|
* @returns {Promise <EmbedBuilder>} A list of member commands and descriptions.
|
||||||
* @returns {Promise<{EmbedBuilder, [string], string}>} A member info embed + info/errors.
|
* @returns {Promise<{EmbedBuilder, [string], string}>} A member info embed + info/errors.
|
||||||
|
* @returns {Promise<string>} - A help message
|
||||||
* @throws {Error} When there's no member or a command is not recognized.
|
* @throws {Error} When there's no member or a command is not recognized.
|
||||||
*/
|
*/
|
||||||
mh.memberArgumentHandler = async function(authorId, authorFull, isHelp, command = null, memberName = null, args = [], attachmentUrl = null, attachmentExpiration = null) {
|
memberHelper.memberArgumentHandler = async function(authorId, authorFull, isHelp, command = null, memberName = null, args = [], attachmentUrl = null, attachmentExpiration = null) {
|
||||||
if (!command && !memberName && !isHelp) {
|
if (!command && !memberName && !isHelp) {
|
||||||
throw new Error(enums.err.COMMAND_NOT_RECOGNIZED);
|
throw new Error(enums.err.COMMAND_NOT_RECOGNIZED);
|
||||||
}
|
}
|
||||||
else if (isHelp) {
|
else if (isHelp) {
|
||||||
return mh.sendHelpEnum(command);
|
return memberHelper.sendHelpEnum(command);
|
||||||
}
|
}
|
||||||
else if (command === "list") {
|
else if (command === "list") {
|
||||||
return await mh.getAllMembersInfo(authorId, authorFull);
|
return await memberHelper.getAllMembersInfo(authorId, authorFull);
|
||||||
}
|
}
|
||||||
else if (!memberName && !isHelp) {
|
else if (!memberName && !isHelp) {
|
||||||
throw new Error(enums.err.NO_MEMBER);
|
throw new Error(enums.err.NO_MEMBER);
|
||||||
@@ -92,10 +92,10 @@ mh.memberArgumentHandler = async function(authorId, authorFull, isHelp, command
|
|||||||
|
|
||||||
// ex: pf;member blah blah
|
// ex: pf;member blah blah
|
||||||
if (command && memberName && (values.length > 0 || newAndRemoveCommands.includes(command) || attachmentUrl)) {
|
if (command && memberName && (values.length > 0 || newAndRemoveCommands.includes(command) || attachmentUrl)) {
|
||||||
return await mh.memberCommandHandler(authorId, command, memberName, values, attachmentUrl, attachmentExpiration);
|
return await memberHelper.memberCommandHandler(authorId, command, memberName, values, attachmentUrl, attachmentExpiration);
|
||||||
}
|
}
|
||||||
else if (memberName && values.length === 0) {
|
else if (memberName && values.length === 0) {
|
||||||
return await mh.sendCurrentValue(authorId, memberName, command);
|
return await memberHelper.sendCurrentValue(authorId, memberName, command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,12 +112,12 @@ mh.memberArgumentHandler = async function(authorId, authorFull, isHelp, command
|
|||||||
* @returns {Promise<{EmbedBuilder, string[], string}>} A member info embed + info/errors.
|
* @returns {Promise<{EmbedBuilder, string[], string}>} A member info embed + info/errors.
|
||||||
* @throws {Error} When there's no member
|
* @throws {Error} When there's no member
|
||||||
*/
|
*/
|
||||||
mh.sendCurrentValue = async function(authorId, memberName, command= null) {
|
memberHelper.sendCurrentValue = async function(authorId, memberName, command= null) {
|
||||||
const member = await mh.getMemberByName(authorId, memberName);
|
const member = await memberRepo.getMemberByName(authorId, memberName);
|
||||||
if (!member) throw new Error(enums.err.NO_MEMBER);
|
if (!member) throw new Error(enums.err.NO_MEMBER);
|
||||||
|
|
||||||
if (!command) {
|
if (!command) {
|
||||||
return mh.getMemberInfo(member);
|
return memberHelper.getMemberInfo(member);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (command) {
|
switch (command) {
|
||||||
@@ -138,7 +138,7 @@ mh.sendCurrentValue = async function(authorId, memberName, command= null) {
|
|||||||
* @param {string} command - The command being called.
|
* @param {string} command - The command being called.
|
||||||
* @returns {string} - The help text associated with a command.
|
* @returns {string} - The help text associated with a command.
|
||||||
*/
|
*/
|
||||||
mh.sendHelpEnum = function(command) {
|
memberHelper.sendHelpEnum = function(command) {
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case 'new':
|
case 'new':
|
||||||
return enums.help.NEW;
|
return enums.help.NEW;
|
||||||
@@ -167,25 +167,22 @@ mh.sendHelpEnum = function(command) {
|
|||||||
* @param {string[]} values - The values to be passed in. Only includes the values after member name and command name.
|
* @param {string[]} values - The values to be passed in. Only includes the values after member name and command name.
|
||||||
* @param {string | null} attachmentUrl - The attachment URL, if any
|
* @param {string | null} attachmentUrl - The attachment URL, if any
|
||||||
* @param {string | null} attachmentExpiration - The attachment expiry date, if any
|
* @param {string | null} attachmentExpiration - The attachment expiry date, if any
|
||||||
* @returns {Promise<string>} A success message.
|
* @returns {Promise<string> | Promise <EmbedBuilder> | Promise<{EmbedBuilder, [string], string}>}
|
||||||
* @returns {Promise <EmbedBuilder>} A list of 25 members as an embed.
|
|
||||||
* @returns {Promise <EmbedBuilder>} A list of member commands and descriptions.
|
|
||||||
* @returns {Promise<{EmbedBuilder, [string], string}>} A member info embed + info/errors.
|
|
||||||
*/
|
*/
|
||||||
mh.memberCommandHandler = async function(authorId, command, memberName, values, attachmentUrl = null, attachmentExpiration = null) {
|
memberHelper.memberCommandHandler = async function(authorId, command, memberName, values, attachmentUrl = null, attachmentExpiration = null) {
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case 'new':
|
case 'new':
|
||||||
return await mh.addNewMember(authorId, memberName, values, attachmentUrl, attachmentExpiration);
|
return await memberHelper.addNewMember(authorId, memberName, values, attachmentUrl, attachmentExpiration);
|
||||||
case 'remove':
|
case 'remove':
|
||||||
return await mh.removeMember(authorId, memberName);
|
return await memberHelper.removeMember(authorId, memberName);
|
||||||
case 'name':
|
case 'name':
|
||||||
return await mh.updateName(authorId, memberName, values[0]);
|
return await memberHelper.updateName(authorId, memberName, values[0]);
|
||||||
case 'displayname':
|
case 'displayname':
|
||||||
return await mh.updateDisplayName(authorId, memberName, values[0]);
|
return await memberHelper.updateDisplayName(authorId, memberName, values[0]);
|
||||||
case 'proxy':
|
case 'proxy':
|
||||||
return await mh.updateProxy(authorId, memberName, values[0]);
|
return await memberHelper.updateProxy(authorId, memberName, values[0]);
|
||||||
case 'propic':
|
case 'propic':
|
||||||
return await mh.updatePropic(authorId, memberName, values[0], attachmentUrl, attachmentExpiration);
|
return await memberHelper.updatePropic(authorId, memberName, values[0], attachmentUrl, attachmentExpiration);
|
||||||
default:
|
default:
|
||||||
throw new Error(enums.err.COMMAND_NOT_RECOGNIZED);
|
throw new Error(enums.err.COMMAND_NOT_RECOGNIZED);
|
||||||
}
|
}
|
||||||
@@ -202,13 +199,13 @@ mh.memberCommandHandler = async function(authorId, command, memberName, values,
|
|||||||
* @param {string | null} [attachmentExpiration] - The attachment expiry date, if any
|
* @param {string | null} [attachmentExpiration] - The attachment expiry date, if any
|
||||||
* @returns {Promise<{EmbedBuilder, string[], string}>} A successful addition.
|
* @returns {Promise<{EmbedBuilder, string[], string}>} A successful addition.
|
||||||
*/
|
*/
|
||||||
mh.addNewMember = async function (authorId, memberName, values, attachmentUrl = null, attachmentExpiration = null) {
|
memberHelper.addNewMember = async function (authorId, memberName, values, attachmentUrl = null, attachmentExpiration = null) {
|
||||||
const displayName = values[0];
|
const displayName = values[0];
|
||||||
const proxy = values[1];
|
const proxy = values[1];
|
||||||
const propic = values[2] ?? attachmentUrl;
|
const propic = values[2] ?? attachmentUrl;
|
||||||
|
|
||||||
const memberObj = await mh.addFullMember(authorId, memberName, displayName, proxy, propic, attachmentExpiration);
|
const memberObj = await memberHelper.addFullMember(authorId, memberName, displayName, proxy, propic, attachmentExpiration);
|
||||||
const memberInfoEmbed = mh.getMemberInfo(memberObj.member);
|
const memberInfoEmbed = memberHelper.getMemberInfo(memberObj.member);
|
||||||
return {embed: memberInfoEmbed, errors: memberObj.errors, success: `${memberName} has been added successfully.`}
|
return {embed: memberInfoEmbed, errors: memberObj.errors, success: `${memberName} has been added successfully.`}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,12 +219,12 @@ mh.addNewMember = async function (authorId, memberName, values, attachmentUrl =
|
|||||||
* @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.
|
||||||
*/
|
*/
|
||||||
mh.updateName = async function (authorId, memberName, name) {
|
memberHelper.updateName = async function (authorId, memberName, name) {
|
||||||
const trimmedName = name.trim();
|
const trimmedName = name.trim();
|
||||||
if (trimmedName === '') {
|
if (trimmedName === '') {
|
||||||
throw new RangeError(`Name ${enums.err.NO_VALUE}`);
|
throw new RangeError(`Name ${enums.err.NO_VALUE}`);
|
||||||
}
|
}
|
||||||
return await mh.updateMemberField(authorId, memberName, "name", trimmedName);
|
return await memberHelper.updateMemberField(authorId, memberName, "name", trimmedName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -240,7 +237,7 @@ mh.updateName = async function (authorId, memberName, name) {
|
|||||||
* @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.
|
||||||
*/
|
*/
|
||||||
mh.updateDisplayName = async function (authorId, membername, displayname) {
|
memberHelper.updateDisplayName = async function (authorId, membername, displayname) {
|
||||||
const trimmedName = displayname.trim();
|
const trimmedName = displayname.trim();
|
||||||
|
|
||||||
if (trimmedName.length > 32) {
|
if (trimmedName.length > 32) {
|
||||||
@@ -249,7 +246,7 @@ mh.updateDisplayName = async function (authorId, membername, displayname) {
|
|||||||
else if (trimmedName === '') {
|
else if (trimmedName === '') {
|
||||||
throw new RangeError(`Display name ${enums.err.NO_VALUE}`);
|
throw new RangeError(`Display name ${enums.err.NO_VALUE}`);
|
||||||
}
|
}
|
||||||
return await mh.updateMemberField(authorId, membername, "displayname", trimmedName);
|
return await memberHelper.updateMemberField(authorId, membername, "displayname", trimmedName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -261,11 +258,11 @@ mh.updateDisplayName = async function (authorId, membername, displayname) {
|
|||||||
* @param {string} proxy - The proxy to set
|
* @param {string} proxy - The proxy to set
|
||||||
* @returns {Promise<string> } A successful update.
|
* @returns {Promise<string> } A successful update.
|
||||||
*/
|
*/
|
||||||
mh.updateProxy = async function (authorId, memberName, proxy) {
|
memberHelper.updateProxy = async function (authorId, memberName, proxy) {
|
||||||
// Throws error if exists
|
// Throws error if exists
|
||||||
await mh.checkIfProxyExists(authorId, proxy);
|
await memberHelper.checkIfProxyExists(authorId, proxy);
|
||||||
|
|
||||||
return await mh.updateMemberField(authorId, memberName, "proxy", proxy);
|
return await memberHelper.updateMemberField(authorId, memberName, "proxy", proxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -279,12 +276,12 @@ mh.updateProxy = async function (authorId, memberName, proxy) {
|
|||||||
* @param {string | null} attachmentExpiration - The attachment expiry date, if any
|
* @param {string | null} attachmentExpiration - The attachment expiry date, if any
|
||||||
* @returns {Promise<string>} A successful update.
|
* @returns {Promise<string>} A successful update.
|
||||||
*/
|
*/
|
||||||
mh.updatePropic = async function (authorId, memberName, values, attachmentUrl = null, attachmentExpiration = null) {
|
memberHelper.updatePropic = async function (authorId, memberName, values, attachmentUrl = null, attachmentExpiration = null) {
|
||||||
const imgUrl = values ?? attachmentUrl;
|
const imgUrl = values ?? attachmentUrl;
|
||||||
// Throws error if invalid
|
// Throws error if invalid
|
||||||
await utils.checkImageFormatValidity(imgUrl);
|
await utils.checkImageFormatValidity(imgUrl);
|
||||||
const expirationWarning = utils.setExpirationWarning(imgUrl, attachmentExpiration);
|
const expirationWarning = utils.setExpirationWarning(imgUrl, attachmentExpiration);
|
||||||
return await mh.updateMemberField(authorId, memberName, "propic", imgUrl, expirationWarning);
|
return await memberHelper.updateMemberField(authorId, memberName, "propic", imgUrl, expirationWarning);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -296,13 +293,8 @@ mh.updatePropic = async function (authorId, memberName, values, attachmentUrl =
|
|||||||
* @returns {Promise<string>} A successful removal.
|
* @returns {Promise<string>} A successful removal.
|
||||||
* @throws {Error} When there is no member to remove.
|
* @throws {Error} When there is no member to remove.
|
||||||
*/
|
*/
|
||||||
mh.removeMember = async function (authorId, memberName) {
|
memberHelper.removeMember = async function (authorId, memberName) {
|
||||||
const destroyed = await database.members.destroy({
|
const destroyed = await memberRepo.removeMember(authorId, memberName);
|
||||||
where: {
|
|
||||||
name: {[Op.iLike]: memberName},
|
|
||||||
userid: authorId
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (destroyed > 0) {
|
if (destroyed > 0) {
|
||||||
return `Member "${memberName}" has been deleted.`;
|
return `Member "${memberName}" has been deleted.`;
|
||||||
} else {
|
} else {
|
||||||
@@ -322,11 +314,11 @@ mh.removeMember = async function (authorId, memberName) {
|
|||||||
* @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 {string | null} [attachmentExpiration] - The expiration date of an uploaded profile picture.
|
* @param {string | null} [attachmentExpiration] - The expiration date of an uploaded profile picture.
|
||||||
* @returns {Promise<{model, string[]}>} A successful addition object, including errors if there are any.
|
* @returns {Promise<{Members, string[]}>} A successful addition object, including errors if there are any.
|
||||||
* @throws {Error} When the member already exists, there are validation errors, or adding a member doesn't work.
|
* @throws {Error} 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, attachmentExpiration = null) {
|
memberHelper.addFullMember = async function (authorId, memberName, displayName = null, proxy = null, propic = null, attachmentExpiration = null) {
|
||||||
const existingMember = await mh.getMemberByName(authorId, memberName);
|
const existingMember = await memberRepo.getMemberByName(authorId, memberName);
|
||||||
if (existingMember) {
|
if (existingMember) {
|
||||||
throw new Error(`Can't add ${memberName}. ${enums.err.MEMBER_EXISTS}`);
|
throw new Error(`Can't add ${memberName}. ${enums.err.MEMBER_EXISTS}`);
|
||||||
}
|
}
|
||||||
@@ -356,7 +348,7 @@ mh.addFullMember = async function (authorId, memberName, displayName = null, pro
|
|||||||
let isValidProxy;
|
let isValidProxy;
|
||||||
if (proxy && proxy.length > 0) {
|
if (proxy && proxy.length > 0) {
|
||||||
try {
|
try {
|
||||||
const proxyExists = await mh.checkIfProxyExists(authorId, proxy);
|
const proxyExists = await memberHelper.checkIfProxyExists(authorId, proxy);
|
||||||
isValidProxy = !proxyExists;
|
isValidProxy = !proxyExists;
|
||||||
}
|
}
|
||||||
catch(e) {
|
catch(e) {
|
||||||
@@ -365,21 +357,22 @@ mh.addFullMember = async function (authorId, memberName, displayName = null, pro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let isValidPropic;
|
let isValidPropic, expirationWarning;
|
||||||
if (propic && propic.length > 0) {
|
if (propic && propic.length > 0) {
|
||||||
try {
|
try {
|
||||||
isValidPropic = await utils.checkImageFormatValidity(propic);
|
isValidPropic = await utils.checkImageFormatValidity(propic);
|
||||||
|
expirationWarning = utils.setExpirationWarning(propic, attachmentExpiration);
|
||||||
|
if (expirationWarning) {
|
||||||
|
errors.push(expirationWarning);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch(e) {
|
catch(e) {
|
||||||
errors.push(`Tried to set profile picture to \"${propic}\". ${e.message}. ${enums.err.SET_TO_NULL}`);
|
errors.push(`Tried to set profile picture to \"${propic}\". ${e.message}. ${enums.err.SET_TO_NULL}`);
|
||||||
isValidPropic = false;
|
isValidPropic = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const expirationWarning = utils.setExpirationWarning(propic, attachmentExpiration);
|
|
||||||
if (expirationWarning) {
|
const member = await memberRepo.createMember({
|
||||||
errors.push(expirationWarning);
|
|
||||||
}
|
|
||||||
const member = await database.members.create({
|
|
||||||
name: memberName, userid: authorId, displayname: isValidDisplayName ? displayName : null, proxy: isValidProxy ? proxy : null, propic: isValidPropic ? propic : null
|
name: memberName, userid: authorId, displayname: isValidDisplayName ? displayName : null, proxy: isValidProxy ? proxy : null, propic: isValidPropic ? propic : null
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -398,14 +391,9 @@ mh.addFullMember = async function (authorId, memberName, displayName = null, pro
|
|||||||
* @returns {Promise<string>} A successful update.
|
* @returns {Promise<string>} A successful update.
|
||||||
* @throws {Error} When no member row was updated.
|
* @throws {Error} When no member row was updated.
|
||||||
*/
|
*/
|
||||||
mh.updateMemberField = async function (authorId, memberName, columnName, value, expirationWarning = null) {
|
memberHelper.updateMemberField = async function (authorId, memberName, columnName, value, expirationWarning = null) {
|
||||||
const res = await database.members.update({[columnName]: value}, {
|
const res = await memberRepo.updateMemberField(authorId, memberName, columnName, value);
|
||||||
where: {
|
if (res === 0) {
|
||||||
name: {[Op.iLike]: memberName},
|
|
||||||
userid: authorId
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (res[0] === 0) {
|
|
||||||
throw new Error(`Can't update ${memberName}. ${enums.err.NO_MEMBER}.`);
|
throw new Error(`Can't update ${memberName}. ${enums.err.NO_MEMBER}.`);
|
||||||
} else {
|
} else {
|
||||||
return `Updated ${columnName} for ${memberName} to ${value}${expirationWarning ? `. ${expirationWarning}.` : '.'}`;
|
return `Updated ${columnName} for ${memberName} to ${value}${expirationWarning ? `. ${expirationWarning}.` : '.'}`;
|
||||||
@@ -415,10 +403,10 @@ mh.updateMemberField = async function (authorId, memberName, columnName, value,
|
|||||||
/**
|
/**
|
||||||
* Gets the details for a member.
|
* Gets the details for a member.
|
||||||
*
|
*
|
||||||
* @param {model} member - The member object
|
* @param {{Member, string[]}} member - The member object
|
||||||
* @returns {EmbedBuilder} The member's info.
|
* @returns {EmbedBuilder} The member's info.
|
||||||
*/
|
*/
|
||||||
mh.getMemberInfo = function (member) {
|
memberHelper.getMemberInfo = function (member) {
|
||||||
return new EmbedBuilder()
|
return new EmbedBuilder()
|
||||||
.setTitle(member.name)
|
.setTitle(member.name)
|
||||||
.setDescription(`Details for ${member.name}`)
|
.setDescription(`Details for ${member.name}`)
|
||||||
@@ -439,8 +427,8 @@ mh.getMemberInfo = function (member) {
|
|||||||
* @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.
|
||||||
*/
|
*/
|
||||||
mh.getAllMembersInfo = async function (authorId, authorName) {
|
memberHelper.getAllMembersInfo = async function (authorId, authorName) {
|
||||||
const members = await mh.getMembersByAuthor(authorId);
|
const members = await memberRepo.getMembersByAuthor(authorId);
|
||||||
if (members.length === 0) throw Error(enums.err.USER_NO_MEMBERS);
|
if (members.length === 0) throw Error(enums.err.USER_NO_MEMBERS);
|
||||||
const fields = [...members.entries()].map(([index, member]) => ({
|
const fields = [...members.entries()].map(([index, member]) => ({
|
||||||
name: member.name, value: `(Proxy: \`${member.proxy ?? "unset"}\`)`, inline: true,
|
name: member.name, value: `(Proxy: \`${member.proxy ?? "unset"}\`)`, inline: true,
|
||||||
@@ -450,29 +438,6 @@ mh.getAllMembersInfo = async function (authorId, authorName) {
|
|||||||
.addFields(...fields);
|
.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.
|
|
||||||
*/
|
|
||||||
mh.getMemberByName = async function (authorId, memberName) {
|
|
||||||
return await database.members.findOne({where: {userid: authorId, name: {[Op.iLike]: memberName}}});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
* Checks if proxy exists for a member.
|
||||||
*
|
*
|
||||||
@@ -481,12 +446,12 @@ mh.getMembersByAuthor = async function (authorId) {
|
|||||||
* @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.
|
||||||
*/
|
*/
|
||||||
mh.checkIfProxyExists = async function (authorId, proxy) {
|
memberHelper.checkIfProxyExists = async function (authorId, 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);
|
||||||
|
|
||||||
const memberList = await mh.getMembersByAuthor(authorId);
|
const memberList = await memberRepo.getMembersByAuthor(authorId);
|
||||||
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);
|
||||||
@@ -499,7 +464,7 @@ mh.checkIfProxyExists = async function (authorId, proxy) {
|
|||||||
*
|
*
|
||||||
* @returns {EmbedBuilder } An embed of member commands.
|
* @returns {EmbedBuilder } An embed of member commands.
|
||||||
*/
|
*/
|
||||||
mh.getMemberCommandInfo = function() {
|
memberHelper.getMemberCommandInfo = function() {
|
||||||
const fields = [
|
const fields = [
|
||||||
{name: `**new**`, value: enums.help.NEW, inline: false},
|
{name: `**new**`, value: enums.help.NEW, inline: false},
|
||||||
{name: `**remove**`, value: enums.help.REMOVE, inline: false},
|
{name: `**remove**`, value: enums.help.REMOVE, inline: false},
|
||||||
@@ -516,4 +481,4 @@ mh.getMemberCommandInfo = function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const memberHelper = mh;
|
module.exports.memberHelper = memberHelper;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import {memberHelper} from "./memberHelper.js";
|
const {memberRepo} = require('../repositories/memberRepo.js');
|
||||||
|
|
||||||
const msgh = {};
|
const msgh = {};
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ msgh.parseCommandArgs = function(content, commandName) {
|
|||||||
* @returns {Promise<{model, string, bool}>} The proxy message object.
|
* @returns {Promise<{model, string, bool}>} The proxy message object.
|
||||||
*/
|
*/
|
||||||
msgh.parseProxyTags = async function (authorId, content, attachmentUrl = null){
|
msgh.parseProxyTags = async function (authorId, content, attachmentUrl = null){
|
||||||
const members = await memberHelper.getMembersByAuthor(authorId);
|
const members = await memberRepo.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) {
|
||||||
return;
|
return;
|
||||||
@@ -80,4 +80,4 @@ msgh.returnBufferFromText = function (text) {
|
|||||||
return {text: text, file: undefined}
|
return {text: text, file: undefined}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const messageHelper = msgh;
|
module.exports.messageHelper = msgh;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import {enums} from '../enums.js'
|
const {enums} = require('../enums');
|
||||||
|
|
||||||
const u = {};
|
const utils = {};
|
||||||
|
|
||||||
u.debounce = function(func, delay) {
|
utils.debounce = function(func, delay) {
|
||||||
let timeout = null;
|
let timeout = null;
|
||||||
return function (...args) {
|
return function (...args) {
|
||||||
clearTimeout(timeout);
|
clearTimeout(timeout);
|
||||||
@@ -18,7 +18,7 @@ u.debounce = function(func, delay) {
|
|||||||
* @returns {bool} - Whether the image is in a valid format
|
* @returns {bool} - Whether the image is in 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.
|
||||||
*/
|
*/
|
||||||
u.checkImageFormatValidity = async function (imageUrl) {
|
utils.checkImageFormatValidity = async function (imageUrl) {
|
||||||
const acceptableImages = ['image/png', 'image/jpg', 'image/jpeg', 'image/webp'];
|
const acceptableImages = ['image/png', 'image/jpg', 'image/jpeg', 'image/webp'];
|
||||||
let response, blobFile;
|
let response, blobFile;
|
||||||
try {
|
try {
|
||||||
@@ -41,7 +41,7 @@ u.checkImageFormatValidity = async function (imageUrl) {
|
|||||||
* @param {string | null} [expirationString] - An expiration date string.
|
* @param {string | null} [expirationString] - An expiration date string.
|
||||||
* @returns {string | null} A description of the expiration, or null.
|
* @returns {string | null} A description of the expiration, or null.
|
||||||
*/
|
*/
|
||||||
u.setExpirationWarning = function (imgUrl = null, expirationString = null) {
|
utils.setExpirationWarning = function (imgUrl = null, expirationString = null) {
|
||||||
if (imgUrl && imgUrl.startsWith(enums.misc.FLUXER_ATTACHMENT_URL)) {
|
if (imgUrl && imgUrl.startsWith(enums.misc.FLUXER_ATTACHMENT_URL)) {
|
||||||
return enums.misc.ATTACHMENT_EXPIRATION_WARNING;
|
return enums.misc.ATTACHMENT_EXPIRATION_WARNING;
|
||||||
}
|
}
|
||||||
@@ -54,4 +54,4 @@ u.setExpirationWarning = function (imgUrl = null, expirationString = null) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const utils = u;
|
module.exports.utils = utils;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import {messageHelper} from "./messageHelper.js";
|
const {messageHelper} = require("./messageHelper.js");
|
||||||
import {Webhook, Channel, Message, Client} from '@fluxerjs/core';
|
const {Webhook, Channel, Message, Client} = require('@fluxerjs/core');
|
||||||
import {enums} from "../enums.js";
|
const {enums} = require("../enums.js");
|
||||||
|
|
||||||
const wh = {};
|
const webhookHelper = {};
|
||||||
|
|
||||||
const name = 'PluralFlux Proxy Webhook';
|
const name = 'PluralFlux Proxy Webhook';
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ const name = 'PluralFlux Proxy Webhook';
|
|||||||
* @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.
|
||||||
*/
|
*/
|
||||||
wh.sendMessageAsMember = async function(client, message) {
|
webhookHelper.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);
|
const proxyMatch = await messageHelper.parseProxyTags(message.author.id, message.content, attachmentUrl);
|
||||||
// If the message doesn't match a proxy, just return.
|
// If the message doesn't match a proxy, just return.
|
||||||
@@ -27,7 +27,7 @@ wh.sendMessageAsMember = async function(client, message) {
|
|||||||
if (proxyMatch.hasAttachment) {
|
if (proxyMatch.hasAttachment) {
|
||||||
return await message.reply(`${enums.misc.ATTACHMENT_SENT_BY} ${proxyMatch.member.displayname ?? proxyMatch.member.name}`)
|
return await message.reply(`${enums.misc.ATTACHMENT_SENT_BY} ${proxyMatch.member.displayname ?? proxyMatch.member.name}`)
|
||||||
}
|
}
|
||||||
await wh.replaceMessage(client, message, proxyMatch.message, proxyMatch.member);
|
await webhookHelper.replaceMessage(client, message, proxyMatch.message, proxyMatch.member);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,11 +39,11 @@ wh.sendMessageAsMember = async function(client, message) {
|
|||||||
* @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.
|
||||||
*/
|
*/
|
||||||
wh.replaceMessage = async function(client, message, text, member) {
|
webhookHelper.replaceMessage = async function(client, message, text, member) {
|
||||||
// attachment logic is not relevant yet, text length will always be over 0 right now
|
// attachment logic is not relevant yet, text length will always be over 0 right now
|
||||||
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 wh.getOrCreateWebhook(client, channel);
|
const webhook = await webhookHelper.getOrCreateWebhook(client, channel);
|
||||||
const username = member.displayname ?? member.name;
|
const username = member.displayname ?? member.name;
|
||||||
if (text.length <= 2000) {
|
if (text.length <= 2000) {
|
||||||
await webhook.send({content: text, username: username, avatar_url: member.propic})
|
await webhook.send({content: text, username: username, avatar_url: member.propic})
|
||||||
@@ -68,10 +68,10 @@ wh.replaceMessage = async function(client, message, text, member) {
|
|||||||
* @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.
|
||||||
*/
|
*/
|
||||||
wh.getOrCreateWebhook = async function(client, channel) {
|
webhookHelper.getOrCreateWebhook = async function(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 wh.getWebhook(client, channel)
|
let webhook = await webhookHelper.getWebhook(client, channel)
|
||||||
if (!webhook) {
|
if (!webhook) {
|
||||||
webhook = await channel.createWebhook({name: name});
|
webhook = await channel.createWebhook({name: name});
|
||||||
}
|
}
|
||||||
@@ -85,7 +85,7 @@ wh.getOrCreateWebhook = async function(client, channel) {
|
|||||||
* @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.
|
||||||
*/
|
*/
|
||||||
wh.getWebhook = async function(client, channel) {
|
webhookHelper.getWebhook = async function(client, channel) {
|
||||||
const channelWebhooks = await channel?.fetchWebhooks() ?? [];
|
const channelWebhooks = await channel?.fetchWebhooks() ?? [];
|
||||||
if (channelWebhooks.length === 0) {
|
if (channelWebhooks.length === 0) {
|
||||||
return;
|
return;
|
||||||
@@ -93,4 +93,4 @@ wh.getWebhook = async function(client, channel) {
|
|||||||
return channelWebhooks.find((webhook) => webhook.name === name);
|
return channelWebhooks.find((webhook) => webhook.name === name);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const webhookHelper = wh;
|
module.exports.webhookHelper = webhookHelper;
|
||||||
74
src/repositories/memberRepo.js
Normal file
74
src/repositories/memberRepo.js
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
const Member = require("../../database/entity/Member");
|
||||||
|
const { AppDataSource } = require("../../database/data-source");
|
||||||
|
const {ILike} = require("typeorm");
|
||||||
|
const members = AppDataSource.getRepository(Member.Member)
|
||||||
|
|
||||||
|
const memberRepo = {};
|
||||||
|
/**
|
||||||
|
* 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<Member | null>} The member object or null if not found.
|
||||||
|
*/
|
||||||
|
memberRepo.getMemberByName = async function (authorId, memberName) {
|
||||||
|
return await members.findOne({where: {userid: authorId, name: ILike(memberName)}});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all members belonging to the author.
|
||||||
|
*
|
||||||
|
* @async
|
||||||
|
* @param {string} authorId - The author of the message
|
||||||
|
* @returns {Promise<Member[]>} The member object array.
|
||||||
|
*/
|
||||||
|
memberRepo.getMembersByAuthor = async function (authorId) {
|
||||||
|
return await members.findBy({userid: authorId});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a member.
|
||||||
|
*
|
||||||
|
* @async
|
||||||
|
* @param {string} authorId - The author of the message
|
||||||
|
* @param {string} memberName - The name of the member to remove
|
||||||
|
* @returns {Promise<number>} Number of results removed.
|
||||||
|
*/
|
||||||
|
memberRepo.removeMember = async function (authorId, memberName) {
|
||||||
|
const deleted = await members.delete({ name: ILike(memberName), userid: authorId })
|
||||||
|
return deleted.affected;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a member with full details.
|
||||||
|
*
|
||||||
|
* @async
|
||||||
|
* @param {{name: string, userid: string, displayname: (string|null), proxy: (string|null), propic: (string|null)}} createObj - Object with parameters in it
|
||||||
|
* @returns {Promise<Member>} A successful inserted object.
|
||||||
|
*/
|
||||||
|
memberRepo.createMember = async function (createObj) {
|
||||||
|
return await members.save({
|
||||||
|
name: createObj.name, userid: createObj.userid, displayname: createObj.displayname, proxy: createObj.proxy, propic: createObj.propic
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates one fields for a member in the database.
|
||||||
|
*
|
||||||
|
* @async
|
||||||
|
* @param {string} authorId - The author of the message
|
||||||
|
* @param {string} memberName - The member to update
|
||||||
|
* @param {string} columnName - The column name to update.
|
||||||
|
* @param {string} value - The value to update to.
|
||||||
|
* @returns {Promise<number>} A successful update.
|
||||||
|
*/
|
||||||
|
memberRepo.updateMemberField = async function (authorId, memberName, columnName, value) {
|
||||||
|
const updated = await members.update({
|
||||||
|
name: ILike(memberName),
|
||||||
|
userid: authorId
|
||||||
|
}, {[columnName]: value})
|
||||||
|
return updated.affected;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.memberRepo = memberRepo;
|
||||||
@@ -56,6 +56,15 @@ jest.mock("../src/commands.js", () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
jest.mock('../database/data-source.ts', () => {
|
||||||
|
return {
|
||||||
|
AppDataSource: {
|
||||||
|
isInitialized: false,
|
||||||
|
initialize: jest.fn().mockResolvedValue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
const {Client, Events} = require('@fluxerjs/core');
|
const {Client, Events} = require('@fluxerjs/core');
|
||||||
const {messageHelper} = require("../src/helpers/messageHelper.js");
|
const {messageHelper} = require("../src/helpers/messageHelper.js");
|
||||||
|
|||||||
@@ -2,17 +2,15 @@ const {enums} = require('../../src/enums.js');
|
|||||||
const {utils} = require("../../src/helpers/utils.js");
|
const {utils} = require("../../src/helpers/utils.js");
|
||||||
|
|
||||||
jest.mock('@fluxerjs/core', () => jest.fn());
|
jest.mock('@fluxerjs/core', () => jest.fn());
|
||||||
jest.mock('../../src/database.js', () => {
|
jest.mock('../../src/repositories/memberRepo.js', () => {
|
||||||
return {
|
return {
|
||||||
database: {
|
memberRepo: {
|
||||||
members: {
|
getMemberByName: jest.fn().mockResolvedValue(),
|
||||||
create: jest.fn().mockResolvedValue(),
|
getMembersByAuthor: jest.fn().mockResolvedValue(),
|
||||||
update: jest.fn().mockResolvedValue(),
|
removeMember: jest.fn().mockResolvedValue(),
|
||||||
destroy: jest.fn().mockResolvedValue(),
|
createMember: jest.fn().mockResolvedValue(),
|
||||||
findOne: jest.fn().mockResolvedValue(),
|
updateMemberField: jest.fn().mockResolvedValue(),
|
||||||
findAll: jest.fn().mockResolvedValue(),
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -25,10 +23,8 @@ jest.mock("../../src/helpers/utils.js", () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const {Op} = require('sequelize');
|
|
||||||
|
|
||||||
const {memberHelper} = require("../../src/helpers/memberHelper.js");
|
const {memberHelper} = require("../../src/helpers/memberHelper.js");
|
||||||
const {database} = require("../../src/database");
|
const {memberRepo} = require("../../src/repositories/memberRepo.js");
|
||||||
|
|
||||||
describe('MemberHelper', () => {
|
describe('MemberHelper', () => {
|
||||||
const authorId = "0001";
|
const authorId = "0001";
|
||||||
@@ -270,29 +266,29 @@ describe('MemberHelper', () => {
|
|||||||
['propic', `The profile picture for ${mockMember.name} is \"${mockMember.propic}\".`],
|
['propic', `The profile picture for ${mockMember.name} is \"${mockMember.propic}\".`],
|
||||||
])('%s calls getMemberByName and returns value', async (command, expected) => {
|
])('%s calls getMemberByName and returns value', async (command, expected) => {
|
||||||
// Arrange
|
// Arrange
|
||||||
jest.spyOn(memberHelper, 'getMemberByName').mockResolvedValue(mockMember);
|
memberRepo.getMemberByName.mockResolvedValue(mockMember);
|
||||||
// Act
|
// Act
|
||||||
const result = await memberHelper.sendCurrentValue(authorId, mockMember.name, command);
|
const result = await memberHelper.sendCurrentValue(authorId, mockMember.name, command);
|
||||||
// Assert
|
// Assert
|
||||||
expect(result).toEqual(expected);
|
expect(result).toEqual(expected);
|
||||||
expect(memberHelper.getMemberByName).toHaveBeenCalledTimes(1);
|
expect(memberRepo.getMemberByName).toHaveBeenCalledTimes(1);
|
||||||
expect(memberHelper.getMemberByName).toHaveBeenCalledWith(authorId, mockMember.name);
|
expect(memberRepo.getMemberByName).toHaveBeenCalledWith(authorId, mockMember.name);
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
test('returns error if no member found', async () => {
|
test('returns error if no member found', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
jest.spyOn(memberHelper, 'getMemberByName').mockResolvedValue(null);
|
memberRepo.getMemberByName.mockResolvedValue(null);
|
||||||
// Act
|
// Act
|
||||||
await expect(memberHelper.sendCurrentValue(authorId, mockMember.name, 'name')).rejects.toThrow(enums.err.NO_MEMBER);
|
await expect(memberHelper.sendCurrentValue(authorId, mockMember.name, 'name')).rejects.toThrow(enums.err.NO_MEMBER);
|
||||||
// Assert
|
// Assert
|
||||||
expect(memberHelper.getMemberByName).toHaveBeenCalledTimes(1);
|
expect(memberRepo.getMemberByName).toHaveBeenCalledTimes(1);
|
||||||
expect(memberHelper.getMemberByName).toHaveBeenCalledWith(authorId, mockMember.name);
|
expect(memberRepo.getMemberByName).toHaveBeenCalledWith(authorId, mockMember.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('calls getMemberInfo with member if no command present', async () => {
|
test('calls getMemberInfo with member if no command present', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
jest.spyOn(memberHelper, 'getMemberByName').mockResolvedValue(mockMember);
|
memberRepo.getMemberByName.mockResolvedValue(mockMember);
|
||||||
jest.spyOn(memberHelper, 'getMemberInfo').mockResolvedValue('member info');
|
jest.spyOn(memberHelper, 'getMemberInfo').mockResolvedValue('member info');
|
||||||
// Act
|
// Act
|
||||||
const result = await memberHelper.sendCurrentValue(authorId, mockMember.name, null);
|
const result = await memberHelper.sendCurrentValue(authorId, mockMember.name, null);
|
||||||
@@ -309,13 +305,13 @@ describe('MemberHelper', () => {
|
|||||||
])('returns null message if no value found', async (command, expected) => {
|
])('returns null message if no value found', async (command, expected) => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const empty = {name: mockMember.name, displayname: null, proxy: null, propic: null}
|
const empty = {name: mockMember.name, displayname: null, proxy: null, propic: null}
|
||||||
jest.spyOn(memberHelper, 'getMemberByName').mockResolvedValue(empty);
|
memberRepo.getMemberByName.mockResolvedValue(empty);
|
||||||
// Act
|
// Act
|
||||||
const result = await memberHelper.sendCurrentValue(authorId, mockMember.name, command);
|
const result = await memberHelper.sendCurrentValue(authorId, mockMember.name, command);
|
||||||
// Assert
|
// Assert
|
||||||
expect(result).toEqual(expected);
|
expect(result).toEqual(expected);
|
||||||
expect(memberHelper.getMemberByName).toHaveBeenCalledTimes(1);
|
expect(memberRepo.getMemberByName).toHaveBeenCalledTimes(1);
|
||||||
expect(memberHelper.getMemberByName).toHaveBeenCalledWith(authorId, mockMember.name);
|
expect(memberRepo.getMemberByName).toHaveBeenCalledWith(authorId, mockMember.name);
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -479,39 +475,38 @@ describe('MemberHelper', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('addFullMember', () => {
|
describe('addFullMember', () => {
|
||||||
const {database} = require('../../src/database.js');
|
|
||||||
beforeEach(() => {
|
|
||||||
jest.spyOn(memberHelper, 'getMemberByName').mockResolvedValue();
|
|
||||||
})
|
|
||||||
|
|
||||||
test('calls getMemberByName', async () => {
|
test('calls getMemberByName', async () => {
|
||||||
|
// Arrange
|
||||||
|
memberRepo.getMemberByName.mockResolvedValue();
|
||||||
// Act
|
// Act
|
||||||
await memberHelper.addFullMember(authorId, mockMember.name)
|
await memberHelper.addFullMember(authorId, mockMember.name)
|
||||||
// Assert
|
// Assert
|
||||||
expect(memberHelper.getMemberByName).toHaveBeenCalledWith(authorId, mockMember.name);
|
expect(memberRepo.getMemberByName).toHaveBeenCalledWith(authorId, mockMember.name);
|
||||||
expect(memberHelper.getMemberByName).toHaveBeenCalledTimes(1);
|
expect(memberRepo.getMemberByName).toHaveBeenCalledTimes(1);
|
||||||
})
|
})
|
||||||
|
|
||||||
test('if getMemberByName returns member, throw error', async () => {
|
test('if getMemberByName returns member, throw error', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
memberHelper.getMemberByName.mockResolvedValue({name: mockMember.name});
|
memberRepo.getMemberByName.mockResolvedValue({name: mockMember.name});
|
||||||
// Act & Assert
|
// Act & Assert
|
||||||
await expect(memberHelper.addFullMember(authorId, mockMember.name)).rejects.toThrow(`Can't add ${mockMember.name}. ${enums.err.MEMBER_EXISTS}`)
|
await expect(memberHelper.addFullMember(authorId, mockMember.name)).rejects.toThrow(`Can't add ${mockMember.name}. ${enums.err.MEMBER_EXISTS}`)
|
||||||
// Assert
|
// Assert
|
||||||
expect(database.members.create).not.toHaveBeenCalled();
|
expect(memberRepo.createMember).not.toHaveBeenCalled();
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
test('if name is not filled out, throw error', async () => {
|
test('if name is not filled out, throw error', async () => {
|
||||||
// Act & Assert
|
// Arrange
|
||||||
|
memberRepo.getMemberByName.mockResolvedValue();
|
||||||
|
// Act
|
||||||
await expect(memberHelper.addFullMember(authorId, " ")).rejects.toThrow(`Name ${enums.err.NO_VALUE}. ${enums.err.NAME_REQUIRED}`);
|
await expect(memberHelper.addFullMember(authorId, " ")).rejects.toThrow(`Name ${enums.err.NO_VALUE}. ${enums.err.NAME_REQUIRED}`);
|
||||||
// Assert
|
// Assert
|
||||||
expect(database.members.create).not.toHaveBeenCalled();
|
expect(memberRepo.createMember).not.toHaveBeenCalled();
|
||||||
})
|
})
|
||||||
|
|
||||||
test('if displayname is over 32 characters, call database.member.create with null value', async () => {
|
test('if displayname is over 32 characters, call memberRepo.createMember with null value', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
memberHelper.getMemberByName.mockResolvedValue();
|
memberRepo.getMemberByName.mockResolvedValue();
|
||||||
const tooLongDisplayName = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
|
const tooLongDisplayName = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
|
||||||
const expectedMemberArgs = {
|
const expectedMemberArgs = {
|
||||||
name: mockMember.name,
|
name: mockMember.name,
|
||||||
@@ -520,7 +515,7 @@ describe('MemberHelper', () => {
|
|||||||
proxy: null,
|
proxy: null,
|
||||||
propic: null
|
propic: null
|
||||||
}
|
}
|
||||||
database.members.create = jest.fn().mockResolvedValue(expectedMemberArgs);
|
memberRepo.createMember = jest.fn().mockResolvedValue(expectedMemberArgs);
|
||||||
const expectedReturn = {
|
const expectedReturn = {
|
||||||
member: expectedMemberArgs,
|
member: expectedMemberArgs,
|
||||||
errors: [`Tried to set displayname to \"${tooLongDisplayName}\". ${enums.err.DISPLAY_NAME_TOO_LONG}. ${enums.err.SET_TO_NULL}`]
|
errors: [`Tried to set displayname to \"${tooLongDisplayName}\". ${enums.err.DISPLAY_NAME_TOO_LONG}. ${enums.err.SET_TO_NULL}`]
|
||||||
@@ -530,8 +525,8 @@ describe('MemberHelper', () => {
|
|||||||
const res = await memberHelper.addFullMember(authorId, mockMember.name, tooLongDisplayName, null, null);
|
const res = await memberHelper.addFullMember(authorId, mockMember.name, tooLongDisplayName, null, null);
|
||||||
// Assert
|
// Assert
|
||||||
expect(res).toEqual(expectedReturn);
|
expect(res).toEqual(expectedReturn);
|
||||||
expect(database.members.create).toHaveBeenCalledWith(expectedMemberArgs);
|
expect(memberRepo.createMember).toHaveBeenCalledWith(expectedMemberArgs);
|
||||||
expect(database.members.create).toHaveBeenCalledTimes(1);
|
expect(memberRepo.createMember).toHaveBeenCalledTimes(1);
|
||||||
})
|
})
|
||||||
|
|
||||||
test('if proxy, call checkIfProxyExists', async () => {
|
test('if proxy, call checkIfProxyExists', async () => {
|
||||||
@@ -544,7 +539,7 @@ describe('MemberHelper', () => {
|
|||||||
proxy: null,
|
proxy: null,
|
||||||
propic: null
|
propic: null
|
||||||
}
|
}
|
||||||
database.members.create = jest.fn().mockResolvedValue(expectedMemberArgs);
|
memberRepo.createMember = jest.fn().mockResolvedValue(expectedMemberArgs);
|
||||||
const expectedReturn = {member: expectedMemberArgs, errors: []}
|
const expectedReturn = {member: expectedMemberArgs, errors: []}
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
@@ -553,8 +548,8 @@ describe('MemberHelper', () => {
|
|||||||
expect(res).toEqual(expectedReturn);
|
expect(res).toEqual(expectedReturn);
|
||||||
expect(memberHelper.checkIfProxyExists).toHaveBeenCalledWith(authorId, mockMember.proxy);
|
expect(memberHelper.checkIfProxyExists).toHaveBeenCalledWith(authorId, mockMember.proxy);
|
||||||
expect(memberHelper.checkIfProxyExists).toHaveBeenCalledTimes(1);
|
expect(memberHelper.checkIfProxyExists).toHaveBeenCalledTimes(1);
|
||||||
expect(database.members.create).toHaveBeenCalledWith(expectedMemberArgs);
|
expect(memberRepo.createMember).toHaveBeenCalledWith(expectedMemberArgs);
|
||||||
expect(database.members.create).toHaveBeenCalledTimes(1);
|
expect(memberRepo.createMember).toHaveBeenCalledTimes(1);
|
||||||
})
|
})
|
||||||
|
|
||||||
test('if checkProxyExists throws error, call database.member.create with null value', async () => {
|
test('if checkProxyExists throws error, call database.member.create with null value', async () => {
|
||||||
@@ -567,7 +562,7 @@ describe('MemberHelper', () => {
|
|||||||
proxy: null,
|
proxy: null,
|
||||||
propic: null
|
propic: null
|
||||||
}
|
}
|
||||||
database.members.create = jest.fn().mockResolvedValue(expectedMemberArgs);
|
memberRepo.createMember = jest.fn().mockResolvedValue(expectedMemberArgs);
|
||||||
const expectedReturn = {
|
const expectedReturn = {
|
||||||
member: expectedMemberArgs,
|
member: expectedMemberArgs,
|
||||||
errors: [`Tried to set proxy to \"${mockMember.proxy}\". error. ${enums.err.SET_TO_NULL}`]
|
errors: [`Tried to set proxy to \"${mockMember.proxy}\". error. ${enums.err.SET_TO_NULL}`]
|
||||||
@@ -577,8 +572,8 @@ describe('MemberHelper', () => {
|
|||||||
const res = await memberHelper.addFullMember(authorId, mockMember.name, null, mockMember.proxy, null)
|
const res = await memberHelper.addFullMember(authorId, mockMember.name, null, mockMember.proxy, null)
|
||||||
// Assert
|
// Assert
|
||||||
expect(res).toEqual(expectedReturn);
|
expect(res).toEqual(expectedReturn);
|
||||||
expect(database.members.create).toHaveBeenCalledWith(expectedMemberArgs);
|
expect(memberRepo.createMember).toHaveBeenCalledWith(expectedMemberArgs);
|
||||||
expect(database.members.create).toHaveBeenCalledTimes(1);
|
expect(memberRepo.createMember).toHaveBeenCalledTimes(1);
|
||||||
})
|
})
|
||||||
|
|
||||||
test('if propic, call checkImageFormatValidity', async () => {
|
test('if propic, call checkImageFormatValidity', async () => {
|
||||||
@@ -590,7 +585,8 @@ describe('MemberHelper', () => {
|
|||||||
proxy: null,
|
proxy: null,
|
||||||
propic: null
|
propic: null
|
||||||
}
|
}
|
||||||
database.members.create = jest.fn().mockResolvedValue(expectedMemberArgs);
|
utils.setExpirationWarning = jest.fn().mockReturnValue();
|
||||||
|
memberRepo.createMember = jest.fn().mockResolvedValue(expectedMemberArgs);
|
||||||
const expectedReturn = {member: expectedMemberArgs, errors: []}
|
const expectedReturn = {member: expectedMemberArgs, errors: []}
|
||||||
// Act
|
// Act
|
||||||
const res = await memberHelper.addFullMember(authorId, mockMember.name, null, null, mockMember.propic);
|
const res = await memberHelper.addFullMember(authorId, mockMember.name, null, null, mockMember.propic);
|
||||||
@@ -598,8 +594,8 @@ describe('MemberHelper', () => {
|
|||||||
expect(res).toEqual(expectedReturn);
|
expect(res).toEqual(expectedReturn);
|
||||||
expect(utils.checkImageFormatValidity).toHaveBeenCalledWith(mockMember.propic);
|
expect(utils.checkImageFormatValidity).toHaveBeenCalledWith(mockMember.propic);
|
||||||
expect(utils.checkImageFormatValidity).toHaveBeenCalledTimes(1);
|
expect(utils.checkImageFormatValidity).toHaveBeenCalledTimes(1);
|
||||||
expect(database.members.create).toHaveBeenCalledWith(expectedMemberArgs);
|
expect(memberRepo.createMember).toHaveBeenCalledWith(expectedMemberArgs);
|
||||||
expect(database.members.create).toHaveBeenCalledTimes(1);
|
expect(memberRepo.createMember).toHaveBeenCalledTimes(1);
|
||||||
})
|
})
|
||||||
|
|
||||||
test('if checkImageFormatValidity throws error, call database.member.create with null value', async () => {
|
test('if checkImageFormatValidity throws error, call database.member.create with null value', async () => {
|
||||||
@@ -612,7 +608,7 @@ describe('MemberHelper', () => {
|
|||||||
proxy: null,
|
proxy: null,
|
||||||
propic: null
|
propic: null
|
||||||
}
|
}
|
||||||
database.members.create = jest.fn().mockResolvedValue(expectedMemberArgs);
|
memberRepo.createMember = jest.fn().mockResolvedValue(expectedMemberArgs);
|
||||||
const expectedReturn = {
|
const expectedReturn = {
|
||||||
member: expectedMemberArgs,
|
member: expectedMemberArgs,
|
||||||
errors: [`Tried to set profile picture to \"${mockMember.propic}\". error. ${enums.err.SET_TO_NULL}`]
|
errors: [`Tried to set profile picture to \"${mockMember.propic}\". error. ${enums.err.SET_TO_NULL}`]
|
||||||
@@ -621,19 +617,19 @@ describe('MemberHelper', () => {
|
|||||||
const res = await memberHelper.addFullMember(authorId, mockMember.name, null, null, mockMember.propic);
|
const res = await memberHelper.addFullMember(authorId, mockMember.name, null, null, mockMember.propic);
|
||||||
// Assert
|
// Assert
|
||||||
expect(res).toEqual(expectedReturn);
|
expect(res).toEqual(expectedReturn);
|
||||||
expect(database.members.create).toHaveBeenCalledWith(expectedMemberArgs);
|
expect(memberRepo.createMember).toHaveBeenCalledWith(expectedMemberArgs);
|
||||||
expect(database.members.create).toHaveBeenCalledTimes(1);
|
expect(memberRepo.createMember).toHaveBeenCalledTimes(1);
|
||||||
})
|
})
|
||||||
|
|
||||||
test('calls setExpirationWarning if attachmentExpiration exists', async () => {
|
test('calls setExpirationWarning if attachmentExpiration exists', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
utils.checkImageFormatValidity = jest.fn().mockResolvedValue(true);
|
utils.checkImageFormatValidity = jest.fn().mockResolvedValue(true);
|
||||||
jest.spyOn(memberHelper, 'setExpirationWarning').mockReturnValue(`${enums.misc.ATTACHMENT_EXPIRATION_WARNING}`);
|
utils.setExpirationWarning = jest.fn().mockReturnValue(`${enums.misc.ATTACHMENT_EXPIRATION_WARNING}`);
|
||||||
// Act
|
// Act
|
||||||
await memberHelper.addFullMember(authorId, mockMember.name, null, null, mockMember.propic, attachmentExpiration)
|
await memberHelper.addFullMember(authorId, mockMember.name, null, null, mockMember.propic, attachmentExpiration)
|
||||||
// Assert
|
// Assert
|
||||||
expect(memberHelper.setExpirationWarning).toHaveBeenCalledTimes(1);
|
expect(utils.setExpirationWarning).toHaveBeenCalledTimes(1);
|
||||||
expect(memberHelper.setExpirationWarning).toHaveBeenCalledWith(mockMember.propic, attachmentExpiration);
|
expect(utils.setExpirationWarning).toHaveBeenCalledWith(mockMember.propic, attachmentExpiration);
|
||||||
})
|
})
|
||||||
|
|
||||||
test('if all values are valid, call database.members.create', async () => {
|
test('if all values are valid, call database.members.create', async () => {
|
||||||
@@ -646,26 +642,24 @@ describe('MemberHelper', () => {
|
|||||||
proxy: mockMember.proxy,
|
proxy: mockMember.proxy,
|
||||||
propic: mockMember.propic
|
propic: mockMember.propic
|
||||||
}
|
}
|
||||||
database.members.create = jest.fn().mockResolvedValue(expectedMemberArgs);
|
memberRepo.createMember = jest.fn().mockResolvedValue(expectedMemberArgs);
|
||||||
utils.checkImageFormatValidity = jest.fn().mockResolvedValue(true);
|
utils.checkImageFormatValidity = jest.fn().mockResolvedValue(true);
|
||||||
|
utils.setExpirationWarning = jest.fn().mockReturnValue();
|
||||||
const expectedReturn = {member: expectedMemberArgs, errors: []}
|
const expectedReturn = {member: expectedMemberArgs, errors: []}
|
||||||
// Act
|
// Act
|
||||||
const res = await memberHelper.addFullMember(authorId, mockMember.name, mockMember.displayname, mockMember.proxy, mockMember.propic);
|
const res = await memberHelper.addFullMember(authorId, mockMember.name, mockMember.displayname, mockMember.proxy, mockMember.propic);
|
||||||
// Assert
|
// Assert
|
||||||
expect(res).toEqual(expectedReturn);
|
expect(res).toEqual(expectedReturn);
|
||||||
expect(database.members.create).toHaveBeenCalledWith(expectedMemberArgs);
|
expect(memberRepo.createMember).toHaveBeenCalledWith(expectedMemberArgs);
|
||||||
expect(database.members.create).toHaveBeenCalledTimes(1);
|
expect(memberRepo.createMember).toHaveBeenCalledTimes(1);
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('updateMemberField', () => {
|
describe('updateMemberField', () => {
|
||||||
const {database} = require('../../src/database.js');
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.spyOn(memberHelper, "setExpirationWarning").mockReturnValue(' warning');
|
utils.setExpirationWarning = jest.fn().mockReturnValue(`warning`);
|
||||||
database.members = {
|
memberRepo.updateMemberField = jest.fn().mockResolvedValue([1]);
|
||||||
update: jest.fn().mockResolvedValue([1])
|
|
||||||
};
|
|
||||||
})
|
})
|
||||||
|
|
||||||
test.each([
|
test.each([
|
||||||
@@ -680,20 +674,13 @@ describe('MemberHelper', () => {
|
|||||||
const res = await memberHelper.updateMemberField(authorId, mockMember.name, columnName, value, attachmentExpiration)
|
const res = await memberHelper.updateMemberField(authorId, mockMember.name, columnName, value, attachmentExpiration)
|
||||||
// Assert
|
// Assert
|
||||||
expect(res).toEqual(expected);
|
expect(res).toEqual(expected);
|
||||||
expect(database.members.update).toHaveBeenCalledTimes(1);
|
expect(memberRepo.updateMemberField).toHaveBeenCalledTimes(1);
|
||||||
expect(database.members.update).toHaveBeenCalledWith({[columnName]: value}, {
|
expect(memberRepo.updateMemberField).toHaveBeenCalledWith(authorId, mockMember.name, columnName, value)
|
||||||
where: {
|
|
||||||
name: {[Op.iLike]: mockMember.name},
|
|
||||||
userid: authorId
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
test('if database.members.update returns 0 rows changed, throw error', async () => {
|
test('if database.members.update returns 0 rows changed, throw error', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
database.members = {
|
memberRepo.updateMemberField = jest.fn().mockResolvedValue(0);
|
||||||
update: jest.fn().mockResolvedValue([0])
|
|
||||||
};
|
|
||||||
// Act
|
// Act
|
||||||
await expect(memberHelper.updateMemberField(authorId, mockMember.name, "displayname", mockMember.displayname)).rejects.toThrow(`Can't update ${mockMember.name}. ${enums.err.NO_MEMBER}.`);
|
await expect(memberHelper.updateMemberField(authorId, mockMember.name, "displayname", mockMember.displayname)).rejects.toThrow(`Can't update ${mockMember.name}. ${enums.err.NO_MEMBER}.`);
|
||||||
})
|
})
|
||||||
@@ -702,7 +689,7 @@ describe('MemberHelper', () => {
|
|||||||
describe('checkIfProxyExists', () => {
|
describe('checkIfProxyExists', () => {
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.spyOn(memberHelper, "getMembersByAuthor").mockResolvedValue([mockMember]);
|
memberRepo.getMembersByAuthor.mockResolvedValue([mockMember]);
|
||||||
})
|
})
|
||||||
|
|
||||||
test.each([
|
test.each([
|
||||||
@@ -720,8 +707,8 @@ describe('MemberHelper', () => {
|
|||||||
const res = await memberHelper.checkIfProxyExists(authorId, proxy)
|
const res = await memberHelper.checkIfProxyExists(authorId, proxy)
|
||||||
// Assert
|
// Assert
|
||||||
expect(res).toEqual(false)
|
expect(res).toEqual(false)
|
||||||
expect(memberHelper.getMembersByAuthor).toHaveBeenCalledTimes(1);
|
expect(memberRepo.getMembersByAuthor).toHaveBeenCalledTimes(1);
|
||||||
expect(memberHelper.getMembersByAuthor).toHaveBeenCalledWith(authorId);
|
expect(memberRepo.getMembersByAuthor).toHaveBeenCalledWith(authorId);
|
||||||
})
|
})
|
||||||
|
|
||||||
test.each([
|
test.each([
|
||||||
@@ -732,13 +719,13 @@ describe('MemberHelper', () => {
|
|||||||
// Act & Assert
|
// Act & Assert
|
||||||
await expect(memberHelper.checkIfProxyExists(authorId, proxy)).rejects.toThrow(error);
|
await expect(memberHelper.checkIfProxyExists(authorId, proxy)).rejects.toThrow(error);
|
||||||
|
|
||||||
expect(memberHelper.getMembersByAuthor).not.toHaveBeenCalled();
|
expect(memberRepo.getMembersByAuthor).not.toHaveBeenCalled();
|
||||||
})
|
})
|
||||||
|
|
||||||
test('--text returns correct error and calls getMemberByAuthor', async () => {
|
test('--text returns correct error and calls getMemberByAuthor', async () => {
|
||||||
await expect(memberHelper.checkIfProxyExists(authorId, "--text")).rejects.toThrow(enums.err.PROXY_EXISTS);
|
await expect(memberHelper.checkIfProxyExists(authorId, "--text")).rejects.toThrow(enums.err.PROXY_EXISTS);
|
||||||
expect(memberHelper.getMembersByAuthor).toHaveBeenCalledTimes(1);
|
expect(memberRepo.getMembersByAuthor).toHaveBeenCalledTimes(1);
|
||||||
expect(memberHelper.getMembersByAuthor).toHaveBeenCalledWith(authorId);
|
expect(memberRepo.getMembersByAuthor).toHaveBeenCalledWith(authorId);
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -2,16 +2,16 @@ const env = require('dotenv');
|
|||||||
env.config();
|
env.config();
|
||||||
|
|
||||||
|
|
||||||
jest.mock('../../src/helpers/memberHelper.js', () => {
|
jest.mock('../../src/repositories/memberRepo.js', () => {
|
||||||
return {
|
return {
|
||||||
memberHelper: {
|
memberRepo: {
|
||||||
getMembersByAuthor: jest.fn()
|
getMembersByAuthor: jest.fn()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const {memberHelper} = require("../../src/helpers/memberHelper.js");
|
|
||||||
const {messageHelper} = require("../../src/helpers/messageHelper.js");
|
const {messageHelper} = require("../../src/helpers/messageHelper.js");
|
||||||
|
const {memberRepo} = require("../../src/repositories/memberRepo");
|
||||||
|
|
||||||
describe('messageHelper', () => {
|
describe('messageHelper', () => {
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ describe('messageHelper', () => {
|
|||||||
const attachmentUrl = "../oya.png"
|
const attachmentUrl = "../oya.png"
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
memberHelper.getMembersByAuthor = jest.fn().mockImplementation((specificAuthorId) => {
|
memberRepo.getMembersByAuthor = jest.fn().mockImplementation((specificAuthorId) => {
|
||||||
if (specificAuthorId === "1") return membersFor1;
|
if (specificAuthorId === "1") return membersFor1;
|
||||||
if (specificAuthorId === "2") return membersFor2;
|
if (specificAuthorId === "2") return membersFor2;
|
||||||
if (specificAuthorId === "3") return membersFor3;
|
if (specificAuthorId === "3") return membersFor3;
|
||||||
|
|||||||
16
tsconfig.json
Normal file
16
tsconfig.json
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"lib": [
|
||||||
|
"es2021"
|
||||||
|
],
|
||||||
|
"target": "es2021",
|
||||||
|
"module": "commonjs",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"outDir": "./database/build",
|
||||||
|
"rootDir": "./database",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"sourceMap": true
|
||||||
|
}
|
||||||
|
}
|
||||||
7
variables.env
Normal file
7
variables.env
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
FLUXER_BOT_TOKEN=<>
|
||||||
|
POSTGRES_PASSWORD=<>
|
||||||
|
POSTGRES_ENDPOINT=postgres
|
||||||
|
PGADMIN_DEFAULT_EMAIL: <>
|
||||||
|
PGADMIN_DEFAULT_PASSWORD: <>
|
||||||
|
PGADMIN_CONFIG_SERVER_MODE: 'False'
|
||||||
|
PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED: 'False'
|
||||||
Reference in New Issue
Block a user