import WebSocket from 'ws'; process.on('SIGINT', () => process.exit(0)); const apiKey = process.env['CTDO_WIKIJS_API_KEY']; async function graphql(query) { const res = await fetch('https://wiki.ctdo.de/graphql', { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${apiKey}`, }, body: JSON.stringify({ query }), }); return await res.json(); } function graphqlSubscribe(query, callback) { const ws = new WebSocket( 'wss://wiki.ctdo.de/graphql-subscriptions', 'graphql-ws' ); ws.onmessage = (event) => callback(JSON.parse(event.data)); ws.onopen = () => { ws.send(JSON.stringify({ type: 'connection_init' })); ws.send( JSON.stringify({ id: '1', type: 'start', payload: { query: `subscription ${query}` }, }) ); }; } async function update() { const pageIds = ( await graphql('query { pages { list(tags: ["metapage"]) { id } } }') ).data.pages.list.map((page) => page.id); console.log('checking metapages', { pageIds }); pageIds.forEach((pageId) => updatePage(pageId)); } async function updatePage(pageId) { console.log('checking page', { pageId }); const page = ( await graphql(`query { pages { single(id: ${pageId}) { id content description editor isPrivate isPublished locale path publishEndDate publishStartDate scriptCss scriptJs tags { tag } title } } }`) ).data.pages.single; page.tags = page.tags.map((tag) => tag.tag); let contentLines = page.content.split('\n'); const pagelistConfigs = contentLines.filter((line) => line.match(/^\s*\s*$/) ); for (const pagelistConfig of pagelistConfigs) { await updatePagelist(pagelistConfig, contentLines); } const updatedContent = contentLines.join('\n'); if (page.content !== updatedContent) { page.content = updatedContent; console.log('updating page'); console.log({ page }); const mutation = Object.entries(page) .map(([key, value]) => `${key}: ${JSON.stringify(value)}`) .join(', '); const result = await graphql( `mutation { pages { update(${mutation}) { responseResult { succeeded, message, errorCode } } } }` ); console.log({ result: JSON.stringify(result) }); } } async function updatePagelist(pagelistConfig, contentLines) { const query = pagelistConfig .replace(/^\s*\s*$/, ''); const result = ( await graphql(`query { pages { list(${query}) { path, title, tags } }}`) ).data.pages.list .filter((page) => !page.path.includes('/_')) .filter((page) => !page.tags.includes('metapage')) .map((page) => `- [${page.title}](/${page.path})`); console.log({ pagelistConfig, query, result }); const startIndex = contentLines.findIndex((line) => line == pagelistConfig); let endIndex = startIndex + 1; while ( endIndex < contentLines.length && contentLines[endIndex].startsWith('- ') ) { endIndex++; } contentLines.splice( startIndex, endIndex - startIndex, ``, ...result ); } async function main() { await update(); graphqlSubscribe('{ loggingLiveTrail { output } }', async (message) => { if ( message.type === 'data' && message.payload.data.loggingLiveTrail.output.includes( 'Committing updated file' ) ) { await update(); } }); } main();