Skip to content

Instantly share code, notes, and snippets.

@icsAT
Last active October 15, 2021 15:25
Show Gist options
  • Save icsAT/23e5a5290f5b56eed277241964fbb4b8 to your computer and use it in GitHub Desktop.
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.
// 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()
}
@icsAT
Copy link
Author

icsAT commented Oct 12, 2021

Version 0.81 (10/15/2021)

  • added possibility to remove background.

Version 0.80 (10/12/2021)

  • Very first version.

@icsAT
Copy link
Author

icsAT commented Oct 12, 2021

Small:
IMG_2983IMG_2991

Medium:
IMG_2981
IMG_2990

Large:
IMG_2982
IMG_2988

Extra Large:
IMG_0162
IMG_0161

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment