-
Notifications
You must be signed in to change notification settings - Fork 0
/
Status Slack Widget.scriptable
12 lines (11 loc) · 19.8 KB
/
Status Slack Widget.scriptable
1
2
3
4
5
6
7
8
9
10
11
12
{
"always_run_in_app" : false,
"icon" : {
"color" : "deep-purple",
"glyph" : "hashtag"
},
"name" : "Status Slack Widget 1",
"script" : "\/\/ Variables used by Scriptable.\n\/\/ These must be at the very top of the file. Do not edit.\n\/\/ icon-color: purple; icon-glyph: hashtag;\n\/\/ Script is written by iamrbn - GitHub (u\/iamrbn → Reddit, iamrbn_ → Twitter)\n\/\/ Script = https:\/\/github.com\/iamrbn\/slack-status\n\nconst scriptURL = 'https:\/\/raw.githubusercontent.com\/iamrbn\/slack-status\/main\/slack-status-widget.js'\nconst scriptVersion = '1.2.1'\nconst bgColor = Color.dynamic(Color.white(), new Color(\"#481349\"));\nconst txtColor = Color.dynamic(Color.black(), Color.white());\nconst newDate = new Date();\nconst dateFormatter = new DateFormatter();\nconst widgetSize = config.widgetFamily;\nconst fm = FileManager.iCloud();\nconst dir = fm.joinPath(fm.documentsDirectory(), \"slack-status-widget\");\nif (!fm.fileExists(dir)) fm.createDirectory(dir);\nconst getStatusNotifications = true;\nconst nKey = Keychain;\nconst top = Color.dynamic(new Color('#ffffff'), new Color('#4E1E54'));\nconst middle = Color.dynamic(new Color('#EDEDED'), new Color('#481C4D'));\nconst bottom = Color.dynamic(new Color('#D4D4D4'), new Color('#441A49'));\nconst bgGradient = new LinearGradient();\n bgGradient.locations = [0, 0.4, 1];\n bgGradient.colors = [top, middle, bottom]; \n\nlet nParameter = await args.notification;\nlet refreshInt = await args.widgetParameter;\nif (refreshInt == null) refreshInt = 30; \/\/in minutes\n\nlet api;\ntry { \n api = await new Request('https:\/\/status.slack.com\/api\/v2.0.0\/current').loadJSON(); \n noInternet = false;\n emoji = \" ✅ \";\n if (api.status != \"ok\") {\n dateCreated = api.date_created;\n dateUpdated = api.date_updated;\n dataID = api.active_incidents[0].id;\n dateCreated2 = api.active_incidents[0].date_created;\n dateUpdated2 = api.active_incidents[0].date_updated;\n dataTitle = api.active_incidents[0].title;\n dataType = api.active_incidents[0].type;\n dataStatus = api.active_incidents[0].status;\n dataURL = api.active_incidents[0].url;\n dataServices = api.active_incidents[0].services;\n dateCreatedBody = api.active_incidents[0].notes[0].date_created;\n dataBody = api.active_incidents[0].notes[0].body;\n\n if (dataType == \"incident\" || \"active\") emoji = \" ⚠️ \";\n else if (dataType == \"outage\") emoji = \" ⛔️ \";\n else if (dataType == \"notice\") emoji = \" 🚩 \";\n else if (dataType == \"maintenance\") emoji = \" 🔧 \";\n };\n} catch (e) {\n logError(e);\n noInternet = true;\n if (config.runsInApp) await presentAlert(String(e));\n};\n \nif (config.runsInApp && !noInternet) {\n\tawait presentMenu();\n} else if (config.runsInWidget) {\n switch (widgetSize) {\n \tcase \"small\":\n if (noInternet) widget = await createErrorWidget(10);\n else widget = await createSmallWidget();\n\tbreak;\n \tcase \"medium\":\n if (noInternet) widget = await createErrorWidget(20);\n else widget = await createMediumWidget();\n\tbreak;\n \tcase \"large\":\n if (noInternet) widget = await createErrorWidget(25);\n \t else widget = await createLargeWidget();\n\tbreak;\n \tdefault:\n widget = await createErrorWidget();\n\t}\n\tScript.setWidget(widget);\n} else if (config.runsInNotification) QuickLook.present(await getImageFor(nParameter.userInfo.imgName));\n\nif (!nKey.contains(\"current_issue\")) nKey.set(\"current_issue\", api.date_updated);\nlog(nKey.get(\"current_issue\"));\nif (getStatusNotifications) {\nif (nKey.get(\"current_issue\") != api.date_updated && api.status != 'ok') createIssueNotification();\nelse if (nKey.get(\"current_issue\") != api.date_updated && api.status == 'ok') createOkNotification();\n};\n\n\n\/\/ ############ SETUP SMALL WIDGET ############\nasync function createSmallWidget() {\n let widget = new ListWidget();\n widget.url = \"https:\/\/status.slack.com\";\n widget.backgroundGradient = bgGradient\n widget.refreshAfterDate = new Date(Date.now() + 1000 * 60 * refreshInt);\n\n await createHeader(widget, 20, 17)\n\n widget.addSpacer(3);\n\n\tif (api.status == 'ok') {\n\t\tstatusImage = widget.addImage(await getImageFor(api.status));\n statusTitle = widget.addText(\"is up and running\");\n\t\twidget.addSpacer();\n\t} else {\n\t\tstatusImage = widget.addImage(await getImageFor(dataType));\n\t\theadline = widget.addText(\"Trouble with\");\n\t\theadline.textColor = Color.red();\n\t\theadline.font = Font.semiboldSystemFont(11);\n\t\theadline.centerAlignText();\n\n statusTitle = widget.addText(String(dataServices).replace(\" \", \"\\n\"));\n statusTitle.textColor = Color.red();\n statusTitle.lineLimit = 3;\n statusTitle.minimumScaleFactor = 0.8;\n\t};\n \n statusImage.imageSize = new Size(77, 77); \n statusImage.centerAlignImage();\n \n statusTitle.font = Font.lightSystemFont(12); \n statusTitle.centerAlignText();\n\n let uCheck = await updateCheck(scriptVersion)\n if (uCheck.version > scriptVersion) {\n updateInfo = widget.addText(`Update ${uCheck.version} Available!`)\n updateInfo.font = Font.lightRoundedSystemFont(11)\n updateInfo.centerAlignText()\n updateInfo.textColor = Color.red()\n widgetURL = 'https:\/\/github.com\/iamrbn\/slack-status\/tree\/main'\n widget.url = \"https:\/\/status.slack.com\"\n}\n\n dateFormatter.useShortTimeStyle();\n let footer = widget.addText(\"Last Update \" + dateFormatter.string(new Date()));\n footer.font = Font.mediumSystemFont(9);\n footer.textOpacity = 0.16;\n footer.centerAlignText();\n\n\treturn widget;\n};\n\n\/\/ ########### SETUP MEDIUM WIDGET ###########\nasync function createMediumWidget() {\n let widget = new ListWidget();\n widget.setPadding(10, 10, 5, 10);\n widget.backgroundGradient = bgGradient\n widget.refreshAfterDate = new Date(Date.now() + 1000 * 60 * refreshInt);\n\n await createHeader(widget, 25, 25);\n\n\twidget.addSpacer();\n\n let mainStack = widget.addStack();\n\n\t\/\/ Left stack contains the status text\n let leftStack = mainStack.addStack();\n leftStack.layoutVertically();\n\n\t\/\/ Right stack contains the status icon\n let rightStack = mainStack.addStack();\n rightStack.layoutVertically();\n\n\tif (api.status == 'ok') {\n rightStack.setPadding(0, 30, 15, 0);\n leftStack.setPadding(0, 10, 0, 0);\n\n leftStack.addSpacer(25);\n\n statusTitle = leftStack.addText(\"Slack is up and running 🚀\");\n statusTitle.font = Font.lightSystemFont(14);\n\n leftStack.addSpacer(7);\n\n linkStack = leftStack.addStack();\n linkStack.centerAlignContent();\n linkStack.url = \"https:\/\/slack.com\/help\/articles\/205138367-Troubleshoot-connection-issues\";\n\n linkElement = linkStack.addText(\"Having trouble? \");\n linkElement.textColor = Color.gray();\n linkElement.font = Font.lightSystemFont(11);\n linkElement.textOpacity = 0.4;\n\n linkSymbolElement = linkStack.addImage(SFSymbol.named(\"safari\").image);\n linkSymbolElement.imageSize = new Size(12, 12);\n linkSymbolElement.tintColor = Color.gray();\n linkSymbolElement.imageOpacity = 0.2;\n \n StatusImage = rightStack.addImage(await getImageFor('ok'));\n StatusImage.url = \"https:\/\/status.slack.com\";\n\t} else {\n\t\tStatusImage = rightStack.addImage(await getImageFor(dataType));\n\n\t\tStatusImage.url = dataURL;\n\t\tleftStack.setPadding(0, 5, 0, 0);\n\t\trightStack.setPadding(0, 5, 5, 0);\n\n\t\twidget.addSpacer(7);\n\n\t\tapiTitle = leftStack.addText(dataTitle);\n\t\tapiTitle.font = Font.boldSystemFont(12);\n\t\tapiTitle.textColor = Color.red();\n\t\tapiTitle.lineLimit = 2;\n\t\tapiTitle.minimumScaleFactor = 0.5;\n\n\t\tleftStack.addSpacer(3);\n\n\t\tapiBody = leftStack.addText(dataBody);\n\t\tapiBody.font = Font.lightSystemFont(12);\n\t\tapiBody.minimumScaleFactor = 0.6;\n\t\tapiBody.textColor = Color.red();\n\n\t\tleftStack.addSpacer(3);\n\n linkStack = leftStack.addStack();\n linkStack.centerAlignContent();\n linkStack.url = dataURL;\n \n linkSymbolElement = linkStack.addImage(SFSymbol.named(\"info.circle\").image);\n linkSymbolElement.imageSize = new Size(9, 9);\n linkSymbolElement.tintColor = Color.blue();\n \n linkStack.addSpacer(3);\n\n\t\tlinkElement = linkStack.addText(\"Read more about \" + dataType + \" ID \" + dataID);\n linkElement.textColor = Color.blue();\n linkElement.font = new Font(\"PingFangTC-Thin\", 10);\n\t}\n\n let uCheck = await updateCheck(scriptVersion)\n if (uCheck.version > scriptVersion) {\n updateInfo = widget.addText(`Update ${uCheck.version} Available!`)\n updateInfo.font = Font.regularRoundedSystemFont(14)\n updateInfo.url = 'https:\/\/github.com\/iamrbn\/slack-status\/tree\/main'\n updateInfo.textColor = Color.red()\n updateInfo.centerAlignText()\n widget.url = 'https:\/\/github.com\/iamrbn\/slack-status\/tree\/main'\n}\n\n dateFormatter.useShortDateStyle();\n dateFormatter.useShortTimeStyle();\n\n let footer = widget.addText(\"Last Widget Refresh \" + dateFormatter.string(newDate));\n footer.font = Font.mediumSystemFont(9);\n footer.textOpacity = 0.16;\n footer.centerAlignText();\n\n\treturn widget;\n}\n\n\n\/\/ ############ SETUP LARGE WIDGET ##############\nasync function createLargeWidget() {\n let widget = new ListWidget();\n widget.backgroundGradient = bgGradient;\n widget.setPadding(15, 15, 5, 15);\n widget.refreshAfterDate = new Date(Date.now() + 1000 * 60 * refreshInt);\n \n await createHeader(widget, 25, 23)\n\n let uCheck = await updateCheck(scriptVersion)\n if (uCheck.version > scriptVersion) {\n widget.addSpacer(7)\n updateInfo = widget.addText(`Update ${uCheck.version} Available!`)\n updateInfo.font = Font.regularRoundedSystemFont(14)\n updateInfo.url = 'https:\/\/github.com\/iamrbn\/slack-status\/tree\/main'\n updateInfo.textColor = Color.red()\n updateInfo.centerAlignText()\n widget.url = 'https:\/\/github.com\/iamrbn\/slack-status\/tree\/main'\n}\n widget.addSpacer();\n\n\t\/\/ content of the widget\n\tif (api.status == 'ok') {\n\t\twidget.addSpacer();\n\t\tStatusImage = widget.addImage(await getImageFor(\"ok\"));\n\n\t\twidget.addSpacer();\n\n\t\tStatusImage.centerAlignImage();\n\t\tStatusImage.imageSize = new Size(77, 77);\n\t\tStatusImage.url = \"https:\/\/status.slack.com\";\n\t\tstatusTitle = widget.addText(\"Slack is up and running 🚀\");\n\t\tstatusTitle.font = new Font(\"Futura-Medium\", 17);\n\n\t\twidget.addSpacer(5);\n\n\t\tlet linkStack = widget.addStack();\n\t\tlinkStack.setPadding(0, 103, 0, 0);\n\t\tlinkStack.centerAlignContent();\n\t\tlinkStack.url = \"https:\/\/slack.com\/help\/articles\/205138367-Troubleshoot-connection-issues\";\n\n\t\tlet linkElement = linkStack.addText(\"Having trouble? \");\n\t\tlinkElement.textColor = Color.gray();\n\t\tlinkElement.font = Font.lightSystemFont(11);\n\t\tlinkElement.textOpacity = 0.4;\n\n\t\tlet linkSymbolElement = linkStack.addImage(SFSymbol.named(\"safari\").image);\n\t\tlinkSymbolElement.imageSize = new Size(12, 12);\n\t\tlinkSymbolElement.tintColor = Color.gray();\n\t\tlinkSymbolElement.imageOpacity = 0.2;\n\n\t\tstatusTitle.font = new Font(\"Futura-Medium\", 17);\n\t\tstatusTitle.centerAlignText();\n\t\twidget.addSpacer();\n} else {\n\t\tStatusImage = widget.addImage(await getImageFor(dataType));\n\t\tStatusImage.imageSize = new Size(77, 77);\n\t\tStatusImage.centerAlignImage();\n\t\tStatusImage.url = dataURL;\n\n\t\tapiTitle = widget.addText(dataTitle);\n\t\tapiTitle.font = Font.semiboldSystemFont(14);\n\t\tapiTitle.minimumScaleFactor = 0.5;\n\t\tapiTitle.textColor = Color.red();\n\t\tapiTitle.centerAlignText();\n\t\tapiTitle.lineLimit = 2;\n\n\t\twidget.addSpacer(3);\n\n\t\tapiBody = widget.addText(dataBody);\n\t\tapiBody.font = Font.lightSystemFont(10);\n\t\tapiBody.minimumScaleFactor = 0.7;\n\t\tapiBody.textColor = Color.red();\n\t\tapiBody.centerAlignText();\n\n \tlinkStack = widget.addStack();\n\t\tlinkStack.centerAlignContent();\n\t\tlinkStack.setPadding(0, 50, 0, 0);\n\t\tlinkStack.url = dataURL;\n\n\t\tlinkElement = linkStack.addText(\"Read more about \" + dataType + \" ID \" + dataID);\n\t\tlinkElement.textColor = Color.blue();\n\t\tlinkElement.font = Font.lightSystemFont(12);\n\n\t\tlinkStack.addSpacer(3);\n\n\t\tlinkSymbolElement = linkStack.addImage(SFSymbol.named(\"info.circle\").image);\n\t\tlinkSymbolElement.imageSize = new Size(12, 12);\n\t\tlinkSymbolElement.tintColor = Color.blue();\n\t}\n\n\twidget.addSpacer();\n \n await addString(widget, \"Login\/SSO\", \"Connections\");\n await addString(widget, \"Messaging\", \"Link Previews\");\n await addString(widget, \"Posts\/Files\", \"Notifications\");\n await addString(widget, \"Calls\", \"Search\");\n await addString(widget, \"Apps\/APIs\/\\nIntegrations\", \"Workspace\/Org\/\\nAdministration\");\n\n\twidget.addSpacer();\n\n\t\/\/ shows the last widget update\n\tdateFormatter.useMediumDateStyle();\n\tdateFormatter.useShortTimeStyle();\n let footer = widget.addText(\"Last Widget Refresh \" + dateFormatter.string(newDate));\n footer.font = Font.mediumSystemFont(9);\n footer.textOpacity = 0.16;\n footer.centerAlignText();\n\n\treturn widget;\n};\n\nasync function createErrorWidget(pddng) {\n let errWidget = new ListWidget();\n errWidget.setPadding(pddng, pddng, pddng, pddng);\n errWidget.backgroundGradient = bgGradient;\n errWidget.addImage(await getImageFor(\"sadSlackBot-badConnection\")).cornerRadius = 20;\n errWidget.addSpacer();\n wTitle = errWidget.addText(\"No API Response\").font = Font.headline();\n wSubtitle = errWidget.addText(\"Please ckeck your internet connection\").font = Font.subheadline();\n return errWidget;\n};\n\n\/\/=============================================\n\/\/============== FUNCTION AREA ================\n\/\/=============================================\n\nfunction createIssueNotification() {\n let notify = new Notification();\n notify.title = `Slack ${api.active_incidents[0].type}`.toUpperCase();\n notify.subtitle = `Trouble with: ${api.active_incidents[0].services}`;\n notify.openURL = api.active_incidents[0].url;\n notify.body = api.active_incidents[0].notes[0].body;\n notify.addAction(\"Open Web-Dashboard ↗\", \"https:\/\/status.slack.com\");\n notify.addAction(\"Show \" + api.active_incidents[0].type + \" ID \" + api.active_incidents[0].id, api.active_incidents[0].url, true);\n notify.identifier = `ID_${api.active_incidents[0].id}`;\n notify.threadIdentifier = Script.name();\n notify.preferredContentHeight = 77;\n notify.scriptName = Script.name();\n notify.userInfo = {\"imgName\":dataType};\n notify.schedule();\n \n nKey.set(\"current_issue\", api.date_updated);\n};\n\nfunction createOkNotification() {\n let notify = new Notification();\n notify.title = \"Slack is now running again\";\n notify.subtitle = \"Trouble has been solved\";\n notify.identifier = api.date_updated;\n notify.threadIdentifier = Script.name();\n notify.addAction(\"Open Web-Dashboard ↗\", \"https:\/\/status.slack.com\");\n notify.scriptName = Script.name();\n notify.preferredContentHeight = 77;\n notify.userInfo = {\"imgName\":'ok'};\n notify.schedule();\n \n nKey.set(\"current_issue\", api.date_updated);\n};\n\n\nasync function createHeader(w, iSize, fSize) {\n headerStack = w.addStack();\n headerStack.centerAlignContent();\n headerStack.url = \"slack:\/\/\";\n headerStack.spacing = 7\n\n headerIcon = headerStack.addImage(await getImageFor(\"slackIcon\")).imageSize = new Size(iSize, iSize);\n headerTitle = headerStack.addText(\"Slack Status\").font = new Font(\"Futura-Medium\", fSize);\n};\n\nasync function addString(widget, leftText, rightText) {\n let line = widget.addStack();\n line.spacing = 15;\n\n let firstStack = line.addStack();\n firstStack.centerAlignContent()\n firstStack.addText(leftText).font = Font.lightSystemFont(12);\n firstStack.addSpacer();\n if (api.status != 'ok' && dataServices.includes(leftText)) image = dataType;\n else image = 'ok';\n firstStack.addImage(await getImageFor(image)).imageSize = new Size(20, 20)\n \n let secondStack = line.addStack();\n secondStack.centerAlignContent()\n secondStack.addText(rightText).font = Font.lightSystemFont(12);\n secondStack.addSpacer();\n if (api.status != 'ok' && dataServices.includes(rightText)) image = dataType;\n else image = 'ok';\n secondStack.addImage(await getImageFor(image)).imageSize = new Size(20, 20);\n};\n\nasync function presentAlert(message) {\n let alert = new Alert();\n alert.title = \"No Api Response\";\n alert.message = message;\n alert.addAction(\"OK\");\n idx = await alert.present();\n \/\/if (idx == 0) Safari.open(\"prefs:root\");\n}\n\n\/\/ LOADING AND SAVING IMAGES FROM URL TO FOLDER\nconst imgURL = \"https:\/\/raw.githubusercontent.com\/iamrbn\/slack-status\/main\/Symbols\/\";\nasync function saveImages() {\n\tconsole.log(\"loading & saving images\");\n\tvar imgs = [\"slackIcon.png\", \"ok.png\", \"incident.png\", \"outage.png\", \"notice.png\", \"maintenance.png\"];\n\tfor (img of imgs) {\n\t\tlet img_path = fm.joinPath(dir, img);\n\t\tif (!fm.fileExists(img_path)) {\n\t\t\tconsole.log(\"Loading image: \" + img);\n\t\t\tlet request = new Request(imgURL + img);\n\t\t\timage = await request.loadImage();\n\t\t\tfm.writeImage(img_path, image);\n\t\t}\n\t}\n};\n\nasync function getImageFor(name) {\n\timgPath = fm.joinPath(dir, name + '.png')\n\tawait fm.downloadFileFromiCloud(imgPath);\n\timg = await fm.readImage(imgPath);\n return img;\n};\n\n\/\/ Runtime images:\nawait saveImages();\ntry {saveData(data)}\ncatch(e) {}\n\nasync function presentMenu() {\n\tlet alert = new Alert();\n\talert.title = \"Slack Status\";\n\talert.message = emoji + api.status.toUpperCase() + emoji;\n\talert.addAction(\"Small\");\n\talert.addAction(\"Medium\");\n\talert.addAction(\"Large\");\n\talert.addDestructiveAction(\"Web Dashboard ↗\");\n\talert.addCancelAction(\"Cancel\");\n\tlet idx = await alert.present();\n\tif (idx == 0) {\n\t\tlet widget = await createSmallWidget();\n\t\tawait widget.presentSmall();\n\t} else if (idx == 1) {\n\t\tlet widget = await createMediumWidget();\n\t\tawait widget.presentMedium();\n\t} else if (idx == 2) {\n\t\tlet widget = await createLargeWidget();\n\t\tawait widget.presentLarge();\n\t} else if (idx == 3) Safari.openInApp(\"https:\/\/status.slack.com\", false);\n};\n\nasync function updateCheck(version) {\n let uC;\n try {\n let updateCheck = new Request(`${scriptURL}on`)\n uC = await updateCheck.loadJSON()\n } catch (e) {return log(e)}\n \n log(uC);\n \n let needUpdate = false\n if (uC.version != version) {\n needUpdate = true\n console.warn(`Server Version ${uC.version} Available!`)\n if (!config.runsInWidget) {\n let newAlert = new Alert()\n newAlert.title = `Server Version ${uC.version} Available!`\n newAlert.addAction(\"OK\")\n newAlert.addDestructiveAction(\"Later\")\n newAlert.message=\"Changes:\\n\" + uC.notes + \"\\n\\nPress OK to get the update from GitHub\"\n if (await newAlert.present() == 0) {\n let req = new Request(scriptURL)\n let updatedCode = await req.loadString()\n let fm = FileManager.iCloud()\n let path = fm.joinPath(fm.documentsDirectory(), `${Script.name()}.js`)\n log(path)\n fm.writeString(path, updatedCode)\n throw new Error(\"Update Complete!\")\n }\n }\n } else {log(\"up to date\")}\n\n return needUpdate, uC;\n};\n\n\/\/============================================\n\/\/============== END OF SCRIPT ===============\n\/\/============================================\n",
"share_sheet_inputs" : [
]
}