fix and improve matrix layer

This commit is contained in:
hippoz 2023-03-17 22:46:49 +02:00
parent afb046b3b6
commit 5a5588f1e3
Signed by: hippoz
GPG key ID: 56C4E02A85F2FBED

View file

@ -12,6 +12,9 @@ const router = express.Router();
router.use(cors()); router.use(cors());
const isInt = (val: any) => typeof val === "number" && Number.isSafeInteger(val);
const isUint = (val: any) => (isInt(val) && val >= 0);
const matrixProtocol = process.env.MATRIX_PROTOCOL ? process.env.MATRIX_PROTOCOL : "http"; const matrixProtocol = process.env.MATRIX_PROTOCOL ? process.env.MATRIX_PROTOCOL : "http";
const matrixHomeserverBaseUrl = process.env.MATRIX_HOMESERVER_BASE_URL ? process.env.MATRIX_HOMESERVER_BASE_URL : "localhost:3000"; const matrixHomeserverBaseUrl = process.env.MATRIX_HOMESERVER_BASE_URL ? process.env.MATRIX_HOMESERVER_BASE_URL : "localhost:3000";
const matrixWaffleAppUrl = process.env.MATRIX_WAFFLE_APP_URL ? process.env.MATRIX_WAFFLE_APP_URL : "localhost:3000"; const matrixWaffleAppUrl = process.env.MATRIX_WAFFLE_APP_URL ? process.env.MATRIX_WAFFLE_APP_URL : "localhost:3000";
@ -47,22 +50,60 @@ const matrixUserProfile = (matrixUserId: string) => {
}; };
}; };
const cursorType = "waffletrackv1";
interface MatrixSyncCursors { interface MatrixSyncCursors {
[channel_id: number]: number; type: string,
chan: {[channel_id: number]: number};
}; };
async function buildSyncPayload(user: User, cursors: MatrixSyncCursors, onlyOutstandingEvents: boolean, client: PoolClient, channels: Channel[]) { function parseCursor(cursor: string | null): MatrixSyncCursors | null {
if (!cursor) {
return null;
}
let json;
try {
json = JSON.parse(cursor);
} catch(O_o) {
return null;
}
if (json.type !== "waffletrackv1") {
return null;
}
if (typeof json.chan !== "object") {
return null;
}
for (const [key, value] of Object.entries(json.chan)) {
if (!isUint(parseInt(key)) || !isUint(value)) {
return null;
}
}
return json;
}
function cursorNew(): MatrixSyncCursors {
return {
type: cursorType,
chan: {}
}
}
async function buildSyncPayload(user: User, cursors: MatrixSyncCursors, onlyOutstandingEvents: boolean, channels: Channel[]) {
const joinedChannels: any[any] = {}; const joinedChannels: any[any] = {};
let nextBatchCursors = ""; const nextBatchCursors = cursorNew();
for (let i = 0; i < channels.length; i++) { for (let i = 0; i < channels.length; i++) {
const channel = channels[i]; const channel = channels[i];
const roomId = `!${channel.id}:${matrixHomeserverBaseUrl}`; const roomId = `!${channel.id}:${matrixHomeserverBaseUrl}`;
let channelMessagesResult; let channelMessagesResult;
if (cursors[channel.id]) { if (cursors.chan[channel.id]) {
channelMessagesResult = await client.query(getMessagesByChannelAfterPage(50), [cursors[channel.id], channel.id]); channelMessagesResult = await query(getMessagesByChannelAfterPage(50), [cursors.chan[channel.id], channel.id]);
} else { } else {
channelMessagesResult = await client.query(getMessagesByChannelFirstPage(50), [channel.id]); channelMessagesResult = await query(getMessagesByChannelFirstPage(50), [channel.id]);
} }
const messages = channelMessagesResult && channelMessagesResult.rows ? channelMessagesResult.rows.reverse() : []; const messages = channelMessagesResult && channelMessagesResult.rows ? channelMessagesResult.rows.reverse() : [];
const messagesTimeline = messages.map(e => ({ const messagesTimeline = messages.map(e => ({
@ -78,9 +119,9 @@ async function buildSyncPayload(user: User, cursors: MatrixSyncCursors, onlyOuts
})); }));
if (messages.length > 0) { if (messages.length > 0) {
nextBatchCursors += `${channel.id}:${messages[messages.length - 1].id};`; nextBatchCursors.chan[channel.id] = messages[messages.length - 1].id;
} else if (cursors[channel.id]) { } else if (cursors.chan[channel.id]) {
nextBatchCursors += `${channel.id}:${cursors[channel.id]};`; nextBatchCursors.chan[channel.id] = cursors.chan[channel.id];
} }
if (messages.length < 1 && onlyOutstandingEvents) { if (messages.length < 1 && onlyOutstandingEvents) {
@ -139,7 +180,7 @@ async function buildSyncPayload(user: User, cursors: MatrixSyncCursors, onlyOuts
} }
return { return {
next_batch: nextBatchCursors, next_batch: JSON.stringify(nextBatchCursors),
rooms: { rooms: {
invite: {}, invite: {},
join: joinedChannels, join: joinedChannels,
@ -335,46 +376,16 @@ router.get(
isInitial = false; isInitial = false;
} }
await withClient((client: PoolClient) => { const channelsResult = await query("SELECT id, name, owner_id FROM channels");
return new Promise(async (resolve, reject) => {
const channelsResult = await client.query("SELECT id, name, owner_id FROM channels");
if (!channelsResult) return; if (!channelsResult) return;
const channels = channelsResult.rows || []; const channels = channelsResult.rows;
const sendPayload = async () => {
const cursors: MatrixSyncCursors = {};
if (since) {
const sinceParts = since.split(";");
if (sinceParts.length < 100) {
sinceParts.forEach((part) => {
const def = part.split(":");
if (def.length !== 2) return;
const channelId = parseInt(def[0]);
const page = parseInt(def[1]);
if (!isNaN(channelId) && isFinite(channelId) && !isNaN(page) && isFinite(page)) {
cursors[channelId] = page;
}
});
}
}
res.json(await buildSyncPayload({
id: 3,
username: "test",
is_superuser: true,
avatar: null
}, cursors, !isInitial, client, channels));
};
if (timeout) { if (timeout) {
let dispatchChannels = ["*"]; const dispatchChannels = channels.map(channel => `channel:${channel.id}`);
channels.forEach(channel => dispatchChannels.push(`channel:${channel.id}`)); dispatchChannels.push("*");
await waitForEvent(dispatchChannels, timeout); await waitForEvent(dispatchChannels, timeout);
} }
await sendPayload(); res.json(await buildSyncPayload(req.publicUser, parseCursor(since) ?? cursorNew(), !isInitial, channels));
resolve(true);
});
});
} }
); );