Compare commits

...

7 commits
v1.1.1 ... main

Author SHA1 Message Date
Bee
53c7367acf Merge branch 'main' of https://github.com/padlocks/Compatiplural 2025-01-02 12:26:14 -08:00
Bee
b33335d18a fix: crash when custom front is activated 2025-01-02 12:22:37 -08:00
bee!
a764d7b21c
Update dataManager.js 2024-06-19 22:01:14 -07:00
bee!
0f00694d2e
Update .env_example 2024-06-19 22:00:50 -07:00
bee!
2983fb83e3
Update README.md 2024-06-19 21:59:49 -07:00
bee!
5e0fe8aa0c
docker: add dockerfile, format log 2023-10-22 16:31:10 -07:00
bee!
1564a110e0
allow for publishing entire front instead
Signed-off-by: bee! <pascalyoung03@gmail.com>
2023-09-24 13:32:14 -07:00
7 changed files with 121 additions and 17 deletions

2
.dockerignore Normal file
View file

@ -0,0 +1,2 @@
node_modules
npm-debug.log

View file

@ -1,11 +1,13 @@
# Compatiplural # Compatiplural
url_override="https://v2.apparyllis.com" url_override="https://api.apparyllis.com"
api_version="v1" api_version="v1"
socket="wss://v2.apparyllis.com/v1/socket" socket="wss://api.apparyllis.com/v1/socket"
pk_url="https://api.pluralkit.me/v2" pk_url="https://api.pluralkit.me/v2"
token="SIMPLYPLURAL_TOKEN" token="SIMPLYPLURAL_TOKEN"
userId="abcd1234" userId="abcd1234"
pk_token= "PLURALKIT_TOKEN" pk_token= "PLURALKIT_TOKEN"
heartbeat=4500000 heartbeat=4500000
max_workers=1 max_workers=1
silence_connections=true silence_connections=true
full_swap=false
primary_tag="primary "

2
.gitignore vendored
View file

@ -5,3 +5,5 @@ config.json
package-lock.json package-lock.json
.env .env
.vercel .vercel
docker_build.bat
docker_run.bat

16
Dockerfile Normal file
View file

@ -0,0 +1,16 @@
FROM node:18
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
# If you are building your code for production
# RUN npm ci --omit=dev
# Bundle app source
COPY . .
#EXPOSE 8080
CMD [ "node", "index.js" ]

View file

@ -9,9 +9,9 @@ This project already has a Procfile set up, so it's super easy to get started. O
These can be set either in the .env file, in terminal, or in the config vars section of Heroku. These can be set either in the .env file, in terminal, or in the config vars section of Heroku.
| Setting | Default | Description | | Setting | Default | Description |
| ---------| ------- | ------------------ | | ---------| ------- | ------------------ |
| url_override | https://v2.apparyllis.com | The base URL for all SimplyPlural API requests. Unless you are running your own fork of Simply Plural, you shouldn't change this. | | url_override | https://api.apparyllis.com | The base URL for all SimplyPlural API requests. Unless you are running your own fork of Simply Plural, you shouldn't change this. |
| api_version | v1 | The target SimplyPlural API version. Unless you are running your own fork of Simply Plural, you shouldn't change this. | | api_version | v1 | The target SimplyPlural API version. Unless you are running your own fork of Simply Plural, you shouldn't change this. |
| socket | wss://v2.apparyllis.com/v1/socket | The socket URL for SimplyPlural. Unless you are running your own fork of Simply Plural, you shouldn't change this. | | socket | wss://api.apparyllis.com/v1/socket | The socket URL for SimplyPlural. Unless you are running your own fork of Simply Plural, you shouldn't change this. |
| pk_url | https://api.pluralkit.me/v2 | The base URL for all PluralKit API requests. Unless you are running your own fork of PluralKit, you shouldn't change this. | | pk_url | https://api.pluralkit.me/v2 | The base URL for all PluralKit API requests. Unless you are running your own fork of PluralKit, you shouldn't change this. |
| token | token_here | Your SimplyPlural account token. As of now, the only permission necessary is the Read permission. | | token | token_here | Your SimplyPlural account token. As of now, the only permission necessary is the Read permission. |
| userId | user_id | Your SimplyPlural account/system ID. You can find it in account info near the bottom. | | userId | user_id | Your SimplyPlural account/system ID. You can find it in account info near the bottom. |
@ -19,3 +19,4 @@ These can be set either in the .env file, in terminal, or in the config vars sec
| heartbeat | 4500000 | The time in miliseconds before the websocket client reconnects to the websocket server. | | heartbeat | 4500000 | The time in miliseconds before the websocket client reconnects to the websocket server. |
| max_workers | 1 | Max number of workers for processing enqueued tasks. This probably shouldn't be changed. | | max_workers | 1 | Max number of workers for processing enqueued tasks. This probably shouldn't be changed. |
| silence_connections | true | Whether or not to silence the websocket connection and authentication messages. | | silence_connections | true | Whether or not to silence the websocket connection and authentication messages. |
| full_swap | false | Determines whether to completely overwrite PluralKit's front with SimplyPlural's. No individual changes. |

View file

@ -50,9 +50,9 @@ async function findPrimary() {
return new Promise(async (resolve) => { return new Promise(async (resolve) => {
await Util.asyncForEach(fronters, async (fronter) => { await Util.asyncForEach(fronters, async (fronter) => {
if (fronter.content.customStatus) { if (fronter.content.customStatus) {
if (fronter.content.customStatus.toLowerCase().includes("primary")) { if (fronter.content.customStatus.toLowerCase().includes(Config.primary_tag)) {
let member = await system.getMemberById(fronter.content.member) let member = await system.getMemberById(fronter.content.member)
resolve(member.content.pkId) resolve({ name: member.content.name, pkId: member.content.pkId })
found = true found = true
} }
} }
@ -106,6 +106,82 @@ async function determineAction(eventData, frontData = []) {
return action return action
} }
async function swapFront() {
let system = new System(Config)
let front = await system.getFronters()
// start forming new front list
let newFront = []
let frontNames = []
for (member of front) {
let m = await system.getMemberById(member.content.member)
if (m.content && m.content.pkId) {
// fronting member pkID has been found
newFront.push(m.content.pkId)
frontNames.push(m.content.name)
}
else {
console.warn('::SimplyWS:: System member not found, this may be a custom front which is unsupported.')
}
}
// shift primary fronter to first in list
let primary = await findPrimary()
let primaryPK = primary.pkId
let primaryName = primary.name
if (primaryPK) {
if (newFront.indexOf(primaryPK) > 0) {
newFront.splice(newFront.indexOf(primaryPK), 1)
newFront.unshift(primaryPK)
}
if (frontNames.indexOf(primaryName) > 0) {
frontNames.splice(frontNames.indexOf(primaryName), 1)
frontNames.unshift(primaryName)
}
}
// post the new switch
let url = `${pkUrl}/systems/@me/switches`
await axios.post(url, JSON.stringify({ "members": newFront }), {
headers: pkHeader
})
.then(async (res) => {
// check if current front equals the new front
let front = await getPKFronters()
var equal = (front.length == newFront.length) && front.every(function(element, index) {
return element === newFront[index];
})
if (!equal) {
console.log('::SimplyWS:: Failed to swap front: ' + newFront)
await swapFront()
return
} else {
let formattedNames = frontNames.toString().replace(',',', ')
console.log(`::SimplyWS:: SimplyPlural -> PluralKit: ${formattedNames}`)
}
})
.catch(async err => {
let status = err.status || err.toJSON().status
if (status == 400) {
// if the fronter is already in the front, do nothing
return
}
else if (status == 404) {
return
}
else if (status == 429) {
// Too many requests
console.warn("::SimplyWS:: Too many requests, waiting to try again.")
setTimeout(async function () {
await swapFront()
}, 1000)
return
}
})
}
async function insertFront(member) { async function insertFront(member) {
// get current fronters and add new fronter // get current fronters and add new fronter
let fronters = await getPKFronters() let fronters = await getPKFronters()
@ -117,7 +193,7 @@ async function insertFront(member) {
} }
// find the "primary" fronter to move to the first element in the list // find the "primary" fronter to move to the first element in the list
let primary = await findPrimary() let primary = await findPrimary().pkId
if (primary) { if (primary) {
if (fronters.indexOf(primary) > 0) { if (fronters.indexOf(primary) > 0) {
fronters.splice(fronters.indexOf(primary), 1) fronters.splice(fronters.indexOf(primary), 1)
@ -178,11 +254,11 @@ async function removeFront(member) {
} }
// find the "primary" fronter to move to the first element in the list // find the "primary" fronter to move to the first element in the list
let p = await findPrimary() let primary = await findPrimary().pkId
if (p) { if (primary) {
if (fronters.indexOf(p) > 0) { if (fronters.indexOf(primary) > 0) {
fronters.splice(fronters.indexOf(p), 1) fronters.splice(fronters.indexOf(primary), 1)
fronters.unshift(p) fronters.unshift(primary)
} }
} }
@ -222,7 +298,7 @@ async function removeFront(member) {
async function updateCustomStatus(member) { async function updateCustomStatus(member) {
// find the "primary" fronter to move to the first element in the list // find the "primary" fronter to move to the first element in the list
let fronters = await getPKFronters() let fronters = await getPKFronters()
let primary = await findPrimary() let primary = await findPrimary().pkId
if (primary && fronters.length > 1 && (member.content.pkId == primary)) { if (primary && fronters.length > 1 && (member.content.pkId == primary)) {
if (fronters.indexOf(primary) >= 0) { if (fronters.indexOf(primary) >= 0) {
fronters.splice(fronters.indexOf(primary), 1) fronters.splice(fronters.indexOf(primary), 1)
@ -275,8 +351,9 @@ module.exports = {
getPKFronters, getPKFronters,
findPrimary, findPrimary,
determineAction, determineAction,
swapFront,
insertFront, insertFront,
removeFront, removeFront,
updateCustomStatus, updateCustomStatus,
calculateDiff calculateDiff
} }

View file

@ -3,7 +3,7 @@ dotenv.config()
const { Config, System } = require('simplyapi') const { Config, System } = require('simplyapi')
const { Util } = require('simplyapi') const { Util } = require('simplyapi')
const { initializeCache, determineAction, insertFront, removeFront, updateCustomStatus } = require('./dataManager') const { initializeCache, determineAction, swapFront, insertFront, removeFront, updateCustomStatus } = require('./dataManager')
const { const {
isMainThread, isMainThread,
@ -95,8 +95,12 @@ update = async (data) => {
await Util.asyncForEach(data.results, async (o) => { await Util.asyncForEach(data.results, async (o) => {
let system = new System(Config) let system = new System(Config)
let member = await system.getMemberById(o.content.member) let member = await system.getMemberById(o.content.member)
let swap = Config.full_swap
// insert // insert
if (o.operationType == "insert") { if (swap) {
swapFront()
}
else if (o.operationType == "insert") {
insertFront(member) insertFront(member)
} }
else { else {