Skip to content

Instantly share code, notes, and snippets.

@marco79cgn
Last active October 1, 2023 18:28
Show Gist options
  • Save marco79cgn/bba78cb20e9c0847e9d24414f1a07eb5 to your computer and use it in GitHub Desktop.
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
// 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!
@marco79cgn
Copy link
Author

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