Created
November 15, 2020 11:00
-
-
Save pirafrank/1d7d729082e063de343ee6df4aa0b47a to your computer and use it in GitHub Desktop.
Scriptable script to list your Hetzner servers in the app and on widgets. Requires iOS 14+ and Scriptable 1.6
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Your Hetzner API token | |
// Go to Cloud Console > [your project] > Security > API tokens | |
const token = "PUT_YOUR_TOKEN_HERE" // main | |
// urls | |
let listServersUrl = "https://api.hetzner.cloud/v1/servers" | |
let widget = await createWidget(listServersUrl) | |
if (config.runsInWidget) { | |
// The script runs inside a widget, so we pass our instance of ListWidget to be shown inside the widget on the Home Screen. | |
Script.setWidget(widget) | |
} else { | |
// The script runs inside the app | |
// list server | |
await list_servers(listServersUrl) | |
//widget.presentMedium() | |
} | |
// end the script | |
Script.complete() | |
// ********* | |
// functions | |
// ********* | |
async function list_servers(url) { | |
let req = new Request(url) | |
req.headers = { | |
Authorization: "Bearer " + token | |
} | |
let resp = await req.loadJSON() | |
console.log(resp) | |
let table = new UITable() | |
// inject row header in results | |
let header = {} | |
header.name = "Name" | |
header.status = "Status" | |
header.public_net = {} | |
header.public_net.ipv4 = {} | |
header.public_net.ipv4.ip = "IPv4" | |
header.protection = {} | |
header.protection.delete = "🔒" | |
resp.servers.splice(0,0,header) | |
// cycle results | |
for (server of resp.servers) { | |
let row = new UITableRow() | |
// cast dcell to a string, otherwise we will get an error like "Expected value of type UITableCell but got value of type null." | |
let nameCell = row.addText(server.name) | |
let statusCell = row.addText(server.status) | |
let ipCell = row.addText(server.public_net.ipv4.ip) | |
let protectionStatus | |
if(typeof server.protection.delete === "boolean") | |
protectionStatus = server.protection.delete ? "✅" : "❌" | |
else | |
protectionStatus = server.protection.delete | |
let protectedCell = row.addText(protectionStatus) | |
// Set the width weights of our cells | |
protectedCell.widthWeight = 15 | |
nameCell.widthWeight = 25 | |
statusCell.widthWeight = 20 | |
ipCell.widthWeight = 40 | |
// Set height of the row and spacing between cells, in pixels. | |
row.height = 60 | |
row.cellSpacing = 10 | |
// add row to table | |
table.addRow(row) | |
} | |
//QuickLook.present(table) | |
table.present() | |
} | |
async function get_number_of_servers (url) { | |
let req = new Request(url) | |
req.headers = { | |
Authorization: "Bearer " + token | |
} | |
let resp = await req.loadJSON() | |
// get number of servers per available status values | |
let result = resp.servers.reduce((acc, server) => { | |
(acc[server.status] = (acc[server.status] || 0) + 1, acc); | |
return acc; | |
}, {}); | |
return result | |
} | |
async function createWidget(url) { | |
// get number of servers from API | |
let servers = await get_number_of_servers(listServersUrl) | |
// Show widget icon and title | |
let title = "Hetzner" | |
let widget = new ListWidget() | |
// background | |
let gradient = new LinearGradient() | |
gradient.locations = [0, 1] | |
gradient.colors = [ | |
new Color("D72300"), | |
new Color("DF2700") | |
] | |
widget.backgroundGradient = gradient | |
let titleStack = widget.addStack() | |
let cloudSymbol = SFSymbol.named("cloud") | |
let cloudElement = titleStack.addImage(cloudSymbol.image) | |
cloudElement.imageSize = new Size(16, 16) | |
cloudElement.tintColor = Color.white() | |
cloudElement.imageOpacity = 0.7 | |
cloudElement.url = "https://google.com" | |
titleStack.addSpacer(4) | |
let titleElement = titleStack.addText(title) | |
titleElement.textColor = Color.white() | |
titleElement.textOpacity = 0.7 | |
titleElement.font = Font.mediumSystemFont(13) | |
widget.addSpacer(10) | |
// show real widget info | |
let infoText = "Your servers" | |
let infoElement = widget.addText(infoText) | |
infoElement.textColor = Color.white() | |
infoElement.font = Font.mediumSystemFont(14) | |
widget.addSpacer(6) | |
for (item in servers) { | |
let infoStack = widget.addStack() | |
let descElement = infoStack.addText(item.toUpperCase()) | |
descElement.textColor = Color.white() | |
descElement.font = Font.systemFont(16) | |
infoStack.addSpacer() | |
let numberOfServersElement = infoStack.addText(String(servers[item])) | |
numberOfServersElement.textColor = Color.white() | |
numberOfServersElement.font = Font.systemFont(16) | |
numberOfServersElement.minimumScaleFactor = 0.6 | |
} | |
return widget | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment