Last active
November 26, 2021 07:40
-
-
Save leo848/7919e0ea059815ab1c30fb6e7e63d98d to your computer and use it in GitHub Desktop.
An extra large widget (for the iPad) displaying a random Wikipedia article as well as an image, a short summary and related links.
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: light-gray; icon-glyph: user-graduate; | |
const lang = args.widgetParameter || args.queryParameters.lang || "de" | |
let res, img, links, related = []; | |
let qParams = args.queryParameters; | |
// qParams.title = qParams.title || "4529281" | |
//if (config.runsInApp) sendNotification("qParams", qParams); | |
qParams?.title ? | |
await initializeGlobalsWithTitle(qParams.title) : | |
await initializeGlobals(); | |
console.log(links); | |
Array.prototype.last = function(){ | |
return this[this.length - 1]; | |
}; | |
Array.prototype.randomChoice = function(){ | |
return this[Math.floor(Math.random() * this.length)] | |
} | |
let widget = createWidget({ | |
title: res?.title, | |
desc: res?.description, | |
body: res?.extract, | |
img: img, | |
imgUrl: res?.originalimage?.source, url: res?.content_urls?.mobile.page | |
}) | |
if (config.runsInWidget) { | |
// create and show widget | |
Script.setWidget(widget) | |
Script.complete() | |
} | |
else { | |
widget.presentExtraLarge(); | |
} | |
async function initializeGlobals(){ | |
let articleNotAvailable = true; | |
for (let mxctr = 0; | |
mxctr < 10 && articleNotAvailable; | |
mxctr++){ | |
try { | |
res = await loadRandomArticle(lang); | |
img = await loadThumbnail(res); | |
links = await loadLinks(res); | |
articleNotAvailable = false; | |
} catch (e) { | |
console.log(e) | |
} | |
} | |
} | |
async function initializeGlobalsWithTitle(title) { | |
let ttitle = Number(qParams.title); | |
if (isNaN(ttitle)) throw "Not a Number, but " + title | |
res = await loadArticleByPageID(lang, ttitle) | |
log("init by number") | |
//sendNotification(title, qParams); | |
img = await loadThumbnail(res); | |
links = await loadLinks(res); | |
} | |
async function loadRandomArticle(lang){ | |
const url = `https://${lang}.wikipedia.org/api/rest_v1/page/random/summary`; | |
const req = new Request(url); | |
return await req.loadJSON(); | |
} | |
async function loadArticleByTitle(lang,title){ | |
const url = `https://${lang}.wikipedia.org/api/rest_v1/page/summary/${encodeURIComponent(title.replace(" ", "_"))}` | |
const req = new Request(url); | |
return await req.loadJSON(); | |
} | |
async function loadArticleByPageID(lang,id){ const url = `https://${lang}.wikipedia.org/w/api.php?action=query&pageids=${id}&format=json`; | |
const req = new Request(url); | |
const title = (await req.loadJSON())?.query.pages[id].title.replace(" ", "_"); | |
console.log("lABPID title: " + title); | |
return (await loadArticleByTitle(lang,title)); | |
} | |
async function loadThumbnail(res){ | |
if (!res?.thumbnail?.source) return; | |
return await new Request(res.thumbnail.source).loadImage(); | |
} | |
async function loadLinks(res){ | |
const canon = (res.content_urls?.desktop?.page??"/") | |
.split("/") | |
.slice(-1)[0]; | |
console.log("canon: " + canon); | |
const url = `https://${lang}.wikipedia.org/w/api.php?action=query&titles=${canon}&prop=links&pllimit=max&format=json`; | |
const request = new Request(url) | |
const json = await request.loadJSON(); | |
const links = json?.query?.pages[res.pageid]?.links ?? []; | |
const retArr = []; | |
for (let i = 0, sfctr = 0; i < 3 && sfctr < 100; i++, sfctr++){ | |
let elt = links[ | |
Math.floor(Math.random()*links.length) | |
].title; | |
let id = (await loadArticleByTitle(lang, elt)).pageid | |
//log("name: " + elt); | |
console.log("pageid: " + id); | |
if (!retArr.includes(id)) {retArr.push(id);related.push(elt)} | |
else i--; | |
} | |
return retArr | |
} | |
function createWidget(obj){//title, desc, body, img, imgUrl, widgeturl) { | |
console.log("Title: "+obj.title) | |
console.log("Desc: " +obj.imgDesc) | |
let w = new ListWidget() | |
w.backgroundGradient = createGradient(); | |
let stack = w.addStack() | |
stack.layoutHorizontally() | |
if (obj.img){ | |
let imageStack = stack.addStack(); | |
imageStack.layoutVertically(); | |
imageStack.size = new Size(220, 0); | |
imageStack.centerAlignContent() | |
let image = imageStack.addImage(obj.img); | |
image.centerAlignImage() | |
image.applyFittingContentMode() | |
image.url = obj.imgUrl; | |
image.cornerRadius = 15; | |
stack.addSpacer(20); | |
} | |
let innerTextStack = stack.addStack(); | |
innerTextStack.setPadding(2, 5, 2, 5); | |
innerTextStack.cornerRadius = 15; | |
//innerTextStack.borderWidth = 5; | |
innerTextStack.layoutVertically(); | |
let titleTxt = innerTextStack.addText(obj.title ?? "No title (wait what)") | |
titleTxt.textColor = Color.white() | |
titleTxt.font = Font.boldSystemFont(30); | |
titleTxt.url = obj.url; | |
let descText = innerTextStack.addText(obj.desc ?? "No description"); | |
descText.textColor = Color.gray() | |
descText.font = Font.italicSystemFont(18); | |
innerTextStack.addSpacer(3) | |
let bodyText = innerTextStack.addText(obj.body ?? "No body (?)"); | |
bodyText.textColor = Color.white() | |
bodyText.font = getAppropiateFontSize(obj.desc?.length ?? 0, obj.body.length); | |
innerTextStack.addSpacer() | |
let actionStack = innerTextStack.addStack(); | |
actionStack.layoutHorizontally(); | |
let refreshText = actionStack.addText("Neu laden") | |
refreshText.textColor = Color.blue() | |
refreshText.font = Font.systemFont(14) | |
refreshText.url = "scriptable:///run/Random%20Wikipedia"; | |
for (let i = 0; i < links.length; i++){ | |
actionStack.addSpacer() ; | |
let lURL = actionStack.addText((related[i]??"").toString()); | |
lURL.textColor = Color.blue() | |
lURL.font = Font.systemFont(12) | |
lURL.url = `scriptable:///run?scriptName=Random%20Wikipedia&title=${links[i]}&lang=${lang}`; | |
lURL.centerAlignText() | |
} | |
actionStack.addSpacer() | |
stack.setPadding(0,0,0,0) | |
w.url = obj.url | |
return w | |
} | |
function alert(title, body){ | |
let alert = new Alert(); | |
alert.title = title.toString(); | |
alert.message = body.toString(); | |
alert.addAction("Close") | |
alert.presentAlert() | |
} | |
function sendNotification(title, body) { let notif = new Notification() | |
notif.title = JSON.stringify(title); | |
notif.body = JSON.stringify(body); | |
notif.schedule() | |
} | |
/*function encode(str) { | |
console.log("trying to decode str: " + str); | |
return str? btoa(unescape(encodeURIComponent(str))) : | |
str; | |
} | |
function decode(str) { | |
console.log("trying to decode str: " + str); | |
return str? decodeURIComponent(escape(atob(str))): str; | |
}*/ | |
function getAppropiateFontSize(descLength, bodyLength){ | |
let size, totalLength = descLength + bodyLength; | |
console.log(totalLength) | |
if (totalLength < 50) size = 28; | |
else if (totalLength < 125) size = 24; | |
else if (totalLength < 200) size = 20; | |
else if (totalLength < 250) size = 18; | |
else if (totalLength < 400) size = 16; | |
else if (totalLength < 600) size = 14; | |
else if (totalLength < 800) size = 13; | |
else if (totalLength < 1000) size = 12; | |
else size = 10; | |
return Font.systemFont(size); | |
} | |
function createGradient(color1, color2) { | |
let gradient = new LinearGradient() | |
gradient.locations = [0,1] | |
gradient.startPoint = new Point(0,0); | |
gradient.endPoint = new Point(0.4,1); | |
gradient.colors = [new Color(color1 ?? "#535353"), new Color(color2 ?? "#000000")] | |
return gradient; | |
} | |
function randomColor(){ | |
const colors = "0123456789ABCDEF" | |
let string = "" | |
for (let i = 0; i < 6; i++){ | |
string += colors[randint(colors.length)] | |
} | |
return new Color(string); | |
} | |
function randint(limit){ | |
return Math.floor(Math.random() * limit); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment