improvements to proposal event forwarding to matrix, and other bot features
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 33s
Details
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 33s
Details
This commit is contained in:
parent
d8df672a80
commit
d3bc08dd24
|
@ -8,4 +8,5 @@ MATRIX_HOMESERVER_URL="https://matrix.dgov.io"
|
|||
MATRIX_USER="forum-api"
|
||||
MATRIX_PASSWORD=
|
||||
BOT_STORAGE_PATH="./data/bot-storage.json"
|
||||
BOT_CRYPTO_STORAGE_PATH="./data/bot-crypto"
|
||||
BOT_CRYPTO_STORAGE_PATH="./data/bot-crypto"
|
||||
BOT_INSTANCE_ID=
|
|
@ -6,4 +6,7 @@ module.exports = {
|
|||
forum: new Level(`${dataDir}/forum`, { valueEncoding: 'json' }),
|
||||
authorAddresses: new Level(`${dataDir}/authorAddresses`, { valueEncoding: 'utf8' }),
|
||||
authorPrivKeys: new Level(`${dataDir}/authorPrivKeys`, { valueEncoding: 'utf8' }),
|
||||
appState: new Level(`${dataDir}/appState`, { valueEncoding: 'json' }),
|
||||
proposalEventIds: new Level(`${dataDir}/proposalEventIds`, { keyEncoding: 'json', valueEncoding: 'utf8' }),
|
||||
referendumEventIds: new Level(`${dataDir}/referendumEventIds`, { keyEncoding: 'json', valueEncoding: 'utf8' }),
|
||||
};
|
||||
|
|
|
@ -6,7 +6,8 @@ const {
|
|||
SimpleFsStorageProvider,
|
||||
} = require('matrix-bot-sdk');
|
||||
const fastq = require('fastq');
|
||||
const Promise = require('bluebird');
|
||||
|
||||
const { appState, proposalEventIds } = require('./db');
|
||||
|
||||
const {
|
||||
MATRIX_HOMESERVER_URL,
|
||||
|
@ -14,18 +15,36 @@ const {
|
|||
MATRIX_PASSWORD,
|
||||
BOT_STORAGE_PATH,
|
||||
BOT_CRYPTO_STORAGE_PATH,
|
||||
BOT_INSTANCE_ID,
|
||||
ETH_NETWORK,
|
||||
} = process.env;
|
||||
|
||||
const storageProvider = new SimpleFsStorageProvider(BOT_STORAGE_PATH);
|
||||
const cryptoProvider = new RustSdkCryptoStorageProvider(BOT_CRYPTO_STORAGE_PATH);
|
||||
let client;
|
||||
let joinedRooms;
|
||||
const processOutboundQueue = async ({ text }) => {
|
||||
console.log('broadcasting', { text });
|
||||
await Promise.each(joinedRooms, async (roomId) => {
|
||||
await client.sendText(roomId, text);
|
||||
});
|
||||
let targetRoomId;
|
||||
|
||||
const processOutboundQueue = async ({ type, ...args }) => {
|
||||
if (!targetRoomId) return;
|
||||
switch (type) {
|
||||
case 'NewProposal': {
|
||||
const { proposalIndex, text } = args;
|
||||
try {
|
||||
await proposalEventIds.get(Number(proposalIndex));
|
||||
} catch (e) {
|
||||
if (e.status === 404) {
|
||||
console.log('sending to room', targetRoomId, { text });
|
||||
const eventId = await client.sendText(targetRoomId, text);
|
||||
await proposalEventIds.put(Number(proposalIndex), eventId);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
}
|
||||
};
|
||||
|
||||
const outboundQueue = fastq(processOutboundQueue, 1);
|
||||
outboundQueue.pause();
|
||||
|
||||
|
@ -46,18 +65,46 @@ const start = async () => {
|
|||
joinedRooms = await client.getJoinedRooms();
|
||||
console.log('joined rooms:', joinedRooms);
|
||||
|
||||
try {
|
||||
targetRoomId = await appState.get('targetRoomId');
|
||||
} catch (e) {
|
||||
// Leave targetRoomId uninitialized for now
|
||||
}
|
||||
|
||||
async function handleCommand(roomId, event) {
|
||||
// Don't handle unhelpful events (ones that aren't text messages, are redacted, or sent by us)
|
||||
if (event.content?.msgtype !== 'm.text') return;
|
||||
if (event.sender === await client.getUserId()) return;
|
||||
|
||||
// Check to ensure that the `!hello` command is being run
|
||||
const { body } = event.content;
|
||||
if (!body?.startsWith('!hello')) return;
|
||||
const helloRegex = /^!hello\b/i;
|
||||
const targetRegex = /^!target (.*)\b/i;
|
||||
const proposalRegex = /\bprop(|osal) ([0-9]+)\b/i;
|
||||
|
||||
// Now that we've passed all the checks, we can actually act upon the command
|
||||
console.log(`!hello roomId ${roomId}`);
|
||||
await client.replyNotice(roomId, event, 'Hello world!');
|
||||
const { body } = event.content;
|
||||
|
||||
if (helloRegex.test(body)) {
|
||||
console.log(`!hello roomId ${roomId}`);
|
||||
await client.replyNotice(roomId, event, 'Hello world!');
|
||||
} else if (targetRegex.test(body)) {
|
||||
const [, instanceId] = targetRegex.exec(body);
|
||||
console.log(`!target roomId ${roomId} instanceId ${instanceId}`);
|
||||
if (instanceId === BOT_INSTANCE_ID) {
|
||||
targetRoomId = roomId;
|
||||
await appState.put('targetRoomId', targetRoomId);
|
||||
await client.replyNotice(roomId, event, `Proposal events will be sent to this room for network ${ETH_NETWORK}`);
|
||||
}
|
||||
} else if (proposalRegex.test(body)) {
|
||||
const [, , proposalIndexStr] = proposalRegex.exec(body);
|
||||
const proposalIndex = parseInt(proposalIndexStr, 10);
|
||||
console.log(`mention of proposal ${proposalIndex} in roomId ${roomId}`);
|
||||
try {
|
||||
const proposalEventId = await proposalEventIds.get(proposalIndex);
|
||||
const proposalEventUri = `https://matrix.to/#/${roomId}/${proposalEventId}`;
|
||||
await client.sendText(roomId, `Proposal ${proposalIndex}: ${proposalEventUri}`);
|
||||
} catch (e) {
|
||||
// Not found
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Before we start the bot, register our command handler
|
||||
|
@ -69,11 +116,11 @@ const start = async () => {
|
|||
});
|
||||
};
|
||||
|
||||
const broadcastMessage = (text) => {
|
||||
outboundQueue.push({ text });
|
||||
const sendNewProposalEvent = (proposalIndex, text) => {
|
||||
outboundQueue.push({ type: 'NewProposal', proposalIndex, text });
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
start,
|
||||
broadcastMessage,
|
||||
sendNewProposalEvent,
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
const { proposals } = require('./contracts');
|
||||
const read = require('./read');
|
||||
const { broadcastMessage } = require('./matrix');
|
||||
const { sendNewProposalEvent } = require('./matrix');
|
||||
|
||||
// Subscribe to proposal events
|
||||
const start = () => {
|
||||
|
@ -20,7 +20,7 @@ const start = () => {
|
|||
if (post.embeddedData && Object.entries(post.embeddedData).length) {
|
||||
message += `\n\n${JSON.stringify(post.embeddedData, null, 2)}`;
|
||||
}
|
||||
broadcastMessage(message);
|
||||
sendNewProposalEvent(proposalIndex, message);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue