diff --git a/.eslintrc.js b/.eslintrc.js index 72a32ef3..63af3380 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,4 +1,3 @@ -// eslint-disable-next-line no-undef module.exports = { root: true, parser: '@typescript-eslint/parser', diff --git a/src/App/BridgeApp.ts b/src/App/BridgeApp.ts index 94eb6811..451d6ca1 100644 --- a/src/App/BridgeApp.ts +++ b/src/App/BridgeApp.ts @@ -5,7 +5,6 @@ import { BridgeConfig, parseRegistrationFile } from "../Config/Config"; import { Webhooks } from "../Webhooks"; import { MatrixSender } from "../MatrixSender"; import { UserNotificationWatcher } from "../Notifications/UserNotificationWatcher"; - LogWrapper.configureLogging("debug"); const log = new LogWrapper("App"); diff --git a/src/ConnectionManager.ts b/src/ConnectionManager.ts index be01b4ed..ac8b9cd7 100644 --- a/src/ConnectionManager.ts +++ b/src/ConnectionManager.ts @@ -156,11 +156,11 @@ export class ConnectionManager { return connections; } - public getConnectionsForGithubIssue(org: string, repo: string, issueNumber: number): (GitHubIssueConnection|GitLabRepoConnection)[] { + public getConnectionsForGithubIssue(org: string, repo: string, issueNumber: number): (GitHubIssueConnection|GitHubRepoConnection)[] { org = org.toLowerCase(); repo = repo.toLowerCase(); return this.connections.filter((c) => (c instanceof GitHubIssueConnection && c.org === org && c.repo === repo && c.issueNumber === issueNumber) || - (c instanceof GitHubRepoConnection && c.org === org && c.repo === repo)) as (GitHubIssueConnection|GitLabRepoConnection)[]; + (c instanceof GitHubRepoConnection && c.org === org && c.repo === repo)) as (GitHubIssueConnection|GitHubRepoConnection)[]; } public getConnectionsForGithubRepo(org: string, repo: string): GitHubRepoConnection[] { diff --git a/src/Connections/GithubRepo.ts b/src/Connections/GithubRepo.ts index c7ef19b9..2e414c31 100644 --- a/src/Connections/GithubRepo.ts +++ b/src/Connections/GithubRepo.ts @@ -1,20 +1,20 @@ /* eslint-disable @typescript-eslint/ban-ts-comment */ -import { IConnection } from "./IConnection"; import { Appservice } from "matrix-bot-sdk"; -import { MatrixMessageContent, MatrixEvent, MatrixReactionContent } from "../MatrixEvent"; -import markdown from "markdown-it"; -import { UserTokenStore } from "../UserTokenStore"; -import LogWrapper from "../LogWrapper"; -import { CommentProcessor } from "../CommentProcessor"; -import { Octokit } from "@octokit/rest"; -import { MessageSenderClient } from "../MatrixSender"; -import { FormatUtil } from "../FormatUtil"; -import axios from "axios"; import { BotCommands, handleCommand, botCommand, compileBotCommands } from "../BotCommands"; -import { ReposGetResponseData } from "../Github/Types"; -import { IssuesOpenedEvent, IssuesEditedEvent, PullRequestOpenedEvent, PullRequestClosedEvent, PullRequestReadyForReviewEvent, PullRequestReviewSubmittedEvent, ReleaseCreatedEvent } from "@octokit/webhooks-types"; -import emoji from "node-emoji"; +import { CommentProcessor } from "../CommentProcessor"; +import { FormatUtil } from "../FormatUtil"; +import { IConnection } from "./IConnection"; +import { IssuesOpenedEvent, IssuesReopenedEvent, IssuesEditedEvent, PullRequestOpenedEvent, IssuesClosedEvent, PullRequestClosedEvent, PullRequestReadyForReviewEvent, PullRequestReviewSubmittedEvent, ReleaseCreatedEvent } from "@octokit/webhooks-types"; +import { MatrixMessageContent, MatrixEvent, MatrixReactionContent } from "../MatrixEvent"; +import { MessageSenderClient } from "../MatrixSender"; import { NotLoggedInError } from "../errors"; +import { Octokit } from "@octokit/rest"; +import { ReposGetResponseData } from "../Github/Types"; +import { UserTokenStore } from "../UserTokenStore"; +import axios from "axios"; +import emoji from "node-emoji"; +import LogWrapper from "../LogWrapper"; +import markdown from "markdown-it"; const log = new LogWrapper("GitHubRepoConnection"); const md = new markdown(); @@ -300,7 +300,7 @@ export class GitHubRepoConnection implements IConnection { }); } - public async onIssueStateChange(event: IssuesEditedEvent) { + public async onIssueStateChange(event: IssuesEditedEvent|IssuesReopenedEvent|IssuesClosedEvent) { if (this.shouldSkipHook('issue.changed', 'issue')) { return; } diff --git a/src/GithubBridge.ts b/src/GithubBridge.ts index ef5a0ccc..ac7ab74f 100644 --- a/src/GithubBridge.ts +++ b/src/GithubBridge.ts @@ -31,31 +31,51 @@ import LogWrapper from "./LogWrapper"; const log = new LogWrapper("GithubBridge"); export class GithubBridge { + private readonly as: Appservice; + private readonly storage: IBridgeStorageProvider; + private readonly messageClient: MessageSenderClient; + private readonly queue: MessageQueue; + private readonly commentProcessor: CommentProcessor; + private readonly notifProcessor: NotificationProcessor; + private readonly tokenStore: UserTokenStore; private connectionManager?: ConnectionManager; private github?: GithubInstance; - private as!: Appservice; private encryptedMatrixClient?: MatrixClient; private adminRooms: Map = new Map(); - private commentProcessor!: CommentProcessor; - private notifProcessor!: NotificationProcessor; - private queue!: MessageQueue; - private tokenStore!: UserTokenStore; - private messageClient!: MessageSenderClient; - private widgetApi!: BridgeWidgetApi; + private widgetApi: BridgeWidgetApi = new BridgeWidgetApi(this.adminRooms); private ready = false; - constructor(private config: BridgeConfig, private registration: IAppserviceRegistration) { } + constructor(private config: BridgeConfig, private registration: IAppserviceRegistration) { + if (this.config.queue.host && this.config.queue.port) { + log.info(`Initialising Redis storage (on ${this.config.queue.host}:${this.config.queue.port})`); + this.storage = new RedisStorageProvider(this.config.queue.host, this.config.queue.port); + } else { + log.info('Initialising memory storage'); + this.storage = new MemoryStorageProvider(); + } + this.as = new Appservice({ + homeserverName: this.config.bridge.domain, + homeserverUrl: this.config.bridge.url, + port: this.config.bridge.port, + bindAddress: this.config.bridge.bindAddress, + registration: this.registration, + storage: this.storage, + }); + this.queue = createMessageQueue(this.config); + this.messageClient = new MessageSenderClient(this.queue); + this.commentProcessor = new CommentProcessor(this.as, this.config.bridge.mediaUrl || this.config.bridge.url); + this.notifProcessor = new NotificationProcessor(this.storage, this.messageClient); + this.tokenStore = new UserTokenStore(this.config.passFile || "./passkey.pem", this.as.botIntent); + } public stop() { this.as.stop(); - if(this.queue.stop) this.queue.stop(); + if (this.queue.stop) this.queue.stop(); } public async start() { log.info('Starting up'); - this.queue = createMessageQueue(this.config); - this.messageClient = new MessageSenderClient(this.queue); if (!this.config.github && !this.config.gitlab) { log.error("You haven't configured support for GitHub or GitLab!"); @@ -67,27 +87,6 @@ export class GithubBridge { await this.github.start(); } - 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); - } else { - log.info('Initialising memory storage'); - storage = new MemoryStorageProvider(); - } - - - this.notifProcessor = new NotificationProcessor(storage, this.messageClient); - - this.as = new Appservice({ - homeserverName: this.config.bridge.domain, - homeserverUrl: this.config.bridge.url, - port: this.config.bridge.port, - bindAddress: this.config.bridge.bindAddress, - registration: this.registration, - storage, - }); - this.as.expressAppInstance.get("/live", (_, res) => res.send({ok: true})); this.as.expressAppInstance.get("/ready", (_, res) => res.status(this.ready ? 200 : 500).send({ready: this.ready})); @@ -95,7 +94,7 @@ export class GithubBridge { log.info(`Loading pantalaimon client`); const pan = new PantalaimonClient( this.config.bridge.pantalaimon.url, - storage, + this.storage, ); this.encryptedMatrixClient = await pan.createClientWithCredentials( this.config.bridge.pantalaimon.username, @@ -109,11 +108,7 @@ export class GithubBridge { log.info(`Pan client is syncing`); } - this.widgetApi = new BridgeWidgetApi(this.adminRooms); - this.commentProcessor = new CommentProcessor(this.as, this.config.bridge.mediaUrl || this.config.bridge.url); - - this.tokenStore = new UserTokenStore(this.config.passFile || "./passkey.pem", this.as.botIntent); await this.tokenStore.load(); const connManager = this.connectionManager = new ConnectionManager(this.as, this.config, this.tokenStore, this.commentProcessor, this.messageClient, this.github); @@ -219,8 +214,9 @@ export class GithubBridge { const connections = connManager.getConnectionsForGithubIssue(owner, repository.name, issue.number); connections.map(async (c) => { try { - if (c instanceof GitHubIssueConnection || c instanceof GitHubRepoConnection) + if (c.onIssueStateChange) { await c.onIssueStateChange(data); + } } catch (ex) { log.warn(`Connection ${c.toString()} failed to handle github.issues.reopened:`, ex); } @@ -228,7 +224,7 @@ export class GithubBridge { }); this.queue.on("github.issues.edited", async ({ data }) => { - const { repository, issue, owner } = validateRepoIssue(data); + const { repository, owner } = validateRepoIssue(data); const connections = connManager.getConnectionsForGithubRepo(owner, repository.name); connections.map(async (c) => { try { diff --git a/tests/MessageQueueTest.ts b/tests/MessageQueueTest.ts index 9bf8e53c..d16ae901 100644 --- a/tests/MessageQueueTest.ts +++ b/tests/MessageQueueTest.ts @@ -5,7 +5,6 @@ const mq = createMessageQueue({ queue: { monolithic: true, }, -// tslint:disable-next-line: no-any } as any); describe("MessageQueueTest", () => {