Created
July 15, 2021 19:47
-
-
Save Vogeslu/bb8dfb42e55f7b774a36f4b02e43f470 to your computer and use it in GitHub Desktop.
scriptable nextbike widget
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
// Maximum distance to next bike | |
const defaultDistance = 2000 | |
// List only stations or stationless bikes as well | |
const onlyStations = true | |
// Auto update every 20 minutes | |
const autoUpdate = true | |
function getLocationApi(position, distance = defaultDistance) { | |
return `https://api.nextbike.net/maps/nextbike-live.json?lat=${position.latitude}&lng=${position.longitude}&distance=${distance}`; | |
} | |
const widget = await createWidget() | |
if (!config.runsInWidget) { | |
await widget.presentSmall() | |
} | |
Script.setWidget(widget) | |
Script.complete() | |
async function createWidget(items) { | |
const data = await getData() | |
const list = new ListWidget() | |
const header = list.addText("🚲 nextbike") | |
header.font = Font.mediumSystemFont(13) | |
if(data) { | |
list.addSpacer() | |
let nextStation = null; | |
if(data.countries.length > 0) { | |
const country = data.countries[0]; | |
if(country.cities.length > 0) { | |
const city = country.cities[0]; | |
for(const place of city.places) { | |
if((place.bike && !onlyStations) || !place.bike) { | |
nextStation = { | |
name: place.name, | |
bikesAvailable: place.bikes_available_to_rent, | |
distance: place.dist | |
} | |
break | |
} | |
} | |
} | |
} | |
if(nextStation == null) { | |
const label = list.addText("Keine Stationen / Räder in der Nähe") | |
label.font = Font.boldSystemFont(16) | |
label.textColor = Color.red() | |
} else { | |
const label = list.addText(nextStation.name) | |
label.font = Font.mediumSystemFont(10) | |
list.addSpacer(12) | |
const count = list.addText(`${nextStation.bikesAvailable} ${nextStation.bikesAvailable === 1 ? 'Rad' : 'Räder'} verfügbar`) | |
count.font = Font.boldSystemFont(16) | |
count.textColor = nextStation.bikesAvailable > 0 ? Color.green() : Color.red() | |
list.addSpacer(6) | |
const distance = list.addText(nextStation.distance >= 1000 ? `${(nextStation.distance / 1000).toFixed(2)} km entfernt` : `${(nextStation.distance).toFixed(2)} m entfernt`) | |
distance.font = Font.mediumSystemFont(11) | |
} | |
if(autoUpdate) list.refreshAfterDate = new Date(Date.now() + 60*20*1000) | |
} else { | |
list.addSpacer() | |
list.addText("Daten nicht verfügbar") | |
} | |
return list | |
} | |
async function getData() { | |
try { | |
const location = await getLocation() | |
if(location) { | |
let data = await new Request(getLocationApi(location)).loadJSON() | |
return data | |
} else { | |
return null | |
} | |
} catch(e) { | |
return null | |
} | |
} | |
async function getLocation() { | |
try { | |
if(args.widgetParameter) { | |
const fixedCoordinates = args.widgetParameter.split(",").map(parseFloat) | |
return { latitude: fixedCoordinates[0], longitude: fixedCoordinates[1] } | |
} else { | |
Location.setAccuracyToThreeKilometers() | |
return await Location.current() | |
} | |
} catch(e) { | |
return null; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment