Skip to content

Instantly share code, notes, and snippets.

@achisto
Forked from marco79cgn/dm-toilet-paper.js
Last active October 29, 2020 19:42
Show Gist options
  • Save achisto/ebccd305226218f1cbd01540213403c3 to your computer and use it in GitHub Desktop.
Save achisto/ebccd305226218f1cbd01540213403c3 to your computer and use it in GitHub Desktop.
Scriptable iOS widget that shows the amount of flour which is available at your next dm drugstore
// Forked from https://gist.github.com/marco79cgn/23ce08fd8711ee893a3be12d4543f2d2
// Based on the code at 24 Oct 2020 00:24
//
// Displays the amount of flour that is still available.
// Product numbers taken from a search for "Weizenmehl": https://www.dm.de/search?query=weizenmehl&searchType=product
//
// Icon made by Freepik from www.flaticon.com and modified by achisto
//
let country = 'de'
let storeId = 251
let grain = 'Weizen'
let type = '1050'
if (!config.runsInWidget) {
} else {
const params = args.widgetParameter ? args.widgetParameter.split(",") : undefined
country = params[0]
storeId = params[1]
grain = params[2]
type = params[3]
}
let typeName;
let typeId;
// // // Mehl-Sorten dan DE // // //
//
// Weizen
// 550 459912,488334
// 1050 468120
// Vollkorn 468178,706590
//
// Dinkel
// 1050 468119
// 630 461923
// Vollkorn 467198
//
// Roggen
// Vollkorn 468121,704854
//
// Hafer
// glutenfrei 721676
//
// Buchweizen
// vollkorn 468168
//
//
// // // Mehl-Sorten dan AT // // //
//
// Weizen
// 550
// 1050
// Vollkorn
//
// Dinkel
// 1050
// 630
// Vollkorn
//
// Roggen
// Vollkorn
//
// Hafer
// glutenfrei
//
// Buchweizen
// vollkorn
//
//
if (grain === "Weizen") {
if (type === "550") {
typeId = '459912,488334'
typeName = 'Weizen 550'
}
if (type === "1050") {
typeId = '468120'
typeName = 'Weizen 1050'
}
if (type === "Vollkorn") {
typeId = '468178,706590'
typeName = 'Weizen Voll'
}
}
if (grain === "Dinkel") {
if (type === "1050") {
typeId = '468119'
typeName = 'Dinkel 1050'
}
if (type === "630") {
typeId = '461923'
typeName = 'Dinkel 630'
}
if (type === "Vollkorn") {
typeId = '467198'
typeName = 'Dinkel Voll'
}
}
if (grain === "Roggen") {
typeId = '468121,704854'
typeName = 'Roggen Voll'
}
if (grain === "Hafer") {
typeId = '468121,704854'
typeName = 'Hafer gluten'
}
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('flour.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(typeName)
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()
let isOpen
if (currentDay > 0) {
const todaysOpeningHour = storeInfo.openingHours[currentDay-1].timeRanges[0].opening
const todaysClosingHour = storeInfo.openingHours[currentDay-1].timeRanges[0].closing
const range = [todaysOpeningHour, todaysClosingHour];
isOpen = isInRange(currentTime, range)
} else {
isOpen = false
}
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 = ["178498", "178489", "223485", "253667", "63675", "178516"]
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=' + typeId + '&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
if (country.toLowerCase() === 'at') {
url = 'https://store-data-service.services.dmtech.com/stores/item/at/' + storeId
widget.url = 'https://www.dm.at/search?query=mehl&searchType=product'
} else {
url = 'https://store-data-service.services.dmtech.com/stores/item/de/' + storeId
widget.url = 'https://www.dm.de/search?query=mehl&searchType=product'
}
let req = new Request(url)
let apiResult = await req.loadJSON()
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 'flour.png':
imageUrl = "https://i.imgur.com/gwWtMWn.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()
}
// end of script
@achisto
Copy link
Author

achisto commented Oct 24, 2020

Tolles Widget! Könntest du es noch so anpassen, dass die genaue Anzahl für die jeweiligen Mehlsorten und -typen angezeigt wird? Vielleicht auch so, dass man im Skript die gewünschten Sorten auswählen kann. Beispielsweise Weizen 550, Weizen 1050, Weizen Vollkorn und Roggen Vollkorn.

Das Widget unterstützt jetzt die Auswahl einer Mehlsorte:

mehlv2

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