Improved layout, added warnings to result page

This commit is contained in:
Lukas Wölfer
2025-05-07 12:18:32 +02:00
parent b88a978606
commit 7cb4319a05
3 changed files with 45 additions and 14 deletions

23
main.ts
View File

@@ -1,7 +1,7 @@
import { Mwn, RecentChange } from 'npm:mwn'
import process, { title } from "node:process";
import { parseSummary } from "./parse.ts";
import { bucketEvents, writeSection } from "./write.ts";
import { bucketEvents, writeSections } from "./write.ts";
async function getWorkshopVideos(bot: Mwn): Promise<string[]> {
const response = await bot.request({
@@ -29,13 +29,20 @@ export interface VideoDescription {
notes: string
path: string
title: string
nags: string[]
}
async function fetchPages(pages: string[], bot: Mwn): Promise<VideoDescription[]> {
const d = await Promise.allSettled(pages.map(async (v) =>
parseSummary(await new bot.Page(v).text(), v)
))
d.map((v, index) => ({ r: v, source: pages[index] })).filter((v): v is { source: string, r: PromiseRejectedResult } => v.r.status === "rejected").forEach(
v => console.warn(`Error parsing ${v.source}: ${v.r.reason}`
))
return d.filter(v => v.status === "fulfilled").map(v => v.value)
}
function sleep(ms: number): Promise<void> {
@@ -45,6 +52,16 @@ function sleep(ms: number): Promise<void> {
async function watchdog(bot: Mwn, onChange: (paths: string[]) => Promise<void>) {
let last_change: string | undefined = undefined;
let heartbeat_count = 0;
const heartbeat_count_max = 60;
const heartbeat = () => {
heartbeat_count += 1
if (heartbeat_count >= heartbeat_count_max) {
heartbeat_count = 0;
console.log(new Date(), "Heartbeat")
}
}
while (true) {
const { last_change: l, new_file_changes } = await queryChanges(bot, last_change);
@@ -53,7 +70,7 @@ async function watchdog(bot: Mwn, onChange: (paths: string[]) => Promise<void>)
console.log(new_file_changes.length, "changes")
await onChange(new_file_changes.map(v => v.title))
}
console.log(new Date(), "Heartbeat")
heartbeat()
await sleep(30000);
}
}
@@ -94,7 +111,7 @@ async function main() {
await watchdog(bot, async (paths) => {
const relevantFiles = await getWorkshopVideos(bot)
const d = await fetchPages(relevantFiles, bot)
const t = writeSection(bucketEvents(d))
const t = writeSections(bucketEvents(d))
const response = await bot.save(title, "{{TOC|limit=3}}\n\n" + t, 'Triggered by changes to ' + paths.map(v => "[[" + v + "]]").join(", "));
console.log(response)
})

View File

@@ -1,21 +1,22 @@
import { Mwn } from "mwn";
import { VideoDescription } from "./main.ts";
function parseTemplate(description: string): Record<string, string> {
function parseTemplate(description: string): { warnings: string[] } & { [k: string]: string } {
const u = new (new Mwn().Wikitext)(description)
const r = u.parseTemplates({
namePredicate: (name) => name === "DanceWorkshopDescription",
})
const warnings = []
if (r.length < 1) {
throw new Error("Could not find DanceWorkshopDescription")
}
if (r.length > 1) {
console.warn("More than one DanceWorkshopDescription template found")
warnings.push("More than one DanceWorkshopDescription template found")
}
const p = r[0]
const properties = p.parameters.map(v => ({ [v.name]: v.value }))
return Object.assign({}, ...properties)
return Object.assign({}, { warnings }, ...properties)
}
function parseBlock(header: string, text: string): string {
@@ -35,9 +36,10 @@ export function parseSummary(description: string, name: string): VideoDescriptio
const properties = parseTemplate(description)
const b: Partial<VideoDescription> = {};
b.nags = properties.warnings
if (Object.hasOwn(properties, 'teachers')) {
console.warn(`Page ${name} has old template usage [contains 'teachers' key]`)
b.nags.push(`Contains 'teachers' key instead of 'leader'/'follower'`)
const t = properties['teachers'].split('&').map(item => item.trim());
b.teachers = t
} else {
@@ -52,15 +54,25 @@ export function parseSummary(description: string, name: string): VideoDescriptio
if (!Object.hasOwn(properties, 'patterns')) {
console.warn(`Page ${name} has old template usage [no 'patterns' key]`)
b.patterns = parseBlock("Shown Patterns", description)
b.nags.push(`No 'patterns' key`)
try {
b.patterns = parseBlock("Shown Patterns", description)
} catch (e) {
b.nags.push("Shown Patterns: " + e)
b.patterns = ""
}
} else {
b.patterns = properties['patterns']
}
if (!Object.hasOwn(properties, 'notes')) {
console.warn(`Page ${name} has old template usage [no 'notes' key]`)
b.notes = parseBlock("Notes", description)
b.nags.push(`No 'notes' key`)
try {
b.notes = parseBlock("Notes", description)
} catch (e) {
b.nags.push("Notes: " + e)
b.notes = ""
}
} else {
b.notes = properties['notes']
}

View File

@@ -3,8 +3,9 @@ import { VideoDescription } from "./main.ts";
export function singleVideoDescription(video: VideoDescription): string {
const teachersList = video.teachers.map(v => "[[" + v + "]]").join(" & ");
const nagElement = video.nags.length > 0 ? `<span title="${video.nags.join("&#010;")}">🔴</span>` : "";
return `=== ${video.title} ===
Date:{{#time: Y-m-d (D) | ${video.date}}}<br>
Date: {{#time: Y-m-d (D) | ${video.date}}} ${nagElement}<br>
Teachers: ${teachersList}<br>
Level: ${video.level}
@@ -21,13 +22,14 @@ ${video.notes}
<br clear=all>`;
}
export function writeSection(events: VideoDescription[][]): string {
export function writeSections(events: VideoDescription[][]): string {
return events.map(v => {
const token = v[0]
const event_name = token.event === token.location ? token.event : token.event + " " + token.location
// FIXME: This will break with videos in 75 years
const event_date = event_name.match(/\d{2}|20\d{2}/) ? "" : new Date(token.date).getFullYear().toString()
const event_contains_year = event_name.match(/\d{2}|20\d{2}/) === null
const event_date = event_contains_year ? "" : new Date(token.date).getFullYear().toString()
let r = `== ${event_name} ${event_date} ==\n`
r += `${v.length} Video${v.length <= 1 ? "" : "s"}\n`