From 5f32f0bb6c7f7bda725e6ec6fd80164a0167dec5 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Tue, 7 Sep 2021 22:55:29 +0100 Subject: [PATCH] Add basic pan support --- src/Config/Config.ts | 5 ++++ src/Connections/GithubUserSpace.ts | 1 - src/GithubBridge.ts | 31 +++++++++++++++++------ src/NotificationsProcessor.ts | 4 +-- src/Stores/MemoryStorageProvider.ts | 4 +-- src/Stores/RedisStorageProvider.ts | 39 ++++++++++++++++++++++++++--- src/Stores/StorageProvider.ts | 4 +-- 7 files changed, 71 insertions(+), 17 deletions(-) diff --git a/src/Config/Config.ts b/src/Config/Config.ts index 4a82cad9..17120dae 100644 --- a/src/Config/Config.ts +++ b/src/Config/Config.ts @@ -51,6 +51,11 @@ interface BridgeConfigBridge { mediaUrl?: string; port: number; bindAddress: string; + pantalaimon?: { + url: string; + username: string; + password: string; + } } interface BridgeConfigWebhook { diff --git a/src/Connections/GithubUserSpace.ts b/src/Connections/GithubUserSpace.ts index afb07e48..2256df4d 100644 --- a/src/Connections/GithubUserSpace.ts +++ b/src/Connections/GithubUserSpace.ts @@ -149,7 +149,6 @@ export class GitHubUserSpace implements IConnection { public async ensureDiscussionInSpace(discussion: GitHubDiscussionSpace) { // TODO: Optimise const children = await this.space.getChildEntities(); - console.log("Foo", children); if (!children[discussion.roomId]) { await this.space.addChildRoom(discussion.roomId); } diff --git a/src/GithubBridge.ts b/src/GithubBridge.ts index e5ad5a8f..97e430e4 100644 --- a/src/GithubBridge.ts +++ b/src/GithubBridge.ts @@ -1,4 +1,4 @@ -import { Appservice, IAppserviceRegistration, RichRepliesPreprocessor, IRichReplyMetadata, StateEvent } from "matrix-bot-sdk"; +import { Appservice, IAppserviceRegistration, RichRepliesPreprocessor, IRichReplyMetadata, StateEvent, PantalaimonClient, MatrixClient } from "matrix-bot-sdk"; import { BridgeConfig, GitLabInstance } from "./Config/Config"; import { OAuthRequest, OAuthTokens, NotificationsEnableEvent, NotificationsDisableEvent,} from "./Webhooks"; import { CommentProcessor } from "./CommentProcessor"; @@ -12,7 +12,7 @@ import { UserNotificationsEvent } from "./Notifications/UserNotificationWatcher" import { RedisStorageProvider } from "./Stores/RedisStorageProvider"; import { MemoryStorageProvider } from "./Stores/MemoryStorageProvider"; import { NotificationProcessor } from "./NotificationsProcessor"; -import { IStorageProvider } from "./Stores/StorageProvider"; +import { IBridgeStorageProvider } from "./Stores/StorageProvider"; import { retry } from "./PromiseUtil"; import { IConnection, GitHubDiscussionSpace, GitHubDiscussionConnection, GitHubUserSpace } from "./Connections"; @@ -35,6 +35,7 @@ const log = new LogWrapper("GithubBridge"); export class GithubBridge { private github?: GithubInstance; private as!: Appservice; + private encryptedMatrixClient?: MatrixClient; private adminRooms: Map = new Map(); private commentProcessor!: CommentProcessor; private notifProcessor!: NotificationProcessor; @@ -215,7 +216,7 @@ export class GithubBridge { await this.github.start(); } - let storage: IStorageProvider; + let storage: IBridgeStorageProvider; if (this.config.queue.host && this.config.queue.port) { log.info(`Initialising Redis storage (on ${this.config.queue.host}:${this.config.queue.port})`); storage = new RedisStorageProvider(this.config.queue.host, this.config.queue.port); @@ -235,6 +236,23 @@ export class GithubBridge { registration: this.registration, storage, }); + if (this.config.bridge.pantalaimon) { + log.info(`Loading pantalaimon client`); + const pan = new PantalaimonClient( + this.config.bridge.pantalaimon.url, + storage, + ); + this.encryptedMatrixClient = await pan.createClientWithCredentials( + this.config.bridge.pantalaimon.username, + this.config.bridge.pantalaimon.password + ); + this.encryptedMatrixClient.on("room.message", async (roomId, event) => { + return this.onRoomMessage(roomId, event); + }); + // TODO: Filter + await this.encryptedMatrixClient.start(); + log.info(`Pan client is syncing`); + } this.widgetApi = new BridgeWidgetApi(this.adminRooms); @@ -558,9 +576,7 @@ export class GithubBridge { // Handle spaces for (const discussion of this.connections.filter((c) => c instanceof GitHubDiscussionSpace) as GitHubDiscussionSpace[]) { - console.log(discussion); const user = this.getConnectionForGithubUser(discussion.owner); - console.log("user:", user); if (user) { await user.ensureDiscussionInSpace(discussion); } @@ -598,8 +614,9 @@ export class GithubBridge { /* We ignore messages from our users */ return; } - log.info(`Got message roomId=${roomId} from=${event.sender}`); - log.debug(event); + log.info(`Got message roomId=${roomId} type=${event.type} from=${event.sender}`); + console.log(event); + log.debug("Content:", JSON.stringify(event)); const adminRoom = this.adminRooms.get(roomId); if (adminRoom) { diff --git a/src/NotificationsProcessor.ts b/src/NotificationsProcessor.ts index f2b0e104..1ca88348 100644 --- a/src/NotificationsProcessor.ts +++ b/src/NotificationsProcessor.ts @@ -1,5 +1,5 @@ import { MessageSenderClient } from "./MatrixSender"; -import { IStorageProvider } from "./Stores/StorageProvider"; +import { IBridgeStorageProvider } from "./Stores/StorageProvider"; import { UserNotificationsEvent } from "./Notifications/UserNotificationWatcher"; import LogWrapper from "./LogWrapper"; import { AdminRoom } from "./AdminRoom"; @@ -106,7 +106,7 @@ export class NotificationProcessor { } } - constructor(private storage: IStorageProvider, private matrixSender: MessageSenderClient) { + constructor(private storage: IBridgeStorageProvider, private matrixSender: MessageSenderClient) { } diff --git a/src/Stores/MemoryStorageProvider.ts b/src/Stores/MemoryStorageProvider.ts index 7b009834..9ea87c64 100644 --- a/src/Stores/MemoryStorageProvider.ts +++ b/src/Stores/MemoryStorageProvider.ts @@ -1,8 +1,8 @@ import { MemoryStorageProvider as MSP } from "matrix-bot-sdk"; -import { IStorageProvider } from "./StorageProvider"; +import { IBridgeStorageProvider } from "./StorageProvider"; import { IssuesGetResponseData } from "../Github/Types"; -export class MemoryStorageProvider extends MSP implements IStorageProvider { +export class MemoryStorageProvider extends MSP implements IBridgeStorageProvider { private issues: Map = new Map(); private issuesLastComment: Map = new Map(); private reviewData: Map = new Map(); diff --git a/src/Stores/RedisStorageProvider.ts b/src/Stores/RedisStorageProvider.ts index 133d0c00..b06495e6 100644 --- a/src/Stores/RedisStorageProvider.ts +++ b/src/Stores/RedisStorageProvider.ts @@ -2,8 +2,12 @@ import { IssuesGetResponseData } from "../Github/Types"; import { Redis, default as redis } from "ioredis"; import LogWrapper from "../LogWrapper"; -import { IStorageProvider } from "./StorageProvider"; +import { IBridgeStorageProvider } from "./StorageProvider"; +import { IFilterInfo } from "matrix-bot-sdk"; +const BOT_SYNC_TOKEN_KEY = "bot.sync_token."; +const BOT_FILTER_KEY = "bot.filter."; +const BOT_VALUE_KEY = "bot.value."; const REGISTERED_USERS_KEY = "as.registered_users"; const COMPLETED_TRANSACTIONS_KEY = "as.completed_transactions"; const GH_ISSUES_KEY = "gh.issues"; @@ -15,16 +19,45 @@ const ISSUES_LAST_COMMENT_EXPIRE_AFTER = 14 * 24 * 60 * 60; // 7 days const log = new LogWrapper("RedisASProvider"); -export class RedisStorageProvider implements IStorageProvider { +export class RedisStorageProvider implements IBridgeStorageProvider { private redis: Redis; - constructor(host: string, port: number) { + constructor(host: string, port: number, private contextSuffix = '') { this.redis = new redis(port, host); this.redis.expire(COMPLETED_TRANSACTIONS_KEY, COMPLETED_TRANSACTIONS_EXPIRE_AFTER).catch((ex) => { log.warn("Failed to set expiry time on as.completed_transactions", ex); }); } + public setSyncToken(token: string|null){ + if (token === null) { + this.redis.del(BOT_SYNC_TOKEN_KEY + this.contextSuffix); + } else { + this.redis.set(BOT_SYNC_TOKEN_KEY + this.contextSuffix, token); + } + } + + public getSyncToken() { + return this.redis.get(BOT_SYNC_TOKEN_KEY + this.contextSuffix); + } + + public setFilter(filter: IFilterInfo) { + this.redis.set(BOT_FILTER_KEY + this.contextSuffix, JSON.stringify(filter)); + } + + public async getFilter() { + const value = await this.redis.get(BOT_FILTER_KEY + this.contextSuffix); + return value && JSON.parse(value); + } + + public storeValue(key: string, value: string) { + this.redis.set(`${BOT_VALUE_KEY}${this.contextSuffix}.${key}`, value); + } + + public readValue(key: string) { + return this.redis.get(`${BOT_VALUE_KEY}${this.contextSuffix}.${key}`); + } + public async addRegisteredUser(userId: string) { this.redis.sadd(REGISTERED_USERS_KEY, [userId]); } diff --git a/src/Stores/StorageProvider.ts b/src/Stores/StorageProvider.ts index 8a77e103..27734222 100644 --- a/src/Stores/StorageProvider.ts +++ b/src/Stores/StorageProvider.ts @@ -1,7 +1,7 @@ -import { IAppserviceStorageProvider } from "matrix-bot-sdk"; +import { IAppserviceStorageProvider, IStorageProvider } from "matrix-bot-sdk"; import { IssuesGetResponseData } from "../Github/Types"; -export interface IStorageProvider extends IAppserviceStorageProvider { +export interface IBridgeStorageProvider extends IAppserviceStorageProvider, IStorageProvider { setGithubIssue(repo: string, issueNumber: string, data: IssuesGetResponseData, scope?: string): Promise; getGithubIssue(repo: string, issueNumber: string, scope?: string): Promise; setLastNotifCommentUrl(repo: string, issueNumber: string, url: string, scope?: string): Promise;