Last active
October 15, 2021 15:25
-
-
Save icsAT/23e5a5290f5b56eed277241964fbb4b8 to your computer and use it in GitHub Desktop.
This Scriptable iOS Script displays the price of the selected Cryptocurrencies in a widget on your iPhone or iPad.
This file contains hidden or 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
// Variables used by Scriptable. | |
// These must be at the very top of the file. Do not edit. | |
// icon-color: deep-brown; icon-glyph: magic; | |
// Crypto Coin Widget | |
// by icsAT (https://gist.github.com/icsAT) | |
// Version 0.81 from the 15th of Oktober 2021 | |
// Data from Coin Market Cap Crypto API. | |
// Get your own privat API Key to use with this widget | |
// const cmcApiKey = "enter Your own API Key here xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" | |
const cmcApiKey = "enter Your own API Key here xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" | |
// With the Basic Plan you have a maximum of 333 API-Calls a Day and 10.000 API-Calls a Month. | |
// That means about 1 Call every 5 minutes. | |
// But be aware , that the refresh of a widget is regulated by iOS (approx. every 7 minutes afaik). | |
// Also be aware, that more than one widget means more API-Calls. | |
const cmcRefresh = 20 | |
// The widget will dispay the actual price of the crypto currencies in the given reference value | |
// You may set what you want to see here in the script or in the widget parameters. | |
// The widget parameter has the format: | |
// referenceValue;crypto1,crypto2,crypto3,... f.e. EUR;BTC,ETH,ADA,SOL,DOT,DOGE,AVAX,LTC | |
// The widget parameter will overrule the values set here. | |
// Reference Value in wich the price is displayed f.e EUR, USD, BTC | |
var referenceValue = "EUR" | |
// Crypto Currencies to be displayed, seperated by "," f.e. BTC,ETH,ADA,SOL,DOT,DOGE,AVAX,LTC | |
// var cryptoCurrencies = "ADA,AVAX,BTC,DOGE,DOT,ETH,LTC" | |
var cryptoCurrencies = "ADA,AVAX,BTC,CHZ,DOGE,DOT,ETH,LINK,LTC,MIOTA,SOL,UNI,AMP,COMP,GRT,SXP,XLM" | |
// Maximum Number of Cryptocurrency Lines | |
// Depending on your device there are more or less lines possible | |
// small and medium | |
const maxLinesSM = 7 | |
// large and extraLarge | |
const maxLinesLX = 17 | |
// Widget Size to be displayed if running from Scriptable App | |
// Use 'small' (max. 8 values), 'medium' (max. 8 values), 'large' (max.21 values) or 'extraLarge' (iPad only, max.21 values) | |
config.widgetFamily = config.widgetFamily || 'large' | |
// Weitere Parameter | |
const COLOR_RED = new Color('#FF0000') | |
const COLOR_GREEN = new Color('#008000') | |
const COLOR_BLACK = new Color('#000000') | |
const COLOR_WHITE = new Color('#FFFFFF') | |
const COLOR_GREY90 = new Color('#E6E6E6') | |
const COLOR_GREY70 = new Color('#B3B3B3') | |
const COLOR_GREY50 = new Color('#808080') | |
const COLOR_GREY30 = new Color('#4D4D4D') | |
const COLOR_GREY10 = new Color('#1a1a1a') | |
// debugging (set to false or to true to disable or enable console logging) | |
const debug = false | |
// Script Name | |
const scriptName = Script.name().replace(".js","") | |
// running the script | |
let widget = await createWidget() | |
if (config.runsInWidget) { | |
Script.setWidget(widget) | |
} else { | |
switch (config.widgetFamily) { | |
case 'small': await widget.presentSmall(); break; | |
case 'medium': await widget.presentMedium(); break; | |
case 'large': await widget.presentLarge(); break; | |
case 'extraLarge': await widget.presentExtraLarge(); break; | |
} | |
} | |
Script.complete() | |
// create the widget | |
async function createWidget() { | |
if (debug) console.log("START async function crateWidget()") | |
if (args.widgetParameter) { | |
var parameters = args.widgetParameter.split(";") | |
referenceValue = parameters[0] | |
cryptoCurrencies = parameters[1] | |
} | |
referenceValue = referenceValue.trim() | |
referenceValue = referenceValue.replace(" ", "") | |
if (debug) console.log("referenceValue: " + referenceValue) | |
cryptoCurrencies = cryptoCurrencies.trim() | |
cryptoCurrencies = cryptoCurrencies.replace(" ", "") | |
if (debug) console.log("cryptoCurrencies: " + cryptoCurrencies) | |
numberCoins = 0 | |
var coins = cryptoCurrencies.split(",") | |
for (coin of coins) { | |
numberCoins++ | |
} | |
if (debug) console.log("numberCoins: " + numberCoins) | |
let listWidget = new ListWidget() | |
listWidget.backgroundColor = Color.clear() | |
listWidget.centerAlignContent | |
let darkMode = !(Color.dynamic(Color.white(),Color.black()).red) | |
if (debug) console.log("darkMode: " + darkMode) | |
const fm = FileManager.local() | |
let directoryPath = fm.joinPath(fm.documentsDirectory(), "Crypto") | |
if (debug) console.log("directoryPath: " + directoryPath) | |
const extension = scriptName + (darkMode ? "_dark" : "_light") + ".jpg" | |
if (debug) console.log("extension: " + extension) | |
const imagePath = fm.joinPath(directoryPath, extension) | |
if (debug) console.log("imagePath: " + imagePath) | |
if (!config.runsInWidget) { | |
changeBackground = !(await generatePrompt("Change Background?", "Would you like to change the background?",["Yes","No"])) | |
if (debug) console.log("setBackground: " + setBackground) | |
if (changeBackground) { | |
setBackground = !(await generatePrompt("New Background?", "Would you like to set a new image or erase the actual image?",["Set","Erase"])) | |
if (setBackground) { | |
if (!fm.fileExists(directoryPath) || !fm.isDirectory(directoryPath)) { | |
fm.createDirectory(directoryPath) | |
} | |
let newImage = await Photos.fromLibrary() | |
fm.writeImage(fm.joinPath(directoryPath, scriptName + "_light.jpg"), newImage) | |
let setBackgroundDark = !(await generatePrompt("Dark Background?", "Would you like to use a different image in dark mode?",["Yes","No"])) | |
if (debug) console.log("setBackgroundDark: " + setBackgroundDark) | |
if (setBackgroundDark) { | |
let newDarkImage = await Photos.fromLibrary() | |
fm.writeImage(fm.joinPath(directoryPath, scriptName + "_dark.jpg"), newImage) | |
} else { | |
fm.writeImage(fm.joinPath(directoryPath, scriptName + "_dark.jpg"), newImage) | |
} | |
} else { | |
if (fm.fileExists(fm.joinPath(directoryPath, scriptName + "_light.jpg"))) { | |
fm.remove(fm.joinPath(directoryPath, scriptName + "_light.jpg")) | |
} | |
if (fm.fileExists(fm.joinPath(directoryPath, scriptName + "_dark.jpg"))) { | |
fm.remove(fm.joinPath(directoryPath, scriptName + "_dark.jpg")) | |
} | |
} | |
} | |
} | |
if (fm.fileExists(imagePath)) { | |
if (fm.isFileStoredIniCloud(imagePath)) { | |
await fm.downloadFileFromiCloud(imagePath) | |
} | |
listWidget.backgroundImage = fm.readImage(imagePath) | |
if (debug) console.log("Background Image gesetzt.") | |
} | |
headLine = listWidget.addStack() | |
headLine.centerAlignContent | |
headLine.addSpacer() | |
headLineText = headLine.addText("Crypto Prices") | |
headLineText.font = Font.boldSystemFont(15) | |
headLineText.centerAlignText() | |
headLine.addSpacer() | |
stack = listWidget.addStack() | |
stack.layoutVertically() | |
stack.centerAlignContent | |
if ((numberCoins<maxLinesSM && (config.widgetFamily == 'small' || config.widgetFamily == 'medium')) || (numberCoins<maxLinesLX && (config.widgetFamily == 'large' || config.widgetFamily == 'extraLarge'))) { | |
stack.addSpacer(8) | |
} | |
lastUpdate = "1900-01-01T00:00:00.000Z" | |
if (debug) console.log("lastUpdate: "+ lastUpdate) | |
cmcUrlParameter = "?convert="+referenceValue+"&symbol="+cryptoCurrencies | |
if (debug) console.log("cmcUrlParameter: "+ cmcUrlParameter) | |
cryptoData = await getCryptoData(fm, cmcUrlParameter) | |
if (cryptoData && cryptoData.status.error_code == 0) { | |
if (config.widgetFamily == 'small') { | |
if (numberCoins <= maxLinesSM) { | |
await smallTable(coins, cryptoData) | |
} else { | |
errorLine = stack.addStack() | |
errorLine.layoutVertically() | |
fehlerText = errorLine.addText("Please use not more than " + maxLinesSM + " coins in a small widget!") | |
fehlerText.font = Font.boldSystemFont(8) | |
fehlerText.textColor = COLOR_RED | |
fehlerText = errorLine.addText("You tried to use " + numberCoins + " coins.") | |
fehlerText.font = Font.boldSystemFont(8) | |
fehlerText.textColor = COLOR_RED | |
} | |
} | |
if (config.widgetFamily == 'medium') { | |
if (numberCoins <= maxLinesSM) { | |
await wideTable(coins, cryptoData) | |
} else { | |
errorLine = stack.addStack() | |
errorLine.layoutVertically() | |
fehlerText = errorLine.addText("Please use not more than " + maxLinesSM + " coins in a medium widget!") | |
fehlerText.font = Font.boldSystemFont(15) | |
fehlerText.textColor = COLOR_RED | |
fehlerText = errorLine.addText("You tried to use " + numberCoins + " coins.") | |
fehlerText.font = Font.boldSystemFont(15) | |
fehlerText.textColor = COLOR_RED | |
} | |
} | |
if (config.widgetFamily == 'large') { | |
if (numberCoins <= maxLinesLX) { | |
await wideTable(coins, cryptoData) | |
} else { | |
errorLine = stack.addStack() | |
errorLine.layoutVertically() | |
fehlerText = errorLine.addText("Please use not more than " + maxLinesLX + " coins in a large widget!") | |
fehlerText.font = Font.boldSystemFont(15) | |
fehlerText.textColor = COLOR_RED | |
fehlerText = errorLine.addText("You tried to use " + numberCoins + " coins.") | |
fehlerText.font = Font.boldSystemFont(15) | |
fehlerText.textColor = COLOR_RED | |
} | |
} | |
if (config.widgetFamily == 'extraLarge') { | |
if (numberCoins <= maxLinesLX) { | |
await extraLargeTable(coins, cryptoData) | |
} else { | |
errorLine = stack.addStack() | |
errorLine.layoutVertically() | |
fehlerText = errorLine.addText("Please use not more than " + maxLinesLX + " coins in a extraLarge widget!") | |
fehlerText.font = Font.boldSystemFont(15) | |
fehlerText.textColor = COLOR_RED | |
fehlerText = errorLine.addText("You tried to use " + numberCoins + " coins.") | |
fehlerText.font = Font.boldSystemFont(15) | |
fehlerText.textColor = COLOR_RED | |
} | |
} | |
df = new DateFormatter() | |
df.dateFormat = "yyyy-MM-dd HH:mm" | |
lastUpdate = df.string(new Date(cryptoData.status.timestamp)) | |
if ((numberCoins<(maxLinesSM - 1) && (config.widgetFamily == 'small' || config.widgetFamily == 'medium')) || (numberCoins<(maxLinesLX - 1) && (config.widgetFamily == 'large' || config.widgetFamily == 'extraLarge'))) { | |
stack.addSpacer(8) | |
} | |
footerLine = listWidget.addStack() | |
footerLine.addSpacer() | |
footerLineText = footerLine.addText(lastUpdate) | |
footerLineText.font = Font.mediumSystemFont(8) | |
footerLineText.textColor = Color.dynamic(COLOR_GREY30, COLOR_GREY70) | |
footerLine.addSpacer() | |
} else { | |
errorLine = stack.addStack() | |
errorLine.layoutHorizontally() | |
if (cryptoData) { | |
errorText = errorLine.addText("Error Calling the Coin Market Cap API: "+cryptoData.status.error_message) | |
} else { | |
errorText = errorLine.addText("Not able to get Data from Coin Market Cap, nor from Cache. Try again.") | |
} | |
errorText.font = Font.boldSystemFont(15) | |
errorText.textColor = COLOR_RED | |
} | |
if (debug) console.log("END async function crateWidget()") | |
return listWidget | |
} | |
// small widget table | |
async function smallTable(coins, cryptoData) { | |
if (debug) console.log("START async function smallTable(coins, cryptoData)") | |
firstLine = stack.addStack() | |
firstLine.layoutHorizontally() | |
firstLine.centerAlignContent() | |
firstLine.backgroundColor = Color.dynamic(COLOR_BLACK, COLOR_WHITE) | |
firstLine.cornerRadius = 5 | |
firstLine.addSpacer() | |
firstLineStack = firstLine.addStack() | |
firstLineStack.size = new Size(50,0) | |
nameText = firstLineStack.addText("Name") | |
nameText.font = Font.mediumSystemFont(12) | |
nameText.textColor = Color.dynamic(COLOR_WHITE, COLOR_BLACK) | |
nameText.leftAlignText() | |
firstLineStack.addSpacer() | |
firstLineStack = firstLine.addStack() | |
firstLineStack.size = new Size(70,0) | |
firstLineStack.addSpacer() | |
priceText = firstLineStack.addText("Price "+referenceValue) | |
priceText.font = Font.mediumSystemFont(12) | |
priceText.textColor = Color.dynamic(COLOR_WHITE, COLOR_BLACK) | |
priceText.rightAlignText() | |
firstLine.addSpacer() | |
lineCount = 1 | |
for (coin of coins) { | |
if (debug) console.log("coin: "+ coin) | |
coinLine = stack.addStack() | |
coinLine.layoutHorizontally() | |
coinLine.centerAlignContent() | |
coinLine.addSpacer() | |
if (lineCount % 2 == 0) { | |
coinLine.backgroundColor = Color.dynamic(COLOR_GREY90, COLOR_GREY10) | |
} | |
coinLineStack = coinLine.addStack() | |
coinLineStack.size = new Size(50,0) | |
nameText = coinLineStack.addText(cryptoData.data[coin].symbol) | |
nameText.font = Font.mediumSystemFont(12) | |
nameText.leftAlignText() | |
coinLineStack.addSpacer() | |
coinLineStack = coinLine.addStack() | |
coinLineStack.size = new Size(70,0) | |
coinLineStack.addSpacer() | |
priceText = coinLineStack.addText(parseFloat(cryptoData.data[coin].quote[referenceValue].price.toFixed(2)).toLocaleString()) | |
priceText.font = Font.mediumSystemFont(12) | |
priceText.textColor = getTextColor("price", cryptoData.data[coin].quote[referenceValue].percent_change_1h) | |
priceText.rightAlignText() | |
coinLine.addSpacer() | |
lineCount++ | |
} | |
if (debug) console.log("END async function smallTable(coins, cryptoData)") | |
} | |
// medium and large widget table | |
async function wideTable(coins, cryptoData) { | |
if (debug) console.log("START async function wideTable(coins, cryptoData)") | |
firstLine = stack.addStack() | |
firstLine.layoutHorizontally() | |
firstLine.centerAlignContent() | |
firstLine.backgroundColor = Color.dynamic(COLOR_BLACK, COLOR_WHITE) | |
firstLine.cornerRadius = 5 | |
firstLine.addSpacer() | |
firstLineStack = firstLine.addStack() | |
firstLineStack.size = new Size(115,0) | |
nameText = firstLineStack.addText("Name") | |
nameText.font = Font.mediumSystemFont(12) | |
nameText.textColor = Color.dynamic(COLOR_WHITE, COLOR_BLACK) | |
nameText.leftAlignText() | |
firstLineStack.addSpacer() | |
firstLineStack = firstLine.addStack() | |
firstLineStack.size = new Size(70,0) | |
firstLineStack.addSpacer() | |
priceText = firstLineStack.addText("Price "+referenceValue) | |
priceText.font = Font.mediumSystemFont(12) | |
priceText.textColor = Color.dynamic(COLOR_WHITE, COLOR_BLACK) | |
priceText.rightAlignText() | |
firstLineStack = firstLine.addStack() | |
firstLineStack.size = new Size(50,0) | |
firstLineStack.addSpacer() | |
dayText = firstLineStack.addText("24h %") | |
dayText.font = Font.mediumSystemFont(12) | |
dayText.textColor = Color.dynamic(COLOR_WHITE, COLOR_BLACK) | |
dayText.rightAlignText() | |
firstLineStack = firstLine.addStack() | |
firstLineStack.size = new Size(50,0) | |
firstLineStack.addSpacer() | |
weekText = firstLineStack.addText("7d %") | |
weekText.font = Font.mediumSystemFont(12) | |
weekText.textColor = Color.dynamic(COLOR_WHITE, COLOR_BLACK) | |
weekText.rightAlignText() | |
firstLine.addSpacer() | |
lineCount = 1 | |
for (coin of coins) { | |
if (debug) console.log("coin: "+ coin) | |
coinLine = stack.addStack() | |
coinLine.layoutHorizontally() | |
coinLine.centerAlignContent() | |
coinLine.addSpacer() | |
if (lineCount % 2 == 0) { | |
coinLine.backgroundColor = Color.dynamic(COLOR_GREY90, COLOR_GREY10) | |
} | |
coinLineStack = coinLine.addStack() | |
coinLineStack.size = new Size(115,0) | |
nameText = coinLineStack.addText(cryptoData.data[coin].symbol + "/" + cryptoData.data[coin].name) | |
nameText.font = Font.mediumSystemFont(12) | |
nameText.leftAlignText() | |
coinLineStack.addSpacer() | |
coinLineStack = coinLine.addStack() | |
coinLineStack.size = new Size(70,0) | |
coinLineStack.addSpacer() | |
priceText = coinLineStack.addText(parseFloat(cryptoData.data[coin].quote[referenceValue].price.toFixed(2)).toLocaleString()) | |
priceText.font = Font.mediumSystemFont(12) | |
priceText.textColor = getTextColor("price", cryptoData.data[coin].quote[referenceValue].percent_change_1h) | |
priceText.rightAlignText() | |
coinLineStack = coinLine.addStack() | |
coinLineStack.size = new Size(50,0) | |
coinLineStack.addSpacer() | |
dayText = coinLineStack.addText(parseFloat(cryptoData.data[coin].quote[referenceValue].percent_change_24h.toFixed(2)).toLocaleString()) | |
dayText.font = Font.mediumSystemFont(12) | |
dayText.textColor = getTextColor("day", cryptoData.data[coin].quote[referenceValue].percent_change_24h) | |
dayText.rightAlignText() | |
coinLineStack = coinLine.addStack() | |
coinLineStack.size = new Size(50,0) | |
coinLineStack.addSpacer() | |
weekText = coinLineStack.addText(parseFloat(cryptoData.data[coin].quote[referenceValue].percent_change_7d.toFixed(2)).toLocaleString()) | |
weekText.font = Font.mediumSystemFont(12) | |
weekText.textColor = getTextColor("week", cryptoData.data[coin].quote[referenceValue].percent_change_7d) | |
weekText.rightAlignText() | |
coinLine.addSpacer() | |
lineCount++ | |
} | |
if (debug) console.log("END async function wideTable(coins, cryptoData)") | |
} | |
//extraLarge table | |
async function extraLargeTable(coins, cryptoData) { | |
if (debug) console.log("START async function extraLargeTable(coins, cryptoData)") | |
firstLine = stack.addStack() | |
firstLine.layoutHorizontally() | |
firstLine.centerAlignContent() | |
firstLine.backgroundColor = Color.dynamic(COLOR_BLACK, COLOR_WHITE) | |
firstLine.cornerRadius = 5 | |
firstLine.addSpacer() | |
firstLineStack = firstLine.addStack() | |
firstLineStack.size = new Size(125,0) | |
nameText = firstLineStack.addText("Name") | |
nameText.font = Font.mediumSystemFont(12) | |
nameText.textColor = Color.dynamic(COLOR_WHITE, COLOR_BLACK) | |
nameText.leftAlignText() | |
firstLineStack.addSpacer() | |
firstLineStack = firstLine.addStack() | |
firstLineStack.size = new Size(75,0) | |
firstLineStack.addSpacer() | |
priceText = firstLineStack.addText("Price "+referenceValue) | |
priceText.font = Font.mediumSystemFont(12) | |
priceText.textColor = Color.dynamic(COLOR_WHITE, COLOR_BLACK) | |
priceText.rightAlignText() | |
firstLineStack = firstLine.addStack() | |
firstLineStack.size = new Size(50,0) | |
firstLineStack.addSpacer() | |
hourText = firstLineStack.addText("1h %") | |
hourText.font = Font.mediumSystemFont(12) | |
hourText.textColor = Color.dynamic(COLOR_WHITE, COLOR_BLACK) | |
hourText.rightAlignText() | |
firstLineStack = firstLine.addStack() | |
firstLineStack.size = new Size(50,0) | |
firstLineStack.addSpacer() | |
dayText = firstLineStack.addText("24h %") | |
dayText.font = Font.mediumSystemFont(12) | |
dayText.textColor = Color.dynamic(COLOR_WHITE, COLOR_BLACK) | |
dayText.rightAlignText() | |
firstLineStack = firstLine.addStack() | |
firstLineStack.size = new Size(55,0) | |
firstLineStack.addSpacer() | |
weekText = firstLineStack.addText("7d %") | |
weekText.font = Font.mediumSystemFont(12) | |
weekText.textColor = Color.dynamic(COLOR_WHITE, COLOR_BLACK) | |
weekText.rightAlignText() | |
firstLineStack = firstLine.addStack() | |
firstLineStack.size = new Size(125,0) | |
firstLineStack.addSpacer() | |
mcText = firstLineStack.addText("Market Cap "+referenceValue) | |
mcText.font = Font.mediumSystemFont(12) | |
mcText.textColor = Color.dynamic(COLOR_WHITE, COLOR_BLACK) | |
mcText.rightAlignText() | |
firstLineStack = firstLine.addStack() | |
firstLineStack.size = new Size(120,0) | |
firstLineStack.addSpacer() | |
csText = firstLineStack.addText("Circulating Supply") | |
csText.font = Font.mediumSystemFont(12) | |
csText.textColor = Color.dynamic(COLOR_WHITE, COLOR_BLACK) | |
csText.rightAlignText() | |
firstLine.addSpacer() | |
lineCount = 1 | |
for (coin of coins) { | |
if (debug) console.log("coin: "+ coin) | |
coinLine = stack.addStack() | |
coinLine.layoutHorizontally() | |
coinLine.centerAlignContent() | |
coinLine.addSpacer() | |
if (lineCount % 2 == 0) { | |
coinLine.backgroundColor = Color.dynamic(COLOR_GREY90, COLOR_GREY10) | |
} | |
coinLineStack = coinLine.addStack() | |
coinLineStack.size = new Size(125,0) | |
nameText = coinLineStack.addText(cryptoData.data[coin].symbol + "/" + cryptoData.data[coin].name) | |
nameText.font = Font.mediumSystemFont(12) | |
nameText.leftAlignText() | |
coinLineStack.addSpacer() | |
coinLineStack = coinLine.addStack() | |
coinLineStack.size = new Size(75,0) | |
coinLineStack.addSpacer() | |
priceText = coinLineStack.addText(parseFloat(cryptoData.data[coin].quote[referenceValue].price.toFixed(2)).toLocaleString()) | |
priceText.font = Font.mediumSystemFont(12) | |
priceText.textColor = getTextColor("price", cryptoData.data[coin].quote[referenceValue].percent_change_1h) | |
priceText.rightAlignText() | |
coinLineStack = coinLine.addStack() | |
coinLineStack.size = new Size(50,0) | |
coinLineStack.addSpacer() | |
hourText = coinLineStack.addText(parseFloat(cryptoData.data[coin].quote[referenceValue].percent_change_1h.toFixed(2)).toLocaleString()) | |
hourText.font = Font.mediumSystemFont(12) | |
hourText.textColor = getTextColor("hour", cryptoData.data[coin].quote[referenceValue].percent_change_1h) | |
hourText.rightAlignText() | |
coinLineStack = coinLine.addStack() | |
coinLineStack.size = new Size(50,0) | |
coinLineStack.addSpacer() | |
dayText = coinLineStack.addText(parseFloat(cryptoData.data[coin].quote[referenceValue].percent_change_24h.toFixed(2)).toLocaleString()) | |
dayText.font = Font.mediumSystemFont(12) | |
dayText.textColor = getTextColor("day", cryptoData.data[coin].quote[referenceValue].percent_change_24h) | |
dayText.rightAlignText() | |
coinLineStack = coinLine.addStack() | |
coinLineStack.size = new Size(55,0) | |
coinLineStack.addSpacer() | |
weekText = coinLineStack.addText(parseFloat(cryptoData.data[coin].quote[referenceValue].percent_change_7d.toFixed(2)).toLocaleString()) | |
weekText.font = Font.mediumSystemFont(12) | |
weekText.textColor = getTextColor("week", cryptoData.data[coin].quote[referenceValue].percent_change_7d) | |
weekText.rightAlignText() | |
coinLineStack = coinLine.addStack() | |
coinLineStack.size = new Size(125,0) | |
coinLineStack.addSpacer() | |
mcText = coinLineStack.addText(Math.round(cryptoData.data[coin].quote[referenceValue].market_cap).toLocaleString()) | |
mcText.font = Font.mediumSystemFont(12) | |
mcText.rightAlignText() | |
coinLineStack = coinLine.addStack() | |
coinLineStack.size = new Size(120,0) | |
coinLineStack.addSpacer() | |
csText = coinLineStack.addText(Math.round(cryptoData.data[coin].circulating_supply).toLocaleString()) | |
csText.font = Font.mediumSystemFont(12) | |
csText.rightAlignText() | |
coinLine.addSpacer() | |
lineCount++ | |
} | |
if (debug) console.log("END async function extraLargeTable(coins, cryptoData)") | |
} | |
// get crypto data from API | |
async function getCryptoData(fm, mcUrlParameter) { | |
if (debug) console.log("START async function getCryptoData(fm, cmcUrlParameter)") | |
let directoryPath = fm.joinPath(fm.libraryDirectory(), scriptName + ".cache") | |
if (debug) console.log("directoryPath: "+ directoryPath) | |
let cmcApiData = getCache(fm, directoryPath, cmcRefresh) | |
if (!cmcApiData || cmcApiData.length == 0 || cmcApiData.cacheExpired) { | |
try { | |
const cmcApiUrl = "https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest" + cmcUrlParameter | |
if (debug) console.log("cmcApiUrl: "+ cmcApiUrl) | |
let cmcApiRequest = new Request(cmcApiUrl) | |
cmcApiRequest.headers = { 'X-CMC_PRO_API_KEY': cmcApiKey, 'Accept': 'application/json' } | |
cmcApiData = await cmcApiRequest.loadJSON() | |
if (!cmcApiData || cmcApiData.length == 0) { throw 0 } | |
fm.writeString(directoryPath, JSON.stringify(cmcApiData, null, 2)) | |
} catch(e) { | |
cmcApiData = getCache(fm, directoryPath, cmcRefresh) | |
} | |
} | |
if (debug) console.log("Return cmcApiData: "+ JSON.stringify(cmcApiData, null, 2)) | |
if (debug) console.log("END async function getCryptoData(fm, cmcUrlParameter)") | |
return cmcApiData | |
} | |
// get text color | |
function getTextColor(object, value) { | |
if (debug) console.log("START function getTextColor(object, value)") | |
let textColor = Color.dynamic(COLOR_BLACK, COLOR_WHITE) | |
if ((object=="price" && value>=1) || (object=="hour" && value>=1) || (object=="day" && value>=5) || (object=="week" && value>=10)) { | |
textColor = COLOR_GREEN | |
} else if ((object=="price" && value<=-1) || (object=="hour" && value<=-1) || (object=="day" && value<=-5) || (object=="week" && value<=-10)) { | |
textColor = COLOR_RED | |
} | |
if (debug) console.log("Return textColor: "+ textColor) | |
if (debug) console.log("END function getTextColor(object, value)") | |
return textColor | |
} | |
// get cache | |
function getCache(fm, path, minAge = -1, maxAge) { | |
if (debug) console.log("START function getCache(fm, path, minAge = -1, maxAge)") | |
if (debug) console.log("path: "+ path) | |
if (debug) console.log("minAge: "+ minAge) | |
if (debug) console.log("maxAge: "+ maxAge) | |
if (!fm.fileExists(path)) { | |
if (debug) console.log("Cache File does not exists. Return null") | |
return null | |
} | |
const cache = JSON.parse(fm.readString(path)) | |
if (debug) console.log("cache: "+ JSON.stringify(cache, null, 2)) | |
now = new Date() | |
if (debug) console.log("now: "+ now) | |
const age = (now.getTime() - fm.modificationDate(path).getTime())/60000 | |
if (debug) console.log("age: "+ age) | |
if (Number.isInteger(maxAge) && age > maxAge) { | |
if (debug) console.log("Age is grater than maxAge. Return null.") | |
return null | |
} | |
if (minAge != -1 && (!minAge || age > minAge)) cache.cacheExpired = true | |
if (debug) console.log("Return cache: "+ JSON.stringify(cache, null, 2)) | |
if (debug) console.log("END function getCache(fm, path, minAge = -1, maxAge)") | |
return cache | |
} | |
// generate prompt. | |
async function generatePrompt(title,message,options) { | |
if (debug) console.log("START async function generatePrompt(title,message,options)") | |
if (debug) console.log("title: "+ title) | |
if (debug) console.log("message: "+ message) | |
if (debug) console.log("options: "+ options) | |
let alert = new Alert() | |
alert.title = title | |
if (message) alert.message = message | |
let buttons = options || ["OK"] | |
for (button of buttons) { | |
alert.addAction(button) | |
} | |
if (debug) console.log("END async function generatePrompt(title,message,options)") | |
return await alert.presentAlert() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Version 0.81 (10/15/2021)
Version 0.80 (10/12/2021)