forked from PluralFlux/PluralFlux
Compare commits
6 Commits
8fe53563d0
...
webhook-re
| Author | SHA1 | Date | |
|---|---|---|---|
| 61d4e121a9 | |||
| 63b2f182bb | |||
| baf2f51773 | |||
| 6c9c253a70 | |||
| 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
|
||||||
@@ -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.
|
||||||
|
|
||||||
|
|||||||
@@ -22,4 +22,5 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- pgadmindata:/var/lib/pgadmin
|
- pgadmindata:/var/lib/pgadmin
|
||||||
volumes:
|
volumes:
|
||||||
pgdata:
|
pgdata:
|
||||||
|
pgadmindata:
|
||||||
@@ -7,13 +7,13 @@ env.config();
|
|||||||
|
|
||||||
export const AppDataSource = new DataSource({
|
export const AppDataSource = new DataSource({
|
||||||
type: "postgres",
|
type: "postgres",
|
||||||
host: "localhost",
|
host: process.env.POSTGRES_ENDPOINT,
|
||||||
port: 5432,
|
port: 5432,
|
||||||
username: "postgres",
|
username: "postgres",
|
||||||
password: process.env.POSTGRES_PASSWORD,
|
password: process.env.POSTGRES_PASSWORD,
|
||||||
database: "postgres",
|
database: "postgres",
|
||||||
synchronize: false,
|
synchronize: false,
|
||||||
logging: true,
|
logging: false,
|
||||||
entities: [path.join(__dirname, "./entity/*.{ts,js}")],
|
entities: [path.join(__dirname, "./entity/*.{ts,js}")],
|
||||||
migrations: [path.join(__dirname, "./migrations/*.{ts,js}")],
|
migrations: [path.join(__dirname, "./migrations/*.{ts,js}")],
|
||||||
migrationsRun: true,
|
migrationsRun: true,
|
||||||
@@ -23,4 +23,4 @@ export const AppDataSource = new DataSource({
|
|||||||
null: "sql-null",
|
null: "sql-null",
|
||||||
undefined: "throw",
|
undefined: "throw",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import {Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn} from "typeorm"
|
import {Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, Unique} from "typeorm"
|
||||||
|
|
||||||
@Entity({name: "Member", synchronize: true})
|
@Entity({name: "Member", synchronize: true})
|
||||||
|
@Unique("UQ_Member_userid_name", ['userid', 'name'])
|
||||||
export class Member {
|
export class Member {
|
||||||
|
|
||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn()
|
||||||
|
|||||||
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"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
"start": "ts-node src/bot.js",
|
"start": "ts-node src/bot.js",
|
||||||
"build-db": "tsc",
|
"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",
|
"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"
|
"run-migration": "typeorm-ts-node-commonjs migration:run -d database/data-source.ts"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ const { AppDataSource } = require("../database/data-source");
|
|||||||
env.config();
|
env.config();
|
||||||
|
|
||||||
const token = process.env.FLUXER_BOT_TOKEN;
|
const token = process.env.FLUXER_BOT_TOKEN;
|
||||||
|
const debug = process.env.debug;
|
||||||
|
|
||||||
if (!token) {
|
if (!token) {
|
||||||
console.error("Missing FLUXER_BOT_TOKEN environment variable.");
|
console.error("Missing FLUXER_BOT_TOKEN environment variable.");
|
||||||
@@ -63,12 +64,15 @@ module.exports.handleMessageCreate = async function(message) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(error) {
|
catch(error) {
|
||||||
console.error(error);
|
if(debug){console.error("An error occurred at unix timestamp " + Date.now() + "while processing the command: " + message + " with error:" + error);}
|
||||||
|
else{console.error(error);}
|
||||||
|
process.exit(2); //need this for now just to make sure the bot continues to restart on errors, since it would seem that fluxer.js doesn't define custom error types. TODO: map out some exit codes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
client.on(Events.Ready, () => {
|
client.on(Events.Ready, () => {
|
||||||
console.log(`Logged in as ${client.user?.username}`);
|
console.log(`Logged in as ${client.user?.username}`);
|
||||||
|
if(debug){console.log(Date.now() + `: Currently running in debug mode!`)}
|
||||||
});
|
});
|
||||||
|
|
||||||
let guildCount = 0;
|
let guildCount = 0;
|
||||||
|
|||||||
@@ -403,7 +403,7 @@ memberHelper.updateMemberField = async function (authorId, memberName, columnNam
|
|||||||
/**
|
/**
|
||||||
* Gets the details for a member.
|
* Gets the details for a member.
|
||||||
*
|
*
|
||||||
* @param {{Members, string[]}} member - The member object
|
* @param {{Member, string[]}} member - The member object
|
||||||
* @returns {EmbedBuilder} The member's info.
|
* @returns {EmbedBuilder} The member's info.
|
||||||
*/
|
*/
|
||||||
memberHelper.getMemberInfo = function (member) {
|
memberHelper.getMemberInfo = function (member) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const {memberHelper} = require('./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;
|
||||||
|
|||||||
@@ -36,12 +36,7 @@ memberRepo.getMembersByAuthor = async function (authorId) {
|
|||||||
* @returns {Promise<number>} Number of results removed.
|
* @returns {Promise<number>} Number of results removed.
|
||||||
*/
|
*/
|
||||||
memberRepo.removeMember = async function (authorId, memberName) {
|
memberRepo.removeMember = async function (authorId, memberName) {
|
||||||
const deleted = await members.delete({
|
const deleted = await members.delete({ name: ILike(memberName), userid: authorId })
|
||||||
where: {
|
|
||||||
name: ILike(memberName),
|
|
||||||
userid: authorId
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return deleted.affected;
|
return deleted.affected;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,8 +48,8 @@ memberRepo.removeMember = async function (authorId, memberName) {
|
|||||||
* @returns {Promise<Member>} A successful inserted object.
|
* @returns {Promise<Member>} A successful inserted object.
|
||||||
*/
|
*/
|
||||||
memberRepo.createMember = async function (createObj) {
|
memberRepo.createMember = async function (createObj) {
|
||||||
return members.insert({
|
return await members.save({
|
||||||
name: createObj.name, userid: createObj.authorId, displayname: createObj.displayName, proxy: createObj.proxy, propic: createObj.propic
|
name: createObj.name, userid: createObj.userid, displayname: createObj.displayname, proxy: createObj.proxy, propic: createObj.propic
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,12 +64,10 @@ memberRepo.createMember = async function (createObj) {
|
|||||||
* @returns {Promise<number>} A successful update.
|
* @returns {Promise<number>} A successful update.
|
||||||
*/
|
*/
|
||||||
memberRepo.updateMemberField = async function (authorId, memberName, columnName, value) {
|
memberRepo.updateMemberField = async function (authorId, memberName, columnName, value) {
|
||||||
const updated = await members.update({[columnName]: value}, {
|
const updated = await members.update({
|
||||||
where: {
|
name: ILike(memberName),
|
||||||
name: ILike(memberName),
|
userid: authorId
|
||||||
userid: authorId
|
}, {[columnName]: value})
|
||||||
}
|
|
||||||
})
|
|
||||||
return updated.affected;
|
return updated.affected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
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