wikijs-metabot/index.js

139 lines
3.5 KiB
JavaScript

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*\\pagelist[^>]*-->\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*\\pagelist\s*/, '')
.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,
`<!-- \\pagelist ${query} -->`,
...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();