Skip to content

Instantly share code, notes, and snippets.

@MisterMike
Forked from marco79cgn/dm-toilet-paper.js
Last active October 24, 2020 20:23
Show Gist options
  • Save MisterMike/3e30dab7f5017bd5f14e759809020bc0 to your computer and use it in GitHub Desktop.
Save MisterMike/3e30dab7f5017bd5f14e759809020bc0 to your computer and use it in GitHub Desktop.
Scriptable iOS widget that shows the amount of toilet paper which is available at your next dm drugstore
// Thanks https://gist.github.com/marco79cgn/23ce08fd8711ee893a3be12d4543f2d2 for the code :-)
// Variables used by Scriptable.
// These must be at the very top of the file. Do not edit.
// icon-color: deep-blue; icon-glyph: magic;
let storeId = 178
let country
let param = args.widgetParameter
if (param != null && param.length > 0) {
storeId = param
}
const widget = new ListWidget()
const storeInfo = await fetchStoreInformation()
const storeCapacity = await fetchAmountOfPaper()
await createWidget()
// used for debugging if script runs inside the app
if (!config.runsInWidget) {
await widget.presentSmall()
}
Script.setWidget(widget)
Script.complete()
// build the content of the widget
async function createWidget() {
widget.addSpacer(4)
const logoImg = await getImage('dm-logo.png')
widget.setPadding(10, 10, 10, 10)
const titleFontSize = 12
const detailFontSize = 36
const logoStack = widget.addStack()
logoStack.addSpacer(86)
const logoImageStack = logoStack.addStack()
logoStack.layoutHorizontally()
logoImageStack.backgroundColor = new Color("#ffffff", 1.0)
logoImageStack.cornerRadius = 8
const wimg = logoImageStack.addImage(logoImg)
wimg.imageSize = new Size(40, 40)
wimg.rightAlignImage()
widget.addSpacer()
const icon = await getImage('toilet-paper.png')
let row = widget.addStack()
row.layoutHorizontally()
row.addSpacer(2)
const iconImg = row.addImage(icon)
iconImg.imageSize = new Size(40, 40)
row.addSpacer(13)
let column = row.addStack()
column.layoutVertically()
const paperText = column.addText("KLOPAPIER")
paperText.font = Font.mediumRoundedSystemFont(13)
const packageCount = column.addText(storeCapacity.toString())
packageCount.font = Font.mediumRoundedSystemFont(22)
if (storeCapacity < 30) {
packageCount.textColor = new Color("#E50000")
} else {
packageCount.textColor = new Color("#00CD66")
}
widget.addSpacer(4)
const row2 = widget.addStack()
row2.layoutVertically()
const street = row2.addText(storeInfo.address.street)
street.font = Font.regularSystemFont(11)
const zipCity = row2.addText(storeInfo.address.zip + " " + storeInfo.address.city)
zipCity.font = Font.regularSystemFont(11)
let currentTime = new Date().toLocaleTimeString('de-DE', { hour: "numeric", minute: "numeric" })
let currentDay = new Date().getDay()
const todaysOpeningHour = storeInfo.openingHours[currentDay].timeRanges[0].opening
const todaysClosingHour = storeInfo.openingHours[currentDay].timeRanges[0].closing
const range = [todaysOpeningHour, todaysClosingHour];
const isOpen = isInRange(currentTime, range)
let shopStateText
if (isOpen) {
shopStateText = row2.addText('Geöffnet')
shopStateText.textColor = new Color("#00CD66")
} else {
shopStateText = row2.addText('Geschlossen')
shopStateText.textColor = new Color("#E50000")
}
shopStateText.font = Font.mediumSystemFont(11)
}
// fetches the amount of toilet paper packages
async function fetchAmountOfPaper() {
let url
let counter = 0
if (country.toLowerCase() === 'at') {
// Austria
const array = ["156754", "180487", "194066", "188494", "194144", "273259", "170237", "232201", "170425", "283216", "205873", "205874", "249881", "184204"]
for (var i = 0; i < array.length; i++) {
let currentItem = array[i]
url = 'https://products.dm.de/store-availability/AT/products/dans/' + currentItem + '/stocklevel?storeNumbers=' + storeId
let req = new Request(url)
let apiResult = await req.loadJSON()
if (req.response.statusCode == 200) {
counter += apiResult.storeAvailability[0].stockLevel
}
}
} else {
// Germany
url = 'https://products.dm.de/store-availability/DE/availability?dans=595420,708997,137425,28171,485698,799358,863567,452740,610544,846857,709006,452753,879536,452744,485695,853483,594080,504606,593761,525943,842480,535981,127048,524535&storeNumbers=' + storeId
const req = new Request(url)
const apiResult = await req.loadJSON()
for (var i in apiResult.storeAvailabilities) {
counter += apiResult.storeAvailabilities[i][0].stockLevel
}
}
return counter
}
// fetches information of the configured store, e.g. opening hours, address etc.
async function fetchStoreInformation() {
let url = 'https://store-data-service.services.dmtech.com/stores/item/de/' + storeId
let req = new Request(url)
let apiResult = await req.loadString()
if (req.response.statusCode == 404) {
// use Austria
url = 'https://store-data-service.services.dmtech.com/stores/item/at/' + storeId
req = new Request(url)
apiResult = await req.loadJSON()
if (req.response.statusCode == 200) {
country = 'at'
widget.url = 'https://www.dm.at/search?query=toilettenpapier&searchType=product'
}
} else if (req.response.statusCode == 200) {
country = 'de'
widget.url = 'https://www.dm.de/search?query=toilettenpapier&searchType=product'
apiResult = JSON.parse(apiResult)
}
return apiResult
}
// checks whether the store is currently open or closed
function isInRange(value, range) {
return value >= range[0] && value <= range[1];
}
// get images from local filestore or download them once
async function getImage(image) {
let fm = FileManager.local()
let dir = fm.documentsDirectory()
let path = fm.joinPath(dir, image)
if (fm.fileExists(path)) {
return fm.readImage(path)
} else {
// download once
let imageUrl
switch (image) {
case 'dm-logo.png':
imageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/5/50/Dm_Logo.svg/300px-Dm_Logo.svg.png"
break
case 'toilet-paper.png':
imageUrl = "https://i.imgur.com/Uv1qZGV.png"
break
default:
console.log(`Sorry, couldn't find ${image}.`);
}
let iconImage = await loadImage(imageUrl)
fm.writeImage(path, iconImage)
return iconImage
}
}
// helper function to download an image from a given url
async function loadImage(imgUrl) {
const req = new Request(imgUrl)
return await req.loadImage()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment