148 lines
6.4 KiB
JavaScript
148 lines
6.4 KiB
JavaScript
//Imports
|
|
import assets from "./assets.mjs"
|
|
|
|
//Setup
|
|
export default async function({login, q, imports, data, account}, {enabled = false, extras = false, token} = {}) {
|
|
//Plugin execution
|
|
try {
|
|
//Check if plugin is enabled and requirements are met
|
|
if ((!q.splatoon) || (!imports.metadata.plugins.splatoon.enabled(enabled, {extras})))
|
|
return null
|
|
|
|
//Load inputs
|
|
const {modes, "versus.limit":_versus_limit, "salmon.limit":_salmon_limit} = imports.metadata.plugins.splatoon.inputs({data, account, q})
|
|
|
|
//Save profile
|
|
{
|
|
const profile = `${imports.__module(import.meta.url)}/s3si/profile.json`
|
|
console.debug(`metrics/compute/${login}/plugins > splatoon > saving ${profile}`)
|
|
const parsed = JSON.parse(token)
|
|
if (!parsed?.loginState?.sessionToken)
|
|
throw new Error("Configuration is missing sessionToken")
|
|
await imports.fs.writeFile(profile, token)
|
|
}
|
|
|
|
//Fetch data
|
|
const allowed = {
|
|
files:["profile.json", "profile.json.swap", "export", "cache"],
|
|
net:["api.imink.app", "accounts.nintendo.com", "api.accounts.nintendo.com", "api-lp1.znc.srv.nintendo.net", "api.lp1.av5ja.srv.nintendo.net"]
|
|
}
|
|
await imports.run(`deno run --no-prompt --cached-only --no-remote --allow-read="${allowed.files}" --allow-write="${allowed.files}" --allow-net="${allowed.net}" index.ts --exporter file --no-progress`, {cwd: `${imports.__module(import.meta.url)}/s3si`}, {prefixed:false})
|
|
|
|
//Read fetched data
|
|
const fetched = (await Promise.all(
|
|
(await imports.fs.readdir(`${imports.__module(import.meta.url)}/s3si/export`))
|
|
.map(async file => JSON.parse(await imports.fs.readFile(`${imports.__module(import.meta.url)}/s3si/export/${file}`)))))
|
|
.sort((a, b) => new Date(b.data.detail.playedTime) - new Date(a.data.detail.playedTime))
|
|
console.debug(`metrics/compute/${login}/plugins > splatoon > fetched ${fetched.length} matches`)
|
|
|
|
//Versus mode
|
|
let vs = null
|
|
if (!((modes.length === 1)&&(modes[0] === "salmon-run"))) {
|
|
vs = {
|
|
matches:await Promise.all(fetched.filter(({type, data}) => (type === "VS")&&(modes.includes(data.detail.vsRule.name.toLocaleLowerCase().replace(/ /g, "-")))).slice(0, _versus_limit).map(async ({data}) => ({
|
|
mode:{
|
|
name:data.detail.vsRule.name,
|
|
icon:await imports.imgb64(assets.modes[data.detail.vsRule.name]),
|
|
},
|
|
result:data.detail.judgement,
|
|
knockout:data.detail.knockout ?? null,
|
|
teams:await Promise.all([data.detail.myTeam, ...data.detail.otherTeams].map(async team => ({
|
|
color:`#${Math.round(255*team.color.r).toString(16)}${Math.round(255*team.color.g).toString(16)}${Math.round(255*team.color.b).toString(16)}`,
|
|
score:((data.detail.vsRule.name === "Turf War") ? team.result?.paintRatio*100 : team.result?.score) ?? null,
|
|
players:await Promise.all(team.players.map(async ({name, byname, weapon, paint, result, isMyself:self}) => ({
|
|
name,
|
|
byname,
|
|
self,
|
|
weapon:{
|
|
name:weapon.name,
|
|
icon:await imports.imgb64(assets.weapons[weapon.name]),
|
|
},
|
|
special:{
|
|
name:weapon.specialWeapon.name,
|
|
icon:await imports.imgb64(assets.specials[weapon.specialWeapon.name]),
|
|
},
|
|
sub:{
|
|
name:weapon.subWeapon.name,
|
|
icon:await imports.imgb64(assets.subweapons[weapon.subWeapon.name]),
|
|
},
|
|
result:{
|
|
paint:paint ?? 0,
|
|
kill:result?.kill ?? 0,
|
|
death:result?.death ?? 0,
|
|
assist:result?.assist ?? 0,
|
|
special:result?.special ?? 0,
|
|
}
|
|
})))
|
|
}))),
|
|
awards:data.detail.awards,
|
|
date:data.detail.playedTime,
|
|
duration:data.detail.duration,
|
|
player:{
|
|
name:data.detail.player.name,
|
|
byname:data.detail.player.byname,
|
|
rank:data.listNode?.udemae ?? null,
|
|
},
|
|
stage:{
|
|
name:data.detail.vsStage.name,
|
|
icon:await imports.imgb64(assets.stages[data.detail.vsStage.name]),
|
|
}
|
|
})))
|
|
}
|
|
vs.player = vs.matches.at(-1)?.player ?? null
|
|
}
|
|
|
|
//Salmon run
|
|
let salmon = null
|
|
if (modes.includes("salmon-run")) {
|
|
salmon = {
|
|
matches:await Promise.all(fetched.filter(({type}) => type === "COOP").slice(0, _salmon_limit).map(async ({data}) => ({
|
|
weapons:await Promise.all(data.detail.myResult.weapons.map(async ({name}) => ({name, icon:await imports.imgb64(assets.weapons[name])}))),
|
|
special:{
|
|
name:data.detail.myResult.specialWeapon.name,
|
|
icon:await imports.imgb64(assets.specials[data.detail.myResult.specialWeapon.name])
|
|
},
|
|
eggs:{
|
|
golden:data.detail.myResult.goldenDeliverCount,
|
|
regular:data.detail.myResult.deliverCount,
|
|
},
|
|
defeated:await Promise.all(data.detail.enemyResults.map(async ({defeatCount:count, enemy:{name}}) => ({name, count, icon:await imports.imgb64(assets.salmon[name])}))),
|
|
rescues:data.detail.myResult.rescueCount,
|
|
rescued:data.detail.myResult.rescuedCount,
|
|
waves:data.detail.waveResults.map(({deliverNorm:quota, teamDeliverCount:delivered}) => ({quota, delivered})),
|
|
failed:data.detail.resultWave,
|
|
hazard:Math.round(data.detail.dangerRate*100),
|
|
boss:data.detail.bossResult ? {
|
|
defeated:data.detail.bossResult.hasDefeatBoss,
|
|
name:data.detail.bossResult.boss.name,
|
|
icon:await imports.imgb64(assets.salmon[data.detail.bossResult.boss.name])
|
|
} : null,
|
|
stage:{
|
|
name:data.detail.coopStage.name,
|
|
icon:await imports.imgb64(assets.stages[data.detail.coopStage.name])
|
|
},
|
|
date:data.detail.playedTime,
|
|
grade:data.detail.afterGrade.name,
|
|
player:data.detail.myResult.player.name,
|
|
}))),
|
|
}
|
|
salmon.player = {
|
|
name:salmon.matches.at(-1)?.player ?? null,
|
|
grade:salmon.matches.at(-1)?.grade ?? null,
|
|
}
|
|
}
|
|
|
|
//Results
|
|
return {
|
|
vs,
|
|
salmon,
|
|
icons:Object.fromEntries(await Promise.all(Object.entries(assets.icons).map(async ([k, v]) => [k, await imports.imgb64(v)])))
|
|
}
|
|
}
|
|
//Handle errors
|
|
catch (error) {
|
|
throw imports.format.error(error)
|
|
}
|
|
}
|
|
|