-
-
Save webOSpinn/7798badfe7ccc08d303ac06e5c8558c2 to your computer and use it in GitHub Desktop.
Stock Widget for iOS using Scriptable
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
// Variables used by Scriptable. | |
// These must be at the very top of the file. Do not edit. | |
// icon-color: deep-blue; icon-glyph: book; share-sheet-inputs: plain-text; | |
// Stock Ticker Widget | |
let locale = Device.locale().replace("_","-"); | |
let stocksInfo = await getStockData() | |
let widget = await createWidget() | |
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, so we preview the widget. | |
//widget.presentSmall() | |
widget.presentMedium() | |
} | |
// Calling Script.complete() signals to Scriptable that the script have finished running. | |
// This can speed up the execution, in particular when running the script from Shortcuts or using Siri. | |
Script.complete() | |
async function createWidget(api) { | |
let upticker = SFSymbol.named("chevron.up"); | |
let downticker = SFSymbol.named("chevron.down"); | |
let widget = new ListWidget() | |
// Add background gradient | |
let gradient = new LinearGradient() | |
gradient.locations = [0, 1] | |
gradient.colors = [ | |
new Color("141414"), | |
new Color("13233F") | |
] | |
widget.backgroundGradient = gradient | |
for(j=0; j<stocksInfo.length; j++) | |
{ | |
let currentStock = stocksInfo[j]; | |
let row1 = widget.addStack(); | |
// Add Stock Symbol | |
let stockSymbol = row1.addText(currentStock.symbol); | |
stockSymbol.textColor = Color.white(); | |
stockSymbol.font = Font.boldMonospacedSystemFont(12); | |
//Add Current Price | |
row1.addSpacer(); | |
let symbolPrice = row1.addText(currentStock.currencySymbol + formatNum(currentStock.price, currentStock.digits)); | |
symbolPrice.textColor = Color.white(); | |
symbolPrice.font = Font.boldMonospacedSystemFont(12); | |
//Second Row | |
widget.addSpacer(2) | |
let row2= widget.addStack(); | |
// Add Company name | |
let companyName= row2.addText(currentStock.name); | |
companyName.textColor = Color.white(); | |
companyName.textOpacity = 0.7; | |
companyName.font = Font.boldMonospacedSystemFont(9); | |
//Add Today's change in price | |
row2.addSpacer(); | |
let sign = ""; | |
if(currentStock.changepercent >= 0) sign = "+"; | |
let changeValue = row2.addText(sign + formatNum(currentStock.changevalue, currentStock.digits) + " (" + sign + currentStock.changepercent + "%)"); | |
//Use changepercent to handle cases where the change value is -0.00 | |
if(currentStock.changepercent < 0) { | |
changeValue.textColor = Color.red(); | |
} else { | |
changeValue.textColor = Color.green(); | |
} | |
changeValue.font = Font.boldMonospacedSystemFont(9); | |
// Add Ticker icon | |
row2.addSpacer(2); | |
let ticker = null; | |
//Use changepercent to handle cases where the change value is -0.00 | |
if(currentStock.changepercent < 0){ | |
ticker = row2.addImage(downticker.image); | |
ticker.tintColor = Color.red(); | |
} else { | |
ticker = row2.addImage(upticker.image); | |
ticker.tintColor = Color.green(); | |
} | |
ticker.imageSize = new Size(8,8); | |
widget.addSpacer(6); | |
} | |
// Add last updated time | |
let row1 = widget.addStack(); | |
row1.addSpacer(); | |
let date = new Date(); | |
let timeString = date.toLocaleTimeString(locale); | |
let updatedTimeText = row1.addText("Update: " + timeString); | |
updatedTimeText.textColor = Color.lightGray(); | |
updatedTimeText.font = Font.lightSystemFont(9); | |
row1.addSpacer(); | |
return widget | |
} | |
async function getStockData() { | |
let stocks = null; | |
// Read from WidgetParameter if present or use hardcoded values | |
// Provide values in Widget Parameter as comma seperated list | |
if(args.widgetParameter == null) { | |
stocks = ["PRGS", "AAPL", "INR=X", "XRP-USD"]; | |
} else { | |
stocks = args.widgetParameter.split(","); | |
} | |
let stocksdata = []; | |
for(i=0; i< stocks.length; i++) | |
{ | |
let stkdata = await queryStockData(stocks[i].trim()); | |
let price = stkdata.quoteSummary.result[0].price; | |
let priceKeys = Object.keys(price); | |
let data = {}; | |
data.digits = price.priceHint.raw; | |
data.symbol = price.symbol; | |
data.changepercent = (price.regularMarketChangePercent.raw * 100).toFixed(2); | |
data.changevalue = price.regularMarketChange.raw.toFixed(data.digits); | |
data.price = price.regularMarketPrice.raw.toFixed(data.digits); | |
data.high = price.regularMarketDayHigh.raw.toFixed(data.digits); | |
data.low = price.regularMarketDayLow.raw.toFixed(data.digits); | |
data.prevclose = price.regularMarketPreviousClose.raw.toFixed(data.digits); | |
data.name = price.shortName; | |
data.currencySymbol = price.currencySymbol; | |
stocksdata.push(data); | |
} | |
return stocksdata; | |
} | |
async function queryStockData(symbol) { | |
let url = "https://query1.finance.yahoo.com/v10/finance/quoteSummary/" + encodeURIComponent(symbol) + "?modules=price" | |
let req = new Request(url) | |
return await req.loadJSON() | |
} | |
function formatNum(num, digits) { | |
let numFormatter = new Intl.NumberFormat(locale, { maximumFractionDigits: digits, minimumFractionDigits: digits }); | |
return numFormatter.format(num); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment