forked from apoc/chaospott_mumble
230 lines
7.0 KiB
JavaScript
230 lines
7.0 KiB
JavaScript
// Variables used by Scriptable.
|
|
// These must be at the very top of the file. Do not edit.
|
|
// icon-color: deep-green; icon-glyph: power-off;
|
|
const mumbleApiUrl = "https://apoc.uber.space/chaospott_mumble.json";
|
|
const spaceApiUrl = "https://status.chaospott.de/status.json";
|
|
const logoUrl = "https://chaospott.de/images/logo.png";
|
|
const logoLocalFilename = "chaospott_logo.png";
|
|
const mumbleLocalFilename = "chaospott_mumble.json";
|
|
const spaceLocalFilename = "chaospott_space.json";
|
|
|
|
const title = "Chaospott";
|
|
const subTitle = "Essen";
|
|
|
|
var colorSpaceClosed;
|
|
var colorSpaceOpen;
|
|
|
|
var widget = await createWidget();
|
|
|
|
if (!config.runsInWidget) {
|
|
await widget.presentSmall();
|
|
}
|
|
Script.setWidget(widget);
|
|
Script.complete();
|
|
|
|
|
|
async function createWidget(){
|
|
const colorOpenFresh = Color.green();
|
|
const colorOpenStale = new Color("#00ff00", 0.3);
|
|
const colorClosedFresh = new Color("#ff0000", 1.0);
|
|
const colorClosedStale = new Color("#ff0000", 0.3);
|
|
const colorLonelyFresh = new Color("#ff8800", 1.0);
|
|
const colorLonelyStale = new Color("#ff8800", 0.3);
|
|
var colorBorderOpen = colorOpenFresh;
|
|
var colorBorderClosed = colorClosedFresh;
|
|
var colorBorderLonely = colorLonelyFresh;
|
|
var colorMumbleOpen;
|
|
var colorMumbleClosed;
|
|
var colorMumbleLonely;
|
|
|
|
const widget = new ListWidget();
|
|
|
|
try {
|
|
var [mumbleStatus, mumbleFresh] = await getJSONandCache(mumbleLocalFilename, mumbleApiUrl);
|
|
var [spaceStatus, spaceFresh] = await getJSONandCache(spaceLocalFilename, spaceApiUrl);
|
|
} catch(err) {
|
|
const errorList = new ListWidget();
|
|
errorList.addText("Please enable internet for initial execution.");
|
|
return errorList;
|
|
}
|
|
|
|
if (mumbleFresh){
|
|
colorMumbleOpen = colorOpenFresh;
|
|
colorMumbleClosed = colorClosedFresh;
|
|
colorMumbleLonely = colorLonelyFresh;
|
|
} else {
|
|
colorMumbleOpen = colorOpenStale;
|
|
colorMumbleClosed = colorClosedStale;
|
|
colorMumbleLonely = colorLonelyStale;
|
|
colorBorderOpen = colorOpenStale;
|
|
colorBorderClosed = colorClosedStale;
|
|
colorBorderLonely = colorLonelyStale;
|
|
}
|
|
|
|
if (spaceFresh){
|
|
colorSpaceOpen = colorOpenFresh;
|
|
colorSpaceClosed = colorClosedFresh;
|
|
} else {
|
|
colorSpaceOpen = colorOpenStale;
|
|
colorSpaceClosed = colorClosedStale;
|
|
colorBorderOpen = colorOpenStale;
|
|
colorBorderClosed = colorClosedStale;
|
|
colorBorderLonely = colorLonelyStale;
|
|
}
|
|
|
|
if (spaceStatus.state.open){
|
|
widget.backgroundColor = colorBorderOpen;
|
|
} else {
|
|
switch(mumbleStatus.connected_users){
|
|
case 0:
|
|
widget.backgroundColor = colorBorderClosed;
|
|
break;
|
|
case 1:
|
|
widget.backgroundColor = colorBorderLonely;
|
|
break;
|
|
default:
|
|
widget.backgroundColor = colorBorderOpen;
|
|
}
|
|
}
|
|
|
|
widget.setPadding(0, 5, 0, 5);
|
|
canvasStack = widget.addStack();
|
|
canvasStack.setPadding(5, 15, 5, 15);
|
|
canvasStack.cornerRadius = 15;
|
|
canvasStack.layoutVertically();
|
|
canvasStack.backgroundColor = Color.dynamic(Color.white(), Color.black());
|
|
|
|
const headerStack = canvasStack.addStack();
|
|
const titleStack = headerStack.addStack();
|
|
|
|
titleStack.layoutVertically();
|
|
const titleText = titleStack.addText(title);
|
|
titleText.font = Font.regularSystemFont(16);
|
|
|
|
const subTitleText = titleStack.addText(subTitle);
|
|
subTitleText.font = Font.mediumSystemFont(10);
|
|
|
|
headerStack.addSpacer(5);
|
|
|
|
let logo = await getCachedImage(logoLocalFilename, logoUrl);
|
|
const logoImage = headerStack.addImage(logo);
|
|
logoImage.imageSize = new Size(30, 30);
|
|
|
|
canvasStack.addSpacer(5);
|
|
|
|
const middleRow = canvasStack.addStack();
|
|
spaceStatus.sensors.door_locked.forEach((obj,i,arr) => {
|
|
spaceView(middleRow, obj.location, obj.value);
|
|
if(i !== arr.length - 1){middleRow.addSpacer();}
|
|
});
|
|
|
|
const spaceLastUpdate = new Date(spaceStatus.state.lastchange*1000);
|
|
const spaceLastUpdateStack = canvasStack.addStack();
|
|
let spaceLastUpdateLabel = spaceLastUpdateStack.addDate(spaceLastUpdate);
|
|
spaceLastUpdateLabel.font = Font.mediumSystemFont(6);
|
|
spaceLastUpdateLabel.applyRelativeStyle();
|
|
|
|
const bottomRow = canvasStack.addStack();
|
|
bottomRow.useDefaultPadding();
|
|
bottomRow.centerAlignContent();
|
|
const mumbleLabelStack = bottomRow.addStack();
|
|
mumbleLabelStack.layoutVertically();
|
|
const labelMumble = mumbleLabelStack.addText("Mumble");
|
|
labelMumble.font = Font.regularSystemFont(14);
|
|
|
|
let mumbleLastUpdate = new Date(mumbleStatus.last_update * 1000 );
|
|
const labelMumbleUpdated = mumbleLabelStack.addDate(mumbleLastUpdate);
|
|
labelMumbleUpdated.font = Font.mediumSystemFont(6);
|
|
labelMumbleUpdated.applyTimeStyle();
|
|
|
|
bottomRow.addSpacer(29);
|
|
const mumbleValueStack = bottomRow.addStack();
|
|
const labelMumbleUser = mumbleValueStack.addText(mumbleStatus.connected_users.toString(10));
|
|
labelMumbleUser.font = Font.boldSystemFont(30);
|
|
switch(mumbleStatus.connected_users){
|
|
case 0:
|
|
labelMumbleUser.textColor = colorMumbleClosed;
|
|
break;
|
|
case 1:
|
|
labelMumbleUser.textColor = colorMumbleLonely;
|
|
break;
|
|
default:
|
|
labelMumbleUser.textColor = colorMumbleOpen;
|
|
}
|
|
|
|
canvasStack.addSpacer(4)
|
|
|
|
dateStack = canvasStack.addStack();
|
|
dateStack.layoutHorizontally();
|
|
dateStack.bottomAlignContent();
|
|
dateStack.addSpacer(41);
|
|
const now = new Date();
|
|
const timeLabel = dateStack.addDate(now)
|
|
timeLabel.font = Font.mediumSystemFont(10)
|
|
timeLabel.centerAlignText()
|
|
timeLabel.applyTimeStyle()
|
|
timeLabel.textColor = Color.darkGray()
|
|
|
|
return widget;
|
|
}
|
|
|
|
function spaceView(widget, space, lockStatus) {
|
|
const viewStack = widget.addStack();
|
|
viewStack.layoutVertically();
|
|
viewStack.centerAlignContent();
|
|
|
|
const spaceName = space.charAt(0).toUpperCase() + space.slice(1)
|
|
const label = viewStack.addText(spaceName);
|
|
label.font = Font.regularSystemFont(14);
|
|
|
|
const lock = SFSymbol.named("lock." + (lockStatus ? "" : "open.") + "fill");
|
|
lock.applyFont(Font.systemFont(20));
|
|
const lockImage = viewStack.addImage(lock.image);
|
|
lockImage.resizable = false;
|
|
lockImage.imageSize = new Size(25, 25);
|
|
if(lockStatus){
|
|
lockImage.tintColor = colorSpaceClosed;
|
|
} else {
|
|
lockImage.tintColor = colorSpaceOpen;
|
|
}
|
|
}
|
|
|
|
async function getCachedImage(localFilename, url) {
|
|
let fm = FileManager.local();
|
|
let dir = fm.cacheDirectory();
|
|
let path = fm.joinPath(dir, localFilename);
|
|
if (fm.fileExists(path)) {
|
|
return fm.readImage(path);
|
|
} else {
|
|
let r = new Request(url);
|
|
try {
|
|
let returnImage = await r.loadImage();
|
|
fm.writeImage(path, returnImage);
|
|
return returnImage;
|
|
} catch (err) {
|
|
// return placeholder
|
|
return SFSymbol.named("photo").image;
|
|
}
|
|
}
|
|
}
|
|
|
|
async function getJSONandCache(localFilename, url){
|
|
let fm = FileManager.local()
|
|
let dir = fm.cacheDirectory()
|
|
let path = fm.joinPath(dir, localFilename)
|
|
let r = new Request(url)
|
|
try {
|
|
var data = await r.loadJSON()
|
|
fm.writeString(path, JSON.stringify(data, null, 2))
|
|
var fresh = true;
|
|
} catch (err) {
|
|
if (fm.fileExists(path)) {
|
|
data = JSON.parse(fm.readString(path), null)
|
|
fresh = false;
|
|
} else {
|
|
throw "no data";
|
|
}
|
|
}
|
|
return [data, fresh];
|
|
}
|