Add in date routes
This commit is contained in:
parent
a268086cfd
commit
2378ed72c7
|
@ -1,6 +1,8 @@
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const path = require('path');
|
|
||||||
const fetch = require('node-fetch');
|
const fetch = require('node-fetch');
|
||||||
|
|
||||||
|
const urlJoin = require('./lib/url-join');
|
||||||
|
|
||||||
const { matrixServerUrl } = require('../config.json');
|
const { matrixServerUrl } = require('../config.json');
|
||||||
const secrets = require('../secrets.json');
|
const secrets = require('../secrets.json');
|
||||||
|
|
||||||
|
@ -10,7 +12,7 @@ assert(matrixAccessToken);
|
||||||
class HTTPResponseError extends Error {
|
class HTTPResponseError extends Error {
|
||||||
constructor(response, responseText, ...args) {
|
constructor(response, responseText, ...args) {
|
||||||
super(
|
super(
|
||||||
`HTTP Error Response: ${response.status} ${response.statusText}: ${responseText}\n\tURL=${response.url}`,
|
`HTTP Error Response: ${response.status} ${response.statusText}: ${responseText}\n URL=${response.url}`,
|
||||||
...args
|
...args
|
||||||
);
|
);
|
||||||
this.response = response;
|
this.response = response;
|
||||||
|
@ -40,7 +42,10 @@ async function fetchEndpoint(endpoint) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchEventsForTimestamp(roomId, ts) {
|
async function fetchEventsForTimestamp(roomId, ts) {
|
||||||
const timestampToEventEndpoint = path.join(
|
assert(roomId);
|
||||||
|
assert(ts);
|
||||||
|
|
||||||
|
const timestampToEventEndpoint = urlJoin(
|
||||||
matrixServerUrl,
|
matrixServerUrl,
|
||||||
`_matrix/client/unstable/org.matrix.msc3030/rooms/${roomId}/timestamp_to_event?ts=${ts}&dir=f`
|
`_matrix/client/unstable/org.matrix.msc3030/rooms/${roomId}/timestamp_to_event?ts=${ts}&dir=f`
|
||||||
);
|
);
|
||||||
|
@ -50,14 +55,14 @@ async function fetchEventsForTimestamp(roomId, ts) {
|
||||||
const eventIdForTimestamp = timestampToEventResData.event_id;
|
const eventIdForTimestamp = timestampToEventResData.event_id;
|
||||||
assert(eventIdForTimestamp);
|
assert(eventIdForTimestamp);
|
||||||
|
|
||||||
const contextEndpoint = path.join(
|
const contextEndpoint = urlJoin(
|
||||||
matrixServerUrl,
|
matrixServerUrl,
|
||||||
`_matrix/client/r0/rooms/${roomId}/context/${eventIdForTimestamp}?limit=0`
|
`_matrix/client/r0/rooms/${roomId}/context/${eventIdForTimestamp}?limit=0`
|
||||||
);
|
);
|
||||||
const contextResData = await fetchEndpoint(contextEndpoint);
|
const contextResData = await fetchEndpoint(contextEndpoint);
|
||||||
//console.log('contextResData', contextResData);
|
//console.log('contextResData', contextResData);
|
||||||
|
|
||||||
const messagesEndpoint = path.join(
|
const messagesEndpoint = urlJoin(
|
||||||
matrixServerUrl,
|
matrixServerUrl,
|
||||||
`_matrix/client/r0/rooms/${roomId}/messages?from=${contextResData.start}&limit=50&filter={"lazy_load_members":true,"include_redundant_members":true}`
|
`_matrix/client/r0/rooms/${roomId}/messages?from=${contextResData.start}&limit=50&filter={"lazy_load_members":true,"include_redundant_members":true}`
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
// via https://javascript.plainenglish.io/how-to-safely-concatenate-url-with-node-js-f6527b623d5
|
||||||
|
function urlJoin(baseUrl, ...pathParts) {
|
||||||
|
const fullUrl = new URL(path.join(...pathParts), baseUrl).toString();
|
||||||
|
return fullUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = urlJoin;
|
|
@ -1,9 +1,15 @@
|
||||||
|
const assert = require('assert');
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const asyncHandler = require('./express-async-handler');
|
const asyncHandler = require('./lib/express-async-handler');
|
||||||
|
const urlJoin = require('./lib/url-join');
|
||||||
|
|
||||||
const fetchEventsForTimestamp = require('./fetch-events-for-timestamp');
|
const fetchEventsForTimestamp = require('./fetch-events-for-timestamp');
|
||||||
const renderHydrogenToString = require('./render-hydrogen-to-string');
|
const renderHydrogenToString = require('./render-hydrogen-to-string');
|
||||||
|
|
||||||
|
const config = require('../config.json');
|
||||||
|
const basePath = config.basePath;
|
||||||
|
assert(basePath);
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
app.get('/style.css', async function (req, res) {
|
app.get('/style.css', async function (req, res) {
|
||||||
|
@ -12,20 +18,75 @@ app.get('/style.css', async function (req, res) {
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get(
|
app.get(
|
||||||
'/',
|
'/:roomIdOrAlias/event/:eventId',
|
||||||
asyncHandler(async function (req, res) {
|
asyncHandler(async function (req, res) {
|
||||||
const { events, stateEventMap } = await fetchEventsForTimestamp(
|
res.send('todo');
|
||||||
'!HBehERstyQBxyJDLfR:my.synapse.server',
|
})
|
||||||
new Date('2022-02-08').getTime()
|
);
|
||||||
);
|
|
||||||
|
app.get(
|
||||||
|
'/:roomIdOrAlias/date/:yyyy(\\d{4})/:mm(\\d{2})/:dd(\\d{2})/:hourRange(\\d\\d?-\\d\\d?)?',
|
||||||
|
asyncHandler(async function (req, res) {
|
||||||
|
const roomIdOrAlias = req.params.roomIdOrAlias;
|
||||||
|
assert(roomIdOrAlias.startsWith('!') || roomIdOrAlias.startsWith('#'));
|
||||||
|
|
||||||
|
const yyyy = parseInt(req.params.yyyy, 10);
|
||||||
|
// Month is the only zero-based index in this group
|
||||||
|
const mm = parseInt(req.params.mm, 10) - 1;
|
||||||
|
const dd = parseInt(req.params.dd, 10);
|
||||||
|
|
||||||
|
const hourRange = req.params.hourRange;
|
||||||
|
|
||||||
|
let fromHour = 0;
|
||||||
|
let toHour = 0;
|
||||||
|
if (hourRange) {
|
||||||
|
const hourMatches = hourRange.match(/^(\d\d?)-(\d\d?)$/);
|
||||||
|
|
||||||
|
if (!hourMatches) {
|
||||||
|
throw new StatusError(404, 'Hour was unable to be parsed');
|
||||||
|
}
|
||||||
|
|
||||||
|
fromHour = parseInt(hourMatches[1], 10);
|
||||||
|
toHour = parseInt(hourMatches[2], 10);
|
||||||
|
|
||||||
|
if (Number.isNaN(fromHour) || fromHour < 0 || fromHour > 23) {
|
||||||
|
throw new StatusError(404, 'From hour can only be in range 0-23');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Currently we force the range to always be 1 hour
|
||||||
|
// If the format isn't correct, redirect to the correct hour range
|
||||||
|
if (toHour !== fromHour + 1) {
|
||||||
|
res.redirect(
|
||||||
|
urlJoin(
|
||||||
|
basePath,
|
||||||
|
roomIdOrAlias,
|
||||||
|
'date',
|
||||||
|
req.params.yyyy,
|
||||||
|
req.params.mm,
|
||||||
|
req.params.dd,
|
||||||
|
`${fromHour}-${fromHour + 1}`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fromTimestamp = Date.UTC(yyyy, mm, dd, fromHour);
|
||||||
|
let toTimestamp = Date.UTC(yyyy, mm, dd + 1, fromHour);
|
||||||
|
if (hourRange) {
|
||||||
|
toTimestamp = Date.UTC(yyyy, mm, dd, toHour);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { events, stateEventMap } = await fetchEventsForTimestamp(roomIdOrAlias, fromTimestamp);
|
||||||
|
|
||||||
const hydrogenHtmlOutput = await renderHydrogenToString(events, stateEventMap);
|
const hydrogenHtmlOutput = await renderHydrogenToString(events, stateEventMap);
|
||||||
|
|
||||||
|
const styleUrl = urlJoin(basePath, 'style.css');
|
||||||
const pageHtml = `
|
const pageHtml = `
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<link href="style.css" rel="stylesheet">
|
<link href="${styleUrl}" rel="stylesheet">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
${hydrogenHtmlOutput}
|
${hydrogenHtmlOutput}
|
||||||
|
|
Loading…
Reference in New Issue