Last active
October 1, 2023 18:28
-
-
Save marco79cgn/bba78cb20e9c0847e9d24414f1a07eb5 to your computer and use it in GitHub Desktop.
A custom widget showing editors picks of the ARD Mediathek for scriptable.app
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: film; | |
// name: ard-mediathek.js | |
// description: A scriptable widget which displays the latest editorial picks of the ARD Mediathek | |
// author: Marco Dengel | |
// email: [email protected] | |
let mediathekData; | |
try { | |
mediathekData = await new Request( | |
'https://api.ardmediathek.de/page-gateway/widgets/ard/editorials/1FdQ5oz2JK6o2qmyqMsqiI:-5299873058662924535?pageNumber=0&pageSize=10' | |
).loadJSON(); | |
} catch (e) { | |
const errorWidget = createErrorWidget(); | |
if (!config.runsInWidget) { | |
await errorWidget.presentMedium(); | |
} else { | |
Script.setWidget(errorWidget); | |
} | |
Script.complete(); | |
} | |
const widget = await createWidget(); | |
if (!config.runsInWidget) { | |
await widget.presentMedium(); | |
} else { | |
Script.setWidget(widget); | |
} | |
Script.complete(); | |
async function createWidget() { | |
let listWidget = new ListWidget(); | |
listWidget.setPadding(10,10,10,10); | |
listWidget.backgroundImage = await loadImage( | |
'https://www.designtagebuch.de/wp-content/uploads/mediathek//2015/03/daserste-corporate-background.jpg' | |
); | |
listWidget = await createHeaderImage(listWidget); | |
listWidget.addSpacer(14); | |
// Get two different random items | |
let itemNumber = getRandomNumber(1, mediathekData.teasers.length) - 1 | |
let itemNumber2 | |
do { | |
itemNumber2 = getRandomNumber(1, mediathekData.teasers.length) - 1 | |
} while (itemNumber2 === itemNumber) | |
listWidget = await createArticle(listWidget, mediathekData.teasers[itemNumber]); | |
listWidget.addSpacer(10) | |
listWidget = await createArticle(listWidget,mediathekData.teasers[itemNumber2]) | |
return listWidget; | |
} | |
async function createArticle(listWidget, data) { | |
const { shortTitle } = data; | |
let date; | |
if (data.broadcastedOn) { | |
date = new Date(data.broadcastedOn); | |
} | |
const image = data.images.aspect16x9.src.replace('{width}', 200); | |
let ressort | |
if(data.publicationService) { | |
ressort = data.publicationService.name | |
} else { | |
ressort = 'Sonstiges' | |
} | |
const article = listWidget.addStack(); | |
const articleImage = article.addImage(await loadImage(image)); | |
articleImage.cornerRadius = 5; | |
articleImage.imageSize = new Size(85,48) | |
let mediaUrl = await getMediaUrl(data) | |
article.url = mediaUrl | |
article.addSpacer(6); | |
const articleInfo = article.addStack(); | |
articleInfo.layoutVertically(); | |
const articleRessort = articleInfo.addText(ressort); | |
articleRessort.textColor = Color.yellow(); | |
articleRessort.font = Font.boldMonospacedSystemFont(11); | |
articleInfo.addSpacer(2) | |
const articleTitle = articleInfo.addText(shortTitle.trim()); | |
articleTitle.textColor = Color.white(); | |
articleTitle.font = Font.semiboldMonospacedSystemFont(13) | |
articleTitle.lineLimit = 1 | |
articleTitle.minimumScaleFactor = 0.7; | |
articleInfo.addSpacer(2) | |
if (date) { | |
const articleDate = articleInfo.addText(formatDate(date)); | |
articleDate.font = Font.semiboldMonospacedSystemFont(11); | |
articleDate.textOpacity = 0.7; | |
articleDate.textColor = Color.white() | |
} | |
return listWidget; | |
} | |
async function createHeaderImage(listWidget) { | |
const headerImage = listWidget.addImage( | |
await getImage('mediathek-logo.png') | |
); | |
headerImage.imageSize = new Size(100, 8); | |
headerImage.tintColor = Color.white(); | |
headerImage.centerAlignImage(); | |
headerImage.applyFillingContentMode(); | |
return listWidget; | |
} | |
function createErrorWidget() { | |
const errorWidget = new ListWidget(); | |
const bgGradient = new LinearGradient(); | |
bgGradient.locations = [0, 1]; | |
bgGradient.colors = [new Color('#2D65AE'), new Color('#19274C')]; | |
errorWidget.backgroundGradient = bgGradient; | |
const title = errorWidget.addText('ARD Mediathek'); | |
title.font = Font.headline(); | |
title.centerAlignText(); | |
title.textColor = Color.white() | |
errorWidget.addSpacer(10); | |
const errorText = errorWidget.addText( | |
'Es besteht momentan keine Verbindung zum Internet.' | |
); | |
errorText.font = Font.semiboldMonospacedSystemFont(16); | |
errorText.textColor = Color.red(); | |
errorText.centerAlignText() | |
return errorWidget; | |
} | |
async function loadImage(url) { | |
return await new Request(url).loadImage(); | |
} | |
function formatDate(dateObject) { | |
return `${leadingZero(dateObject.getDate())}.${leadingZero( | |
dateObject.getMonth() + 1 | |
)}.${dateObject.getFullYear()}, ${leadingZero( | |
dateObject.getHours() | |
)}:${leadingZero(dateObject.getMinutes())} Uhr`; | |
} | |
function leadingZero(input) { | |
return ('0' + input).slice(-2); | |
} | |
// random number, min and max included | |
function getRandomNumber(min, max) { | |
return Math.floor(Math.random() * (max - min + 1) + min) | |
} | |
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 'mediathek-logo.png': | |
imageUrl = "https://i.imgur.com/vUfzOhj.png" | |
break | |
default: | |
console.log(`Sorry, couldn't find ${image}.`); | |
} | |
let iconImage = await loadImage(imageUrl) | |
fm.writeImage(path, iconImage) | |
return iconImage | |
} | |
} | |
async function getMediaUrl(data) { | |
let targetUrl = data.links.target.href.replace('&embedded=true','').replace('?embedded=true','') | |
let mediaUrl | |
if(targetUrl.indexOf('/item/') > 0) { | |
const mediaResult = await new Request(targetUrl).loadJSON() | |
mediaUrl = mediaResult.widgets[0].mediaCollection.embedded._mediaArray[0]._mediaStreamArray[0]._stream | |
if(mediaUrl.startsWith('//')) { | |
mediaUrl = 'https:' + mediaUrl | |
} | |
} else if(targetUrl.indexOf('retro') > 0) { | |
mediaUrl = 'https://www.ardmediathek.de/ard/retro/' | |
} else if(data.type.toLowerCase() === 'show') { | |
mediaUrl = 'https://www.ardmediathek.de/ard/sendung/' + data.links.target.id | |
} | |
else { | |
const nextResult = await new Request(targetUrl).loadJSON() | |
const mediaResult = await new Request(nextResult.widgets[0].teasers[0].links.target.href.replace('&embedded=true','').replace('?embedded=true','')).loadJSON() | |
mediaUrl = mediaResult.widgets[0].mediaCollection.embedded._mediaArray[0]._mediaStreamArray[0]._stream | |
} | |
return mediaUrl | |
} | |
// Ende des Skripts | |
// Bitte alles markieren! |
Update: 01.10.2023
Fixed api url.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Intro
Das Widget zeigt die neuesten Editor's Picks der ARD Mediathek in zufälliger Reihenfolge an. Ein Tap genügt, um das jeweilige Video direkt abzuspielen. Serien und Sammlungen werden im Browser geöffnet.
Anforderungen
Installation
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 Das Erste/ARD.