menicka-cron/cli.mjs
Jan Andrle b685634b54
All checks were successful
Update menicka / update-rss (push) Successful in 5m20s
🐛 fixes gitCommit + desc
2024-07-17 17:01:02 +02:00

135 lines
4.7 KiB
JavaScript
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env -S npx nodejsscript
/* jshint esversion: 11,-W097, -W040, module: true, node: true, expr: true, undef: true *//* global echo, $, pipe, s, fetch, cyclicLoop */
const { version, description }= s.cat("package.json").xargs(JSON.parse);
$.api()
.version(version)
.describe(description)
.command("pull", "Update article list")
.option("--git", "Update git repository")
.action(async function pull({ git: is_git= false }){
if(is_git) s.run`git pull --rebase`;
const menicka= await Promise.allSettled([ menickoCukrovarka(), menickoGlobus(), menickoMamafoodbistro() ])
.then(results=> results.filter(p=> p.status!=="rejected").map(p=> p.value));
const days= [ "pondělí", "úterý", "středa", "čtvrtek", "pátek", "sobota", "neděle" ];
let out= description+"\n\n";
out+= days.map((v)=> `[${v}](#${v})`).join(" · "); // anchors for days
for(const day of days){ // menicka
out+= `\n\n## ${day}\n`;
out+= menicka.map(dayToMd(day)).join("\n");
}
const gen= [ "<!-- generated -->", "<!-- /generated -->" ];
const target= "README.md";
const readme= s.cat(target);
out= [
readme.slice(0, readme.indexOf(gen[0])-1),
gen[0], out.replace(/(\*)/g, "\\$1"), gen[1],
readme.slice(readme.indexOf("\n", readme.indexOf(gen[1]))+1)
].join("\n");
s.echo(out).to(target);
if(is_git) gitCommit([ target ], "pull");
$.exit(0);
})
.parse();
function dayToMd(day){
return function({ symbol, name, url, dny }){
let has= Reflect.has(dny, day);
if(!has && (day==="sobota" || day==="neděle") && Reflect.has(dny, "víkend")){
has= true;
day= "víkend";
}
const section= `[${symbol} ${name}](${url})`;
if(!has) return `- ${section}: —`;
let out= `- ${section}:`;
const { polevky, hlavni }= dny[day];
const food= f=> out+= `\n - ${f}`;
polevky.forEach(food);
hlavni.forEach(food);
return out;
};
}
function gitCommit(files, des= "not specified"){
if(!files.length || !s.run`git diff --numstat`.trim())
return echo("Nothig todo");
echo("Diff to save");
s.run`git config user.name "Bot"`;
s.run`git config user.email "${"zc.murtnec@naj.elrdna".split("").reverse().join("")}"`;
s.run`git add ${files}`;
s.run`git commit -m "Updated by bot ${des}"`;
s.run`git push`;
s.run`git config --remove-section user`;
}
import { JSDOM, VirtualConsole } from "jsdom";
async function fetchHTML(url){
const res= await fetch(url);
if(res.status !== 200) throw new Error(`Fetch failed with status ${res.status}`);
let text;
if(res.headers.get("Content-Type").includes("charset=windows-1250"))
text= await res.arrayBuffer().then(buff=> new TextDecoder('windows-1250').decode(buff));
else
text= await res.text();
const virtualConsole = new VirtualConsole();
virtualConsole.on("error", () => {
// No-op to skip console errors.
});
return (new JSDOM(text, { virtualConsole })).window;
}
async function menickoMamafoodbistro(){
const url= "https://www.mamafoodbistro.cz/#poledne";
const { document }= await fetchHTML(url);
const menicko= document.querySelectorAll("section")[2].getElementsByClassName("sqs-html-content")[1];
const dny= {};
for(const den of menicko.getElementsByTagName("h4")){
const polevka= den.nextElementSibling;
const hlavni= polevka.nextElementSibling;
Reflect.set(dny, den.textContent.trim().toLowerCase(), {
polevky: [ polevka.textContent ],
hlavni: [ hlavni.textContent ],
});
}
return { name: "MAMAFOOD", symbol: "🍎", url, dny };
}
async function menickoCukrovarka(){
const url= "https://www.menicka.cz/api/iframe/?id=8542&continuous=true";
const { document }= await fetchHTML(url);
const food= el=> el.getElementsByClassName("food")[0].textContent;
const dny= {};
for(const den of document.getElementsByClassName("content")){
let name= den.getElementsByTagName("h2")[0].textContent.trim();
name= name.slice(0, name.indexOf(" ")).toLowerCase();
const [ polevka ]= den.getElementsByClassName("soup");
const hlavni= den.getElementsByClassName("main");
Reflect.set(dny, name, {
polevky: [ food(polevka) ],
hlavni: [ ...hlavni ].map(food),
});
if(name==="neděle") break;
}
return { name: "Jídelna Čakovice", symbol: "🏭", url, dny };
}
async function menickoGlobus(){
const url= "https://www.globus.cz/praha-cakovice/sluzby-a-produkty/restaurace#klasicke-menu";
const { document }= await fetchHTML(url);
const menicko= document.getElementById("klasicke-menu");
const dny= {};
for(const den of menicko.getElementsByTagName("li")){
const name= den.getElementsByTagName("h3")[0].textContent.trim();
const vse= [ ...den.getElementsByTagName("tr") ].map(el=> el.getElementsByTagName("td")[1].textContent.trim());
Reflect.set(dny, name, {
polevky: vse.slice(0, 2),
hlavni: vse.slice(2),
});
}
return { name: "Globus", symbol: "🏪", url, dny };
}