From 352632e5a56b0e44c6e5ecb5757d182a0ab2fc98 Mon Sep 17 00:00:00 2001 From: Jan Andrle Date: Sun, 12 May 2024 10:16:48 +0200 Subject: [PATCH] :zap: use wikimedia Potd as HTML wallpaper [Commons:Picture of the day - Wikimedia Commons](https://commons.wikimedia.org/wiki/Commons:Picture_of_the_day) --- .../Bing Image Of The Day/index_template.html | 39 +++--- bin/§wallpaper_BIOTD | 6 + bin/§wallpaper_WCPOTD.mjs | 113 ++++++++++++++++++ 3 files changed, 139 insertions(+), 19 deletions(-) create mode 100755 bin/§wallpaper_BIOTD create mode 100755 bin/§wallpaper_WCPOTD.mjs diff --git a/Obrázky/Bing Image Of The Day/index_template.html b/Obrázky/Bing Image Of The Day/index_template.html index e511b1d..22ec9f9 100644 --- a/Obrázky/Bing Image Of The Day/index_template.html +++ b/Obrázky/Bing Image Of The Day/index_template.html @@ -1,26 +1,27 @@ - - - - Bing Image Of The Day - + + + + Bing Image Of The Day + -
::now::
- +
::now::
+ diff --git a/bin/§wallpaper_BIOTD b/bin/§wallpaper_BIOTD new file mode 100755 index 0000000..5bb40c7 --- /dev/null +++ b/bin/§wallpaper_BIOTD @@ -0,0 +1,6 @@ +#!/bin/bash +nm-online -x -q && \ + node "/home/jaandrle/.nvm/versions/node/$(node --version)/bin/nodejsscript" /home/jaandrle/bin/§wallpaper_WCPOTD.mjs pull && \ + cd "/home/jaandrle/Obrázky/Bing Image Of The Day" && \ + qdbus org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript 'const d= desktops().filter(d=> d.wallpaperPlugin==="de.unkn0wn.htmlwallpaper")[0];const url= (i= "")=> `file:///home/jaandrle/Obr%C3%A1zky/Bing%20Image%20Of%20The%20Day/index${i}.html`;d.currentConfigGroup= Array("Wallpaper", "de.unkn0wn.htmlwallpaper","General");d.writeConfig("DisplayPage", url("1"));d.writeConfig("DisplayPage", url());' +# convert now.jpg prev.jpg +append horizontally.jpg diff --git a/bin/§wallpaper_WCPOTD.mjs b/bin/§wallpaper_WCPOTD.mjs new file mode 100755 index 0000000..e8a2299 --- /dev/null +++ b/bin/§wallpaper_WCPOTD.mjs @@ -0,0 +1,113 @@ +#!/usr/bin/env nodejsscript +/* jshint esversion: 11,-W097, -W040, module: true, node: true, expr: true, undef: true *//* global echo, $, pipe, s, fetch, cyclicLoop */ +const img_params= "?width=1920"; +const url_api= "https://commons.wikimedia.org/w/api.php"; +const url_image= "https://commons.wikimedia.org/wiki/Special:FilePath/"; + +import { join } from "node:path"; +const path_home= $.xdg.home`Obrázky/Bing Image Of The Day/`; +const path_info= join(path_home, "images.json"); + +$.api() +.version("2024-05-12") +.command("pull", "Pull new/today image(s)") +.action(async function pull(){ + const images= { + now: await getImagePath(0), + prev: await getImagePath(-1) + }; + const paths= await downloadImages(images); + updateHTML(images); + convert(paths); + pipe( + images=> Object.entries(images) + .reduce((acc, [ key, { caption } ])=> + Reflect.set(acc, key, caption) && acc, + {}), + images=> JSON.stringify(images, null, "\t"), + s.echo + )(images).to(path_info); + $.exit(0); +}) +.command("status") +.action(function status(){ + const images= s.cat(path_info).xargs(JSON.parse); + const [ stats ]= s.ls("-l", path_info); + echo({ timestamp: stats.mtime, ...images }); + $.exit(0); +}) +.parse(); +/** @typedef {{ url: string, caption: string }} T_response */ +/** @typedef {Record<"now"|"prev",T_response>} T_images */ +/** @param {Record<"now"|"prev",string>} paths */ +function convert(paths){ + const resize_to= "1920x1080"; + + paths= Object.values(paths); + const target= join(path_home, "horizontally.jpg"); + const params= `-resize ${resize_to}^ -gravity center -extent ${resize_to}`.split(" "); + s.run`convert ${paths} ${params} +append ${target}`; +} +import { writeFileSync } from "node:fs"; +/** @param {T_images} images */ +function updateHTML(images){ + let template= s.cat(join(path_home, "index_template.html")).trim(); + for(const [ key, image ] of Object.entries(images)) + template= template.replace(`::${key}::`, image.caption); + s.echo(template).to(join(path_home, "index.html")); +} +/** @param {T_images} images */ +async function downloadImages(images){ + const out= {}; + for(const [ key, image ] of Object.entries(images)) + out[key]= await downloadImage(image, key); + return out; +} +async function getImagePath(shift= 0){ + const date= dateISO(shift); + const { expandtemplates: { wikitext: filepath } }= await fetchGet({ + action: "expandtemplates", + prop: "wikitext", + text: `{{Potd/${date}}}`, + }); + const caption= pipe( + response=> response.expandtemplates.wikitext, + caption=> caption.replace(/\[\[.*?\]\]/g, m=> m.slice(2, -2).split("|").reverse()[0]), + caption=> caption.replace(/''(.*?)''/g, "„$1”"), + )(await fetchGet({ + action: "expandtemplates", + prop: "wikitext", + text: `{{Potd/${date} (cs)}}`, + })); + /* TODO? + * action: 'query', + * prop: 'imageinfo', + * iiprop: 'extmetadata', + * iiextmetadatafilter: 'LicenseShortName|Artist|LicenseUrl', + * titles: `Image:${ filename }` + * + * res.data.query.pages[0].imageinfo[0].extmetadata + * */ + return { + caption: caption, + url: url_image+encodeURI(filepath+img_params) + }; +} + +/** @param {T_response} image @param {"prev"|"now"} type */ +async function downloadImage({ url }, type){ + const filename= join(path_home, `${type}.jpg`); + const response= await fetch(url); + const buffer= await response.arrayBuffer(); + writeFileSync(filename, Buffer.from(buffer)); + return filename; +} +function dateISO(shift= 0){ + const d= new Date(); + d.setDate(d.getDate()+shift); + return d.toISOString().substring(0, 10); +} +function fetchGet(params){ + if(!params.format) params.format= "json"; + return fetch(url_api+"?"+(new URLSearchParams(params)).toString(), { method: "GET" }).then(res=> res.json()); +}