Skip to content

Instantly share code, notes, and snippets.

@marco79cgn
Last active March 3, 2021 08:38
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save marco79cgn/092de56c52ab2b6f7b7e6632f5779e75 to your computer and use it in GitHub Desktop.
Save marco79cgn/092de56c52ab2b6f7b7e6632f5779e75 to your computer and use it in GitHub Desktop.
iOS widget, das die neueste Folge des radioeins Podcasts "Wach & Wichtig" anzeigt und abspielt (für die Scriptable.app)
// Wach und Wichtig Podcast Widget
//
// Copyright (C) 2020 by marco79 <marco79cgn@gmail.com>
//
// Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
// IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
// OF THIS SOFTWARE.
let param = args.widgetParameter
let radioeinsOrange = new Color("#FF9300")
let latestEpisode = await getLatestEpisode(false)
let widget = await createWidget(latestEpisode)
Script.setWidget(widget)
Script.complete()
widget.presentSmall()
// Erzeugt das Widget Layout
async function createWidget(latestEpisode) {
let widget = new ListWidget()
widget.setPadding(0,6,6,6)
let logoStack = widget.addStack()
logoStack.layoutHorizontally()
logoStack.addSpacer()
let logoImg = logoStack.addImage(await getImage("radioeins-logo.png"))
logoImg.imageSize = new Size(70,20)
logoImg.centerAlignImage()
let coverStack = widget.addStack()
coverStack.layoutVertically()
let coverImage = coverStack.addImage(await getImage("wuw-logo.jpg"))
widget.addSpacer(2)
let day = new Date(latestEpisode.pubDate.replace(" ","T"))
let df = new DateFormatter()
df.dateFormat = "dd. MMMM"
let strDate = df.string(day)
let dayText = widget.addText(getWeekday(day) + ", " + strDate)
dayText.font = Font.boldSystemFont(11)
dayText.textColor = radioeinsOrange
dayText.lineLimit = 1
dayText.minimumScaleFactor = 0.8
let titleTxt = widget.addText(latestEpisode.title)
titleTxt.font = Font.semiboldSystemFont(11)
titleTxt.lineLimit = 4
titleTxt.minimumScaleFactor = 0.8
widget.addSpacer(2)
let playStack = widget.addStack()
playStack.layoutHorizontally()
let playImage = playStack.addImage(await getImage("play-button.png"))
playImage.imageSize = new Size(18,18)
playStack.addSpacer(3)
let playTextStack = playStack.addStack()
playTextStack.layoutVertically()
playTextStack.addSpacer(2)
let playText = playTextStack.addText("Podcast hören")
playText.font = Font.semiboldRoundedSystemFont(11)
playText.textColor = radioeinsOrange
if(param != null) {
switch(param.toString().toLowerCase()) {
case 'vlc':
widget.url = "vlc-x-callback://x-callback-url/stream?url=" + latestEpisode.link.toString()
break
case 'spotify':
widget.url = "https://open.spotify.com/show/4LsArcokwkKXmygKFASuka?si=eL2dXCYlTpaXjDH-sKpyHA"
break
case 'audiothek':
widget.url = "https://www.ardaudiothek.de/wach-wichtig/80923132"
break
case 'itunes':
widget.url = "https://podcasts.apple.com/us/podcast/wach-wichtig-radioeins/id171374241"
break
case 'apple':
widget.url = "https://podcasts.apple.com/us/podcast/wach-wichtig-radioeins/id171374241"
break
default:
widget.url = latestEpisode.link
}
} else {
widget.url = latestEpisode.link
}
return widget
}
// lädt die neueste Folge, wenn möglich aus dem Cache
async function getLatestEpisode(forceFetch) {
const url = "https://api.rss2json.com/v1/api.json?rss_url=https://www.radioeins.de/archiv/podcast/wachundwichtig.xml/feed=podcast.xml"
if(!forceFetch) {
const cachedEpisode = await loadCachedEpisode()
let todayYMD = new Date().toISOString().split("T")[0]
let today = new Date().getDay()
if (today > 0 && today < 6) {
// MO-FR → lade gecachet oder neu
if(cachedEpisode != null) {
const cachedYMD = cachedEpisode.pubDate.split(' ')[0]
if (todayYMD === cachedYMD) {
return cachedEpisode
} else {
let req = new Request(url)
let json = await req.loadJSON()
await saveLatestEpisode(JSON.stringify(json.items[0]))
return json.items[0]
}
} else {
forceFetch = true
}
} else {
// SA oder SO, lade gecachte Folge, falls vorhanden
if (cachedEpisode != null) {
return cachedEpisode
} else {
forceFetch = true
}
}
}
if(forceFetch) {
console.log("forced fetch")
let req = new Request(url)
let json = await req.loadJSON()
await saveLatestEpisode(JSON.stringify(json.items[0]))
return json.items[0]
}
}
// Ermittelt den Wochentag für einen übergebenen Tag
function getWeekday(date) {
var weekday = new Array(7);
weekday[0] = "Sonntag";
weekday[1] = "Montag";
weekday[2] = "Dienstag";
weekday[3] = "Mittwoch";
weekday[4] = "Donnerstag";
weekday[5] = "Freitag";
weekday[6] = "Samstag";
return weekday[date.getDay()];
}
// Lädt Metadaten der letzten gecachten Folge aus iCloud Drive
async function loadCachedEpisode() {
let fm = FileManager.iCloud()
let dir = fm.documentsDirectory()
let path = fm.joinPath(dir, "wuw-latest-episode.txt")
let latestEpisode = Data.fromFile(path)
if (latestEpisode != null) {
return JSON.parse(latestEpisode.toRawString())
} else {
return null
}
}
// Speichert Meta-Informationen der neuesten Folge in iCloud Drive
async function saveLatestEpisode(latestEpisode) {
let fm = FileManager.iCloud()
let dir = fm.documentsDirectory()
let path = fm.joinPath(dir, "wuw-latest-episode.txt")
fm.writeString(path, latestEpisode)
}
// Lädt Bilder einmalig aus dem Netz, ansonsten gecachet
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 'radioeins-logo.png':
imageUrl = "https://i.imgur.com/qfmIT2S.png"
break
case 'wuw-logo.jpg':
imageUrl = "https://i.imgur.com/hLFaeIz.jpg"
break
case 'play-button.png':
imageUrl = "http://www.myiconfinder.com/uploads/iconsets/256-256-0424923e1bfdd129567c714224d38010.png"
break
default:
console.log(`Sorry, couldn't find ${image}.`);
}
let iconImage = await loadImage(imageUrl)
fm.writeImage(path, iconImage)
return iconImage
}
}
// Lädt ein Bild von einer übergebenen URL
async function loadImage(imgUrl) {
const req = new Request(imgUrl)
return await req.loadImage()
}
// Ende des Skripts
// Bitte alles bis zum Ende markieren
@marco79cgn
Copy link
Author

marco79cgn commented Oct 30, 2020

Intro

Das Wach & Wichtig Widget zeigt die neueste Folge des gleichnamigen Podcasts von radioeins an. Ein Tap auf das Widget genügt, um die Folge automatisch abzuspielen.

Anforderungen

Installation

  • Kopiere den Quellcode von oben (klick vorher auf "raw" oben rechts oder hier)
  • Achte darauf, den gesamten Code bis zum Ende zu markieren
  • Öffne die Scriptable app
  • Klick auf das "+" Symbol oben rechts und füge das kopierte Skript aus der Zwischenablage ein
  • Klick auf den Titel des Skripts ganz oben und vergebe einen Namen (z.B. Wach-und-Wichtig)
  • Speichere das Skript durch Klick auf "Done" oben links
  • Gehe auf deinen iOS Homescreen und drücke irgendwo lang, um in den "Wiggle Modus" zu kommen (mit dem man auch die Apps anordnen kann)
  • Drücke das "+" Symbol oben links, blättere dann nach unten zu "Scriptable" (Liste ist alphabetisch), wähle die erste Widget Größe (small) und drück unten auf "Widget hinzufügen"
  • Drücke auf das Widget, um seine Einstellungen zu bearbeiten (optional lang drücken, wenn der Wiggle Modus schon beendet wurde)
  • Wähle unter "Script" das oben erstellte aus (Wach-und-Wichtig)

Optional:

  • Gib als "Parameter" eine der folgenden Optionen an, wenn du den Podcast statt in Safari (Standard) lieber in einer anderen App hören willst:
    • spotify
    • vlc
    • apple
    • audiothek

Hinweis: Autoplay funktioniert nur via Safari (default) oder VLC.

Danke

Großer Dank an @simonbs für großartige Apps wie Scriptable, DataJar oder Jayson.

Disclaimer

Es handelt sich um ein von mir selbst entwickeltes Spaßprojekt, kein offizielles Produkt von radioeins.

@kokos1405
Copy link

Hi and congruts.

Where are the images stored? If i change the image link i don't see the new image. If i also change the name on all images the script does not run. What am i doing wrong?

@marco79cgn
Copy link
Author

marco79cgn commented Nov 4, 2020

Hi and congruts.

Where are the images stored? If i change the image link i don't see the new image. If i also change the name on all images the script does not run. What am i doing wrong?

I built an image cache which works like this:
If an image named 'radioeins-logo.png' is already present in the local file store of the Scriptable app, this image will be loaded (locally). If it is not available, it will be downloaded once from the internet (using the given url). This happens usually the first time you run the script (or your widget triggers it).

There are different possibilities to change this behaviour:

  • remove the if/else condition which checks whether the image is already available temporarily by uncommenting Line 180-182 and 201
  • write a delete function and remove the three files from the store (once), like this:
let fm = FileManager.local()
let dir = fm.documentsDirectory()
let path = fm.joinPath(dir, 'radioeins-logo.png')
fm.remove(path)

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