forked from PluralFlux/PluralFlux
Compare commits
15 Commits
8fe53563d0
...
add-system
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee4dca2ae3 | ||
|
|
ff4dba3dfd | ||
|
|
96c2abc06a | ||
| c2a88804ad | |||
| 2b31cc2ae9 | |||
| b602e654ec | |||
| 732ad36bba | |||
| 8446559bfb | |||
| 14ef1581c1 | |||
| 10eab6de74 | |||
| d8682c2a1b | |||
| 20e8564c15 | |||
| 78cda7d3c4 | |||
| 21587dcb7a | |||
| aeb7d88ee9 |
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
|
||||
COPY --from=builder /app/node_modules ./node_modules
|
||||
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)
|
||||
|
||||
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
|
||||
All commands are prefixed by `pf;`. Currently only a few are implemented.
|
||||
|
||||
|
||||
@@ -22,4 +22,5 @@ services:
|
||||
volumes:
|
||||
- pgadmindata:/var/lib/pgadmin
|
||||
volumes:
|
||||
pgdata:
|
||||
pgdata:
|
||||
pgadmindata:
|
||||
@@ -7,13 +7,13 @@ env.config();
|
||||
|
||||
export const AppDataSource = new DataSource({
|
||||
type: "postgres",
|
||||
host: "localhost",
|
||||
host: process.env.POSTGRES_ENDPOINT,
|
||||
port: 5432,
|
||||
username: "postgres",
|
||||
password: process.env.POSTGRES_PASSWORD,
|
||||
database: "postgres",
|
||||
synchronize: false,
|
||||
logging: true,
|
||||
logging: false,
|
||||
entities: [path.join(__dirname, "./entity/*.{ts,js}")],
|
||||
migrations: [path.join(__dirname, "./migrations/*.{ts,js}")],
|
||||
migrationsRun: true,
|
||||
@@ -23,4 +23,4 @@ export const AppDataSource = new DataSource({
|
||||
null: "sql-null",
|
||||
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})
|
||||
@Unique("UQ_Member_userid_name", ['userid', 'name'])
|
||||
export class Member {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
|
||||
47
database/entity/System.ts
Normal file
47
database/entity/System.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import {Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, Unique} from "typeorm"
|
||||
|
||||
@Entity({name: "System", synchronize: true})
|
||||
@Unique("UQ_System_userid", ['userid'])
|
||||
@Unique("UQ_System_shortid", ['shortid'])
|
||||
export class System {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number
|
||||
|
||||
@Column({
|
||||
nullable: true,
|
||||
})
|
||||
shortid: string
|
||||
|
||||
@Column()
|
||||
userid: string
|
||||
|
||||
@Column({
|
||||
length: 100,
|
||||
nullable: true
|
||||
})
|
||||
name: string
|
||||
|
||||
@Column({
|
||||
type: "varchar",
|
||||
nullable: true,
|
||||
length: 100
|
||||
})
|
||||
fronter: string
|
||||
|
||||
@Column({
|
||||
nullable: true,
|
||||
})
|
||||
grouptag: string
|
||||
|
||||
@Column({
|
||||
nullable: true,
|
||||
})
|
||||
autoproxy: string
|
||||
|
||||
@CreateDateColumn({ type: 'timestamptz' })
|
||||
createdAt: Date
|
||||
|
||||
@UpdateDateColumn({ type: 'timestamptz' })
|
||||
updatedAt: Date
|
||||
}
|
||||
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"`);
|
||||
}
|
||||
|
||||
}
|
||||
14
database/migrations/1773670748825-update.ts
Normal file
14
database/migrations/1773670748825-update.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class Update1773670748825 implements MigrationInterface {
|
||||
name = 'Update1773670748825'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`CREATE TABLE "System" ("id" SERIAL NOT NULL, "shortid" character varying, "userid" character varying NOT NULL, "name" character varying(100), "fronter" character varying(100), "grouptag" character varying, "autoproxy" character varying, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), CONSTRAINT "UQ_System_shortid" UNIQUE ("shortid"), CONSTRAINT "UQ_System_userid" UNIQUE ("userid"), CONSTRAINT "PK_b8e3f6855de5a4758fcb59e5567" PRIMARY KEY ("id"))`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP TABLE "System"`);
|
||||
}
|
||||
|
||||
}
|
||||
13
database/migrations/1773749921832-update.ts
Normal file
13
database/migrations/1773749921832-update.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class Update1773749921832 implements MigrationInterface {
|
||||
name = 'Update1773749921832'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`INSERT INTO "System" ("userid") SELECT DISTINCT "userid" FROM "Member";`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DELETE from "System" USING "Member" WHERE "System".userid = "Member".userid;`);
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
"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",
|
||||
"run-migration": "typeorm-ts-node-commonjs migration:run -d database/data-source.ts"
|
||||
}
|
||||
|
||||
@@ -403,7 +403,7 @@ memberHelper.updateMemberField = async function (authorId, memberName, columnNam
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
memberHelper.getMemberInfo = function (member) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const {memberHelper} = require('./memberHelper.js');
|
||||
const {memberRepo} = require('../repositories/memberRepo.js');
|
||||
|
||||
const msgh = {};
|
||||
|
||||
@@ -39,7 +39,7 @@ msgh.parseCommandArgs = function(content, commandName) {
|
||||
* @returns {Promise<{model, string, bool}>} The proxy message object.
|
||||
*/
|
||||
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 (members.length === 0) {
|
||||
return;
|
||||
|
||||
@@ -36,12 +36,7 @@ memberRepo.getMembersByAuthor = async function (authorId) {
|
||||
* @returns {Promise<number>} Number of results removed.
|
||||
*/
|
||||
memberRepo.removeMember = async function (authorId, memberName) {
|
||||
const deleted = await members.delete({
|
||||
where: {
|
||||
name: ILike(memberName),
|
||||
userid: authorId
|
||||
}
|
||||
})
|
||||
const deleted = await members.delete({ name: ILike(memberName), userid: authorId })
|
||||
return deleted.affected;
|
||||
}
|
||||
|
||||
@@ -53,8 +48,8 @@ memberRepo.removeMember = async function (authorId, memberName) {
|
||||
* @returns {Promise<Member>} A successful inserted object.
|
||||
*/
|
||||
memberRepo.createMember = async function (createObj) {
|
||||
return members.insert({
|
||||
name: createObj.name, userid: createObj.authorId, displayname: createObj.displayName, proxy: createObj.proxy, propic: createObj.propic
|
||||
return await members.save({
|
||||
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.
|
||||
*/
|
||||
memberRepo.updateMemberField = async function (authorId, memberName, columnName, value) {
|
||||
const updated = await members.update({[columnName]: value}, {
|
||||
where: {
|
||||
name: ILike(memberName),
|
||||
userid: authorId
|
||||
}
|
||||
})
|
||||
const updated = await members.update({
|
||||
name: ILike(memberName),
|
||||
userid: authorId
|
||||
}, {[columnName]: value})
|
||||
return updated.affected;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,16 +2,16 @@ const env = require('dotenv');
|
||||
env.config();
|
||||
|
||||
|
||||
jest.mock('../../src/helpers/memberHelper.js', () => {
|
||||
jest.mock('../../src/repositories/memberRepo.js', () => {
|
||||
return {
|
||||
memberHelper: {
|
||||
memberRepo: {
|
||||
getMembersByAuthor: jest.fn()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const {memberHelper} = require("../../src/helpers/memberHelper.js");
|
||||
const {messageHelper} = require("../../src/helpers/messageHelper.js");
|
||||
const {memberRepo} = require("../../src/repositories/memberRepo");
|
||||
|
||||
describe('messageHelper', () => {
|
||||
|
||||
@@ -54,7 +54,7 @@ describe('messageHelper', () => {
|
||||
const attachmentUrl = "../oya.png"
|
||||
|
||||
beforeEach(() => {
|
||||
memberHelper.getMembersByAuthor = jest.fn().mockImplementation((specificAuthorId) => {
|
||||
memberRepo.getMembersByAuthor = jest.fn().mockImplementation((specificAuthorId) => {
|
||||
if (specificAuthorId === "1") return membersFor1;
|
||||
if (specificAuthorId === "2") return membersFor2;
|
||||
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