sync-pk-sp/dataManager.js

360 lines
12 KiB
JavaScript
Raw Normal View History

const axios = require('axios')
2022-03-23 14:27:45 -07:00
const { Config, System, Util } = require('simplyapi')
const pkUrl = Config.pk_url
const pkHeader = {
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': Config.pk_token
}
let cache = {}
async function initializeCache() {
let system = new System(Config)
cache.frontHistory = await system.getFronters()
}
function unknownTarget(target) {
console.log('::SimplyWS:: Unknown update target: ' + target + '\n::SimplyWS:: Full message: ' + e)
}
function unrecognizedMessage(msg) {
console.log('::SimplyWS:: Unrecognized message: ' + msg + '\n::SimplyWS:: Full message: ' + e)
}
async function getPKFronters() {
let members = []
let fronters = await axios.get(`${pkUrl}/systems/@me/fronters`, {
headers: pkHeader
})
.catch((err) => {
if (err.toJSON().status == 429)
// Too many requests
setTimeout(async () => {
return await getPKFronters()
}, 1500)
})
if (fronters != undefined) {
fronters.data.members.forEach((key, value) => {
members.push(key.id)
})
}
return members
}
async function findPrimary() {
let found = false
let system = new System(Config)
let fronters = await system.getFronters()
return new Promise(async (resolve) => {
await Util.asyncForEach(fronters, async (fronter) => {
if (fronter.content.customStatus) {
if (fronter.content.customStatus.toLowerCase().includes(Config.primary_tag)) {
let member = await system.getMemberById(fronter.content.member)
2023-10-22 16:31:10 -07:00
resolve({ name: member.content.name, pkId: member.content.pkId })
found = true
}
}
})
if (!found)
resolve(false)
})
}
async function determineAction(eventData, frontData = []) {
if (frontData.length == 0)
return 'remove'
let action = ''
// check for cache
if (!cache.frontHistory) {
let system = new System(Config)
let frontHistory = await system.getFronters()
cache.frontHistory = frontHistory
}
// get the difference between cached history and current front
let diff = await calculateDiff(cache.frontHistory, frontData)
// we handle one thing at a time, although this should be expanded since you can modify multiple custom statuses at once
if (diff.length >= 1) {
if (diff[0].content.customStatus || eventData.content.customStatus || diff[0].content.customStatus == "" || eventData.content.customStatus == "") {
// check if customStatus value is in cache
let foundInCache = Object.keys(cache.frontHistory).filter((key) => {
return cache.frontHistory[key] === diff[0].content.customStatus
})
// if value is unique, publish action
if (foundInCache.length == 0) {
action = 'customStatus'
}
}
else {
if (eventData.content.customStatus == '')
return 'customStatus'
console.error('::SimplyWS:: Unrecognized diff: ' + JSON.stringify(diff))
}
}
else {
// if there's an endTime, it was a removal event
if (eventData.content.endTime && !eventData.content.live) {
action = 'remove'
}
}
return action
}
async function swapFront() {
let system = new System(Config)
let front = await system.getFronters()
// start forming new front list
let newFront = []
2023-10-22 16:31:10 -07:00
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)
2023-10-22 16:31:10 -07:00
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()
2023-10-22 16:31:10 -07:00
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 {
2023-10-22 16:31:10 -07:00
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) {
// get current fronters and add new fronter
let fronters = await getPKFronters()
if (!fronters.includes(member.content.pkId)) {
fronters.push(member.content.pkId)
} else {
console.warn('::SimplyWS:: Member already in fronters: ' + member.content.pkId)
return
}
// find the "primary" fronter to move to the first element in the list
2023-10-22 16:31:10 -07:00
let primary = await findPrimary().pkId
if (primary) {
if (fronters.indexOf(primary) > 0) {
fronters.splice(fronters.indexOf(primary), 1)
fronters.unshift(primary)
}
}
// post the new switch
let url = `${pkUrl}/systems/@me/switches`
await axios.post(url, JSON.stringify({ "members": fronters }), {
headers: pkHeader
})
.then(async (res) => {
let front = await getPKFronters()
if (!front.includes(member.content.pkId)) {
console.log('::SimplyWS:: Failed to insert fronter: ' + member.content.pkId)
await insertFront(member)
return
} else {
console.log('::SimplyWS:: ' + member.content.name + ' was added to the front.')
}
})
.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) {
// member not found
console.error("::SimplyWS:: Could not find member: " + member.content.pkId)
let index = fronters.indexOf(member.content.pkId)
fronters.splice(index, 1)
return
}
else if (status == 429) {
// Too many requests
console.warn("::SimplyWS:: Too many requests, waiting to try again.")
let index = fronters.indexOf(member.content.pkId)
fronters.splice(index, 1)
setTimeout(async function () {
await insertFront(member)
}, 1000)
return
}
})
}
async function removeFront(member) {
let fronters = await getPKFronters()
if (fronters.includes(member.content.pkId)) {
let index = fronters.indexOf(member.content.pkId)
fronters.splice(index, 1)
} else {
console.warn('::SimplyWS:: Member is not in front: ' + member.content.pkId)
return
}
// find the "primary" fronter to move to the first element in the list
2023-10-22 16:31:10 -07:00
let primary = await findPrimary().pkId
if (primary) {
if (fronters.indexOf(primary) > 0) {
fronters.splice(fronters.indexOf(primary), 1)
fronters.unshift(primary)
}
}
let url = `${pkUrl}/systems/@me/switches`
await axios.post(url, JSON.stringify({ "members": fronters }), {
headers: pkHeader
})
.then(async (res) => {
let front = await getPKFronters()
if (front.includes(member.content.pkId)) {
console.log('::SimplyWS:: Failed to remove fronter: ' + member.content.pkId)
await removeFront(member)
return
} else {
console.log('::SimplyWS:: ' + member.content.name + ' was removed from the front.')
}
})
.catch(async err => {
let status = err.status || err.toJSON().status
if (status == 400) {
// fronter is already not in front
console.warn("::SimplyWS:: " + member.content.name + " is not in the front.")
return
}
else if (status == 429) {
// Too many requests
console.warn("::SimplyWS:: Too many requests, waiting to try again.")
fronters.push(member.content.pkId)
setTimeout(async function () {
await removeFront(member)
}, 1000)
return
}
})
}
async function updateCustomStatus(member) {
// find the "primary" fronter to move to the first element in the list
let fronters = await getPKFronters()
2023-10-22 16:31:10 -07:00
let primary = await findPrimary().pkId
if (primary && fronters.length > 1 && (member.content.pkId == primary)) {
if (fronters.indexOf(primary) >= 0) {
fronters.splice(fronters.indexOf(primary), 1)
fronters.unshift(primary)
// post the new switch
axios.post(`${pkUrl}/systems/@me/switches`, JSON.stringify({ "members": fronters }), {
headers: pkHeader
})
.catch(async err => {
if (err.toJSON().status == 429)
//Too many requests
console.warn("::SimplyWS:: Too many requests, waiting to try again.")
setTimeout(function () {
2022-05-09 22:49:16 -07:00
updateCustomStatus(member)
}, 1000)
return
})
console.log('::SimplyWS:: ' + member.content.name + ' is now the primary fronter.')
}
}
else {
console.log('::SimplyWS:: ' + member.content.name + ' changed custom status.')
}
}
const transform = require('lodash.transform')
const isEqual = require('lodash.isequal')
const isObject = require('lodash.isobject')
async function calculateDiff(origObj, newObj) {
return new Promise(function (resolve) {
changes = (newObj, origObj) => {
let arrayIndexCounter = 0
return transform(newObj, function (result, value, key) {
if (!isEqual(value, origObj[key])) {
2022-05-09 22:49:16 -07:00
let resultKey = Array.isArray(origObj) ? arrayIndexCounter++ : key
result[resultKey] = (isObject(value) && isObject(origObj[key])) ? changes(value, origObj[key]) : value
}
})
}
resolve(changes(newObj, origObj))
})
}
module.exports = {
initializeCache,
unknownTarget,
unrecognizedMessage,
getPKFronters,
findPrimary,
determineAction,
swapFront,
insertFront,
removeFront,
updateCustomStatus,
calculateDiff
2024-06-19 22:01:14 -07:00
}