mirror of
https://github.com/matrix-org/matrix-hookshot.git
synced 2025-03-10 13:17:08 +00:00
Update dependencies
This commit is contained in:
parent
94c6c65ed2
commit
745f628e7a
61
package.json
61
package.json
@ -22,53 +22,52 @@
|
||||
"generate-default-config": "node lib/Config/Defaults.js > config.sample.yml"
|
||||
},
|
||||
"dependencies": {
|
||||
"@octokit/auth-app": "2.10.2",
|
||||
"@octokit/auth-token": "^2.4.4",
|
||||
"@octokit/rest": "18.0.9",
|
||||
"@octokit/auth-app": "^3.3.0",
|
||||
"@octokit/auth-token": "^2.4.5",
|
||||
"@octokit/rest": "^18.5.2",
|
||||
"axios": "^0.21.1",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.17.1",
|
||||
"fontsource-open-sans": "^3.1.5",
|
||||
"ioredis": "^4.19.2",
|
||||
"markdown-it": "^12.0.2",
|
||||
"matrix-bot-sdk": "^0.5.8",
|
||||
"matrix-widget-api": "^0.1.0-beta.10",
|
||||
"micromatch": "^4.0.2",
|
||||
"mime": "^2.4.6",
|
||||
"mini.css": "^3.0.1",
|
||||
"ioredis": "^4.26.0",
|
||||
"markdown-it": "^12.0.4",
|
||||
"matrix-bot-sdk": "^0.5.17",
|
||||
"matrix-widget-api": "^0.1.0-beta.13",
|
||||
"micromatch": "^4.0.4",
|
||||
"mime": "^2.5.2",
|
||||
"mocha": "^8.2.1",
|
||||
"node-emoji": "^1.10.0",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"source-map-support": "^0.5.19",
|
||||
"string-argv": "v0.3.1",
|
||||
"uuid": "^8.3.1",
|
||||
"string-argv": "^0.3.1",
|
||||
"uuid": "^8.3.2",
|
||||
"winston": "^3.3.3",
|
||||
"yaml": "^2.0.0-1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@prefresh/snowpack": "^2.2.0",
|
||||
"@snowpack/plugin-typescript": "^1.1.1",
|
||||
"@types/chai": "^4.2.14",
|
||||
"@types/cors": "^2.8.9",
|
||||
"@types/express": "^4.17.9",
|
||||
"@types/ioredis": "^4.17.8",
|
||||
"@types/markdown-it": "^10.0.3",
|
||||
"@prefresh/snowpack": "^3.1.2",
|
||||
"@snowpack/plugin-typescript": "^1.2.1",
|
||||
"@fontsource/open-sans": "^4.2.2",
|
||||
"@types/chai": "^4.2.16",
|
||||
"@types/cors": "^2.8.10",
|
||||
"@types/express": "^4.17.11",
|
||||
"@types/ioredis": "^4.22.3",
|
||||
"@types/markdown-it": "^12.0.1",
|
||||
"@types/micromatch": "^4.0.1",
|
||||
"@types/mime": "^2.0.3",
|
||||
"@types/mocha": "^8.0.4",
|
||||
"@types/mocha": "^8.2.2",
|
||||
"@types/node": "^12",
|
||||
"@types/node-emoji": "^1.8.1",
|
||||
"@types/uuid": "^8.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.8.1",
|
||||
"@typescript-eslint/parser": "^4.8.1",
|
||||
"autoprefixer": "^10.1.0",
|
||||
"chai": "^4.2.0",
|
||||
"eslint": "^7.14.0",
|
||||
"eslint-plugin-mocha": "^8.0.0",
|
||||
"preact": "^10.5.7",
|
||||
"snowpack": "^2.18.3",
|
||||
"@typescript-eslint/eslint-plugin": "^4.21.0",
|
||||
"@typescript-eslint/parser": "^4.21.0",
|
||||
"chai": "^4.3.4",
|
||||
"eslint": "^7.24.0",
|
||||
"eslint-plugin-mocha": "^8.1.0",
|
||||
"preact": "^10.5.13",
|
||||
"mini.css": "^3.0.1",
|
||||
"snowpack": "^3.2.2",
|
||||
"tailwind": "^4.0.0",
|
||||
"ts-node": "^9.0.0",
|
||||
"typescript": "^4.1.2"
|
||||
"ts-node": "^9.1.1",
|
||||
"typescript": "^4.2.4"
|
||||
}
|
||||
}
|
||||
|
@ -7,25 +7,12 @@ module.exports = {
|
||||
'@prefresh/snowpack',
|
||||
['@snowpack/plugin-typescript', '--project tsconfig.web.json'],
|
||||
],
|
||||
install: [
|
||||
/* ... */
|
||||
],
|
||||
installOptions: {
|
||||
packageOptions: {
|
||||
installTypes: true,
|
||||
polyfillNode: true,
|
||||
},
|
||||
devOptions: {
|
||||
/* ... */
|
||||
},
|
||||
buildOptions: {
|
||||
out: 'public'
|
||||
/* ... */
|
||||
},
|
||||
proxy: {
|
||||
/* ... */
|
||||
},
|
||||
alias: {
|
||||
/* ... */
|
||||
},
|
||||
};
|
||||
|
@ -14,8 +14,12 @@ import { GitLabClient } from "./Gitlab/Client";
|
||||
import { GetUserResponse } from "./Gitlab/Types";
|
||||
import { GithubInstance } from "./Github/GithubInstance";
|
||||
import { MatrixMessageContent } from "./MatrixEvent";
|
||||
import { ProjectsListForUserResponseData, ProjectsListForRepoResponseData } from "@octokit/types";
|
||||
import { BridgeRoomState, BridgeRoomStateGitHub } from "./Widgets/BridgeWidgetInterface";
|
||||
import { Endpoints } from "@octokit/types";
|
||||
import { ProjectsListResponseData } from "./Github/Types";
|
||||
|
||||
type ProjectsListForRepoResponseData = Endpoints["GET /repos/{owner}/{repo}/projects"]["response"];
|
||||
type ProjectsListForUserResponseData = Endpoints["GET /users/{username}/projects"]["response"];
|
||||
|
||||
|
||||
const md = new markdown();
|
||||
@ -240,10 +244,11 @@ export class AdminRoom extends EventEmitter {
|
||||
|
||||
if (!username) {
|
||||
const me = await octokit.users.getAuthenticated();
|
||||
username = me.data.name;
|
||||
// TODO: Fix
|
||||
username = me.data.name!;
|
||||
}
|
||||
|
||||
let res: ProjectsListForUserResponseData|ProjectsListForRepoResponseData;
|
||||
let res: ProjectsListResponseData;
|
||||
try {
|
||||
if (repo) {
|
||||
res = (await octokit.projects.listForRepo({
|
||||
@ -259,7 +264,7 @@ export class AdminRoom extends EventEmitter {
|
||||
return this.sendNotice(`Failed to fetch projects due to an error. See logs for details`);
|
||||
}
|
||||
|
||||
const content = `Projects for ${username}:\n` + res.map(r => ` - ${FormatUtil.projectListing([r])}\n`).join("\n");
|
||||
const content = `Projects for ${username}:\n${FormatUtil.projectListing(res)}\n`;
|
||||
return this.botIntent.sendEvent(this.roomId,{
|
||||
msgtype: "m.notice",
|
||||
body: content,
|
||||
@ -285,11 +290,11 @@ export class AdminRoom extends EventEmitter {
|
||||
res = (await octokit.projects.listForRepo({
|
||||
repo,
|
||||
owner: org,
|
||||
})).data;
|
||||
}));
|
||||
}
|
||||
res = (await octokit.projects.listForOrg({
|
||||
org,
|
||||
})).data;
|
||||
}));
|
||||
} catch (ex) {
|
||||
if (ex.status === 404) {
|
||||
return this.sendNotice('Not found');
|
||||
@ -298,7 +303,7 @@ export class AdminRoom extends EventEmitter {
|
||||
return this.sendNotice(`Failed to fetch projects due to an error. See logs for details`);
|
||||
}
|
||||
|
||||
const content = `Projects for ${org}:\n` + res.map(r => ` - ${FormatUtil.projectListing([r])}\n`).join("\n");
|
||||
const content = `Projects for ${org}:\n` + res.data.map(r => ` - ${FormatUtil.projectListing([r])}\n`).join("\n");
|
||||
return this.botIntent.sendEvent(this.roomId,{
|
||||
msgtype: "m.notice",
|
||||
body: content,
|
||||
|
@ -6,7 +6,7 @@ import { MatrixMessageContent, MatrixEvent } from "./MatrixEvent";
|
||||
import LogWrapper from "./LogWrapper";
|
||||
import axios from "axios";
|
||||
import { FormatUtil } from "./FormatUtil";
|
||||
import { IssuesGetCommentResponseData, ReposGetResponseData, IssuesGetResponseData } from "@octokit/types";
|
||||
import { IssuesGetCommentResponseData, ReposGetResponseData, IssuesGetResponseData } from "./Github/Types"
|
||||
import { IGitLabWebhookNoteEvent } from "./Gitlab/WebhookTypes";
|
||||
|
||||
const REGEX_MENTION = /(^|\s)(@[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38})(\s|$)/ig;
|
||||
@ -59,7 +59,10 @@ export class CommentProcessor {
|
||||
|
||||
public async getEventBodyForGitHubComment(comment: IssuesGetCommentResponseData,
|
||||
repo?: ReposGetResponseData,
|
||||
issue?: IssuesGetResponseData): Promise<IMatrixCommentEvent> {
|
||||
issue?: IssuesGetResponseData): Promise<IMatrixCommentEvent|undefined> {
|
||||
if (!comment.body) {
|
||||
return undefined;
|
||||
}
|
||||
let body = comment.body;
|
||||
body = this.replaceMentions(body);
|
||||
body = await this.replaceImages(body, true);
|
||||
|
@ -6,6 +6,7 @@ export function configKey(comment?: string, optional = false) {
|
||||
return Reflect.metadata(configKeyMetadataKey, [comment, optional]);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function getConfigKeyMetadata(target: any, propertyKey: string): [string, boolean] {
|
||||
return Reflect.getMetadata(configKeyMetadataKey, target, propertyKey);
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
import { BridgeConfig } from "./Config";
|
||||
import YAML from "yaml";
|
||||
import { getConfigKeyMetadata } from "./Decorators";
|
||||
import { Node, YAMLSeq } from "yaml/types";
|
||||
import { Node, YAMLSeq, Document, stringify } from "yaml";
|
||||
import { randomBytes } from "crypto";
|
||||
|
||||
const DefaultConfig = new BridgeConfig({
|
||||
@ -61,13 +60,13 @@ const DefaultConfig = new BridgeConfig({
|
||||
}
|
||||
}, {});
|
||||
|
||||
function renderSection(doc: YAML.Document, obj: Record<string, unknown>, parentNode?: YAMLSeq) {
|
||||
function renderSection(doc: Document, obj: Record<string, unknown>, parentNode?: YAMLSeq) {
|
||||
const entries = Object.entries(obj);
|
||||
entries.forEach(([key, value]) => {
|
||||
let newNode: Node;
|
||||
if (typeof value === "object") {
|
||||
if (typeof value === "object" && !Array.isArray(value)) {
|
||||
newNode = doc.createNode({});
|
||||
renderSection(doc, value as any, newNode as YAMLSeq);
|
||||
renderSection(doc, value as Record<string, unknown>, newNode as YAMLSeq);
|
||||
} else {
|
||||
newNode = doc.createNode(value);
|
||||
}
|
||||
@ -86,10 +85,9 @@ function renderSection(doc: YAML.Document, obj: Record<string, unknown>, parentN
|
||||
}
|
||||
|
||||
function renderDefaultConfig() {
|
||||
const doc = new YAML.Document({});
|
||||
const doc = new Document({});
|
||||
doc.commentBefore = ' This is an example configuration file';
|
||||
// Needed because the entries syntax below would not work otherwise
|
||||
//const typeLessDefaultConfig = DefaultConfig as any;
|
||||
renderSection(doc, DefaultConfig as any);
|
||||
return doc.toString();
|
||||
}
|
||||
@ -127,7 +125,7 @@ async function renderRegistrationFile(configPath?: string) {
|
||||
rooms: [],
|
||||
},
|
||||
};
|
||||
console.log(YAML.stringify(obj));
|
||||
console.log(stringify(obj));
|
||||
}
|
||||
|
||||
|
||||
|
@ -12,7 +12,7 @@ import { FormatUtil } from "../FormatUtil";
|
||||
import { IGitHubWebhookEvent } from "../GithubWebhooks";
|
||||
import axios from "axios";
|
||||
import { GithubInstance } from "../Github/GithubInstance";
|
||||
import { IssuesGetResponseData } from "@octokit/types";
|
||||
import { IssuesGetResponseData } from "../Github/Types";
|
||||
|
||||
export interface GitHubIssueConnectionState {
|
||||
org: string;
|
||||
@ -168,8 +168,10 @@ export class GitHubIssueConnection implements IConnection {
|
||||
avatarUrl: comment.user.avatar_url,
|
||||
}, this.as);
|
||||
const matrixEvent = await this.commentProcessor.getEventBodyForGitHubComment(comment, event.repository, event.issue);
|
||||
|
||||
await this.messageClient.sendMatrixMessage(this.roomId, matrixEvent, "m.room.message", commentIntent.userId);
|
||||
// Comment body may be blank
|
||||
if (matrixEvent) {
|
||||
await this.messageClient.sendMatrixMessage(this.roomId, matrixEvent, "m.room.message", commentIntent.userId);
|
||||
}
|
||||
if (!updateState) {
|
||||
return;
|
||||
}
|
||||
@ -193,8 +195,9 @@ export class GitHubIssueConnection implements IConnection {
|
||||
if (this.state.comments_processed === -1) {
|
||||
// This has a side effect of creating a profile for the user.
|
||||
const creator = await getIntentForUser({
|
||||
login: issue.data.user.login,
|
||||
avatarUrl: issue.data.user.avatar_url
|
||||
// TODO: Fix
|
||||
login: issue.data.user?.login as string,
|
||||
avatarUrl: issue.data.user?.avatar_url || undefined
|
||||
}, this.as);
|
||||
// We've not sent any messages into the room yet, let's do it!
|
||||
if (issue.data.body) {
|
||||
@ -232,11 +235,12 @@ export class GitHubIssueConnection implements IConnection {
|
||||
|
||||
if (this.state.state !== issue.data.state) {
|
||||
if (issue.data.state === "closed") {
|
||||
const closedUserId = this.as.getUserIdForSuffix(issue.data.closed_by.login);
|
||||
// TODO: Fix
|
||||
const closedUserId = this.as.getUserIdForSuffix(issue.data.closed_by?.login as string);
|
||||
await this.messageClient.sendMatrixMessage(this.roomId, {
|
||||
msgtype: "m.notice",
|
||||
body: `closed the ${issue.data.pull_request ? "pull request" : "issue"} at ${issue.data.closed_at}`,
|
||||
external_url: issue.data.closed_by.html_url,
|
||||
external_url: issue.data.closed_by?.html_url,
|
||||
}, "m.room.message", closedUserId);
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { IConnection } from "./IConnection";
|
||||
import { Appservice } from "matrix-bot-sdk";
|
||||
import LogWrapper from "../LogWrapper";
|
||||
import { ProjectsGetResponseData } from "@octokit/types";
|
||||
import { ProjectsGetResponseData } from "../Github/Types";
|
||||
|
||||
export interface GitHubProjectConnectionState {
|
||||
// eslint-disable-next-line camelcase
|
||||
|
@ -12,7 +12,7 @@ import { FormatUtil } from "../FormatUtil";
|
||||
import axios from "axios";
|
||||
import { BotCommands, handleCommand, botCommand, compileBotCommands } from "../BotCommands";
|
||||
import { IGitHubWebhookEvent } from "../GithubWebhooks";
|
||||
import { ReposGetResponseData } from "@octokit/types";
|
||||
import { ReposGetResponseData } from "../Github/Types";
|
||||
|
||||
const log = new LogWrapper("GitHubRepoConnection");
|
||||
const md = new markdown();
|
||||
@ -265,11 +265,13 @@ export class GitHubRepoConnection implements IConnection {
|
||||
}
|
||||
const orgRepoName = event.issue.repository_url.substr("https://api.github.com/repos/".length);
|
||||
const content = `New issue created [${orgRepoName}#${event.issue.number}](${event.issue.html_url}): "${event.issue.title}"`;
|
||||
const labelsHtml = event.issue.labels.map((label: {color: string, name: string, description: string}) =>
|
||||
`<span title="${label.description}" data-mx-color="#CCCCCC" data-mx-bg-color="#${label.color}">${label.name}</span>`
|
||||
const labelsHtml = event.issue.labels.map((label: {color?: string|null, name?: string, description?: string|null}|string) =>
|
||||
typeof(label) === "string" ?
|
||||
`<span>${label}</span>` :
|
||||
`<span title="${label.description}" data-mx-color="#CCCCCC" data-mx-bg-color="#${label.color}">${label.name}</span>`
|
||||
).join(" ") || "";
|
||||
const labels = event.issue?.labels.map((label: {name: string}) =>
|
||||
label.name
|
||||
const labels = event.issue?.labels.map((label: {name?: string}|string) =>
|
||||
typeof(label) === "string" ? label : label.name
|
||||
).join(", ") || "";
|
||||
await this.as.botIntent.sendEvent(this.roomId, {
|
||||
msgtype: "m.notice",
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { IConnection } from "./IConnection";
|
||||
import { Appservice } from "matrix-bot-sdk";
|
||||
import { MatrixMessageContent, MatrixEvent } from "../MatrixEvent";
|
||||
import markdown from "markdown-it";
|
||||
import { UserTokenStore } from "../UserTokenStore";
|
||||
import LogWrapper from "../LogWrapper";
|
||||
import { CommentProcessor } from "../CommentProcessor";
|
||||
@ -23,9 +22,6 @@ export interface GitLabIssueConnectionState {
|
||||
}
|
||||
|
||||
const log = new LogWrapper("GitLabIssueConnection");
|
||||
const md = new markdown();
|
||||
|
||||
md.render("foo");
|
||||
|
||||
// interface IQueryRoomOpts {
|
||||
// as: Appservice;
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { IssuesGetCommentResponseData, IssuesGetResponseData, ProjectsListForOrgResponseData, ProjectsListForUserResponseData, ProjectsListForRepoResponseData } from "@octokit/types";
|
||||
/* eslint-disable camelcase */
|
||||
import { IssuesGetCommentResponseData, IssuesGetResponseData, ProjectsListResponseData } from './Github/Types';
|
||||
|
||||
interface IMinimalRepository {
|
||||
id: number;
|
||||
@ -12,8 +13,8 @@ export class FormatUtil {
|
||||
return `${orgRepoName}#${issue.number}: ${issue.title}`;
|
||||
}
|
||||
|
||||
public static formatRepoRoomName(repo: {full_name: string, description: string}) {
|
||||
return `${repo.full_name}: ${repo.description}`;
|
||||
public static formatRepoRoomName(repo: {full_name: string, description: string|null}) {
|
||||
return repo.description ? `${repo.full_name}: ${repo.description}` : repo.full_name;
|
||||
}
|
||||
|
||||
public static formatRoomTopic(repo: {state: string, html_url: string}) {
|
||||
@ -61,7 +62,11 @@ export class FormatUtil {
|
||||
};
|
||||
}
|
||||
|
||||
public static projectListing(projectItem: ProjectsListForOrgResponseData|ProjectsListForUserResponseData|ProjectsListForRepoResponseData) {
|
||||
return `${projectItem[0].name} (#${projectItem[0].number}) - Project ID: ${projectItem[0].id}`
|
||||
public static projectListing(projects: ProjectsListResponseData): string {
|
||||
let f = '';
|
||||
for (const projectItem of projects) {
|
||||
f += ` - ${projectItem.name} (#${projectItem.number}) - Project ID: ${projectItem.id}`;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,18 @@
|
||||
import { IssuesGetResponseData, IssuesGetCommentResponseData, PullsListReviewsResponseData, ReposGetResponseData, PullsListRequestedReviewersResponseData } from "@octokit/types";
|
||||
import { Endpoints } from "@octokit/types";
|
||||
|
||||
export type IssuesGetResponseData = Endpoints["GET /repos/{owner}/{repo}/issues/{issue_number}"]["response"]["data"];
|
||||
export type IssuesGetCommentResponseData = Endpoints["GET /repos/{owner}/{repo}/issues/comments/{comment_id}"]["response"]["data"];
|
||||
export type PullsListReviewsResponseData = Endpoints["GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews"]["response"]["data"];
|
||||
export type PullsListRequestedReviewersResponseData = Endpoints["GET /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers"]["response"]["data"];
|
||||
export type ReposGetResponseData = Endpoints["GET /repos/{owner}/{repo}"]["response"]["data"];
|
||||
export type ProjectsGetResponseData = Endpoints["GET /projects/{project_id}"]["response"]["data"];
|
||||
export type ProjectsListForTeamsResponseData = Endpoints["GET /teams/{team_id}/projects"]["response"]["data"];
|
||||
export type ProjectsListForRepoResponseData = Endpoints["GET /repos/{owner}/{repo}/projects"]["response"]["data"];
|
||||
export type ProjectsListForUserResponseData = Endpoints["GET /users/{username}/projects"]["response"]["data"];
|
||||
export type ProjectsListResponseData = ProjectsListForTeamsResponseData|ProjectsListForRepoResponseData|ProjectsListForUserResponseData;
|
||||
export type IssuesListAssigneesResponseData = Endpoints["GET /repos/{owner}/{repo}/issues"]["response"]["data"];
|
||||
export type PullsGetResponseData = Endpoints["GET /repos/{owner}/{repo}/pulls"]["response"]["data"];
|
||||
export type PullGetResponseData = Endpoints["GET /repos/{owner}/{repo}/pulls/{pull_number}"]["response"]["data"];
|
||||
/* eslint-disable camelcase */
|
||||
export interface GitHubUserNotification {
|
||||
id: string;
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { Appservice, IAppserviceRegistration, RichRepliesPreprocessor, IRichReplyMetadata } from "matrix-bot-sdk";
|
||||
import { ProjectsGetResponseData } from "@octokit/types";
|
||||
import { BridgeConfig, GitLabInstance } from "./Config/Config";
|
||||
import { IGitHubWebhookEvent, IOAuthRequest, IOAuthTokens, NotificationsEnableEvent,
|
||||
NotificationsDisableEvent } from "./GithubWebhooks";
|
||||
@ -27,6 +26,7 @@ import { GitLabIssueConnection } from "./Connections/GitlabIssue";
|
||||
import { GetIssueResponse, GetIssueOpts } from "./Gitlab/Types"
|
||||
import { GitLabClient } from "./Gitlab/Client";
|
||||
import { BridgeWidgetApi } from "./Widgets/BridgeWidgetApi";
|
||||
import { ProjectsGetResponseData } from "./Github/Types";
|
||||
|
||||
const log = new LogWrapper("GithubBridge");
|
||||
|
||||
@ -220,15 +220,19 @@ export class GithubBridge {
|
||||
if (!data.repository || !data.issue) {
|
||||
throw Error("Malformed webhook event, missing repository or issue");
|
||||
}
|
||||
if (!data.repository.owner?.login) {
|
||||
throw Error('Cannot get connection for ownerless issue');
|
||||
}
|
||||
return {
|
||||
owner: data.repository.owner?.login,
|
||||
repository: data.repository,
|
||||
issue: data.issue,
|
||||
};
|
||||
}
|
||||
|
||||
this.queue.on<IGitHubWebhookEvent>("comment.created", async ({ data }) => {
|
||||
const { repository, issue } = validateRepoIssue(data);
|
||||
const connections = this.getConnectionsForGithubIssue(repository.owner.login, repository.name, issue.number);
|
||||
const { repository, issue, owner } = validateRepoIssue(data);
|
||||
const connections = this.getConnectionsForGithubIssue(owner, repository.name, issue.number);
|
||||
connections.map(async (c) => {
|
||||
try {
|
||||
if (c instanceof GitHubIssueConnection)
|
||||
@ -240,8 +244,8 @@ export class GithubBridge {
|
||||
});
|
||||
|
||||
this.queue.on<IGitHubWebhookEvent>("issue.opened", async ({ data }) => {
|
||||
const { repository } = validateRepoIssue(data);
|
||||
const connections = this.getConnectionsForGithubRepo(repository.owner.login, repository.name);
|
||||
const { repository, owner } = validateRepoIssue(data);
|
||||
const connections = this.getConnectionsForGithubRepo(owner, repository.name);
|
||||
connections.map(async (c) => {
|
||||
try {
|
||||
await c.onIssueCreated(data);
|
||||
@ -252,8 +256,8 @@ export class GithubBridge {
|
||||
});
|
||||
|
||||
this.queue.on<IGitHubWebhookEvent>("issue.edited", async ({ data }) => {
|
||||
const { repository, issue } = validateRepoIssue(data);
|
||||
const connections = this.getConnectionsForGithubIssue(repository.owner.login, repository.name, issue.number);
|
||||
const { repository, issue, owner } = validateRepoIssue(data);
|
||||
const connections = this.getConnectionsForGithubIssue(owner, repository.name, issue.number);
|
||||
connections.map(async (c) => {
|
||||
try {
|
||||
if (c instanceof GitHubIssueConnection)
|
||||
@ -265,8 +269,8 @@ export class GithubBridge {
|
||||
});
|
||||
|
||||
this.queue.on<IGitHubWebhookEvent>("issue.closed", async ({ data }) => {
|
||||
const { repository, issue } = validateRepoIssue(data);
|
||||
const connections = this.getConnectionsForGithubIssue(repository.owner.login, repository.name, issue.number);
|
||||
const { repository, issue, owner } = validateRepoIssue(data);
|
||||
const connections = this.getConnectionsForGithubIssue(owner, repository.name, issue.number);
|
||||
connections.map(async (c) => {
|
||||
try {
|
||||
if (c instanceof GitHubIssueConnection)
|
||||
@ -278,8 +282,8 @@ export class GithubBridge {
|
||||
});
|
||||
|
||||
this.queue.on<IGitHubWebhookEvent>("issue.reopened", async ({ data }) => {
|
||||
const { repository, issue } = validateRepoIssue(data);
|
||||
const connections = this.getConnectionsForGithubIssue(repository.owner.login, repository.name, issue.number);
|
||||
const { repository, issue, owner } = validateRepoIssue(data);
|
||||
const connections = this.getConnectionsForGithubIssue(owner, repository.name, issue.number);
|
||||
connections.map(async (c) => {
|
||||
try {
|
||||
if (c instanceof GitHubIssueConnection)
|
||||
@ -413,7 +417,7 @@ export class GithubBridge {
|
||||
if (connections.length === 0) {
|
||||
// TODO: Refactor this to be a connection
|
||||
try {
|
||||
const accountData = await this.as.botIntent.underlyingClient.getRoomAccountData(
|
||||
const accountData = await this.as.botIntent.underlyingClient.getRoomAccountData<AdminAccountData>(
|
||||
BRIDGE_ROOM_TYPE, roomId,
|
||||
);
|
||||
const adminRoom = await this.setupAdminRoom(roomId, accountData);
|
||||
@ -461,9 +465,9 @@ export class GithubBridge {
|
||||
log.info(`Got message roomId=${roomId} from=${event.sender}`);
|
||||
log.debug(event);
|
||||
|
||||
if (this.adminRooms.has(roomId)) {
|
||||
const room = this.adminRooms.get(roomId)!;
|
||||
if (room.userId !== event.sender) {
|
||||
const adminRoom = this.adminRooms.get(roomId);
|
||||
if (adminRoom) {
|
||||
if (adminRoom.userId !== event.sender) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -472,7 +476,7 @@ export class GithubBridge {
|
||||
|
||||
if (processedReply) {
|
||||
const metadata: IRichReplyMetadata = processedReply.mx_richreply;
|
||||
log.info(`Handling reply to ${metadata.parentEventId} for ${room.userId}`);
|
||||
log.info(`Handling reply to ${metadata.parentEventId} for ${adminRoom.userId}`);
|
||||
// This might be a reply to a notification
|
||||
try {
|
||||
const ev = metadata.realEvent;
|
||||
@ -490,15 +494,14 @@ export class GithubBridge {
|
||||
log.info("Missing parts!:", splitParts, issueNumber);
|
||||
}
|
||||
} catch (ex) {
|
||||
await room.sendNotice("Failed to handle repy. You may not be authenticated to do that.");
|
||||
await adminRoom.sendNotice("Failed to handle repy. You may not be authenticated to do that.");
|
||||
log.error("Reply event could not be handled:", ex);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const command = event.content.body;
|
||||
const adminRoom = this.adminRooms.get(roomId);
|
||||
if (command && adminRoom) {
|
||||
if (command) {
|
||||
await adminRoom.handleCommand(event.event_id, command);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { BridgeConfig } from "./Config/Config";
|
||||
import { Application, default as express, Request, Response } from "express";
|
||||
import { createHmac } from "crypto";
|
||||
import { IssuesGetResponseData, IssuesGetCommentResponseData, ReposGetResponseData } from "@octokit/types";
|
||||
import { EventEmitter } from "events";
|
||||
import { MessageQueue, createMessageQueue, MessageQueueMessage } from "./MessageQueue/MessageQueue";
|
||||
import LogWrapper from "./LogWrapper";
|
||||
@ -10,6 +9,7 @@ import { Server } from "http";
|
||||
import axios from "axios";
|
||||
import { UserNotificationWatcher } from "./Notifications/UserNotificationWatcher";
|
||||
import { IGitLabWebhookEvent } from "./Gitlab/WebhookTypes";
|
||||
import { IssuesGetCommentResponseData, IssuesGetResponseData, ReposGetResponseData } from "./Github/Types";
|
||||
|
||||
const log = new LogWrapper("GithubWebhooks");
|
||||
|
||||
@ -34,7 +34,9 @@ export interface IOAuthRequest {
|
||||
}
|
||||
|
||||
export interface IOAuthTokens {
|
||||
// eslint-disable-next-line camelcase
|
||||
access_token: string;
|
||||
// eslint-disable-next-line camelcase
|
||||
token_type: string;
|
||||
state: string;
|
||||
}
|
||||
@ -181,6 +183,7 @@ export class GithubWebhooks extends EventEmitter {
|
||||
redirect_uri: this.config.github.oauth.redirect_uri,
|
||||
state: req.query.state as string,
|
||||
})}`);
|
||||
// eslint-disable-next-line camelcase
|
||||
const result = qs.parse(accessTokenRes.data) as { access_token: string, token_type: string };
|
||||
await this.queue.push<IOAuthTokens>({
|
||||
eventName: "oauth.tokens",
|
||||
|
@ -2,9 +2,8 @@ import { LogService } from "matrix-bot-sdk";
|
||||
import util from "util";
|
||||
import winston from "winston";
|
||||
|
||||
// Logs contain unknowns, ignore this.
|
||||
// tslint:disable: no-any
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
type MsgType = string|Error|any|{error?: string};
|
||||
export default class LogWrapper {
|
||||
|
||||
public static configureLogging(level: string) {
|
||||
@ -24,7 +23,7 @@ export default class LogWrapper {
|
||||
}),
|
||||
],
|
||||
});
|
||||
const getMessageString = (...messageOrObject: any[]) => {
|
||||
const getMessageString = (messageOrObject: MsgType[]) => {
|
||||
messageOrObject = messageOrObject.flat();
|
||||
const messageParts: string[] = [];
|
||||
messageOrObject.forEach((obj) => {
|
||||
@ -37,7 +36,7 @@ export default class LogWrapper {
|
||||
return messageParts.join(" ");
|
||||
};
|
||||
LogService.setLogger({
|
||||
info: (module: string, ...messageOrObject: any[]) => {
|
||||
info: (module: string, ...messageOrObject: MsgType[]) => {
|
||||
// These are noisy, redirect to debug.
|
||||
if (module.startsWith("MatrixLiteClient")) {
|
||||
log.debug(getMessageString(messageOrObject), { module });
|
||||
@ -45,19 +44,22 @@ export default class LogWrapper {
|
||||
}
|
||||
log.info(getMessageString(messageOrObject), { module });
|
||||
},
|
||||
warn: (module: string, ...messageOrObject: any[]) => {
|
||||
warn: (module: string, ...messageOrObject: MsgType[]) => {
|
||||
log.warn(getMessageString(messageOrObject), { module });
|
||||
},
|
||||
error: (module: string, ...messageOrObject: any[]) => {
|
||||
if (messageOrObject[0]?.error === "Room account data not found") {
|
||||
error: (module: string, ...messageOrObject: MsgType[]) => {
|
||||
if (typeof messageOrObject[0] === "object" && messageOrObject[0].error === "Room account data not found") {
|
||||
log.debug(getMessageString(messageOrObject), { module });
|
||||
return; // This is just noise :|
|
||||
}
|
||||
log.error(getMessageString(messageOrObject), { module });
|
||||
},
|
||||
debug: (module: string, ...messageOrObject: any[]) => {
|
||||
debug: (module: string, ...messageOrObject: MsgType[]) => {
|
||||
log.debug(getMessageString(messageOrObject), { module });
|
||||
},
|
||||
trace: (module: string, ...messageOrObject: MsgType[]) => {
|
||||
log.verbose(getMessageString(messageOrObject), { module });
|
||||
},
|
||||
});
|
||||
LogService.info("LogWrapper", "Reconfigured logging");
|
||||
}
|
||||
@ -69,7 +71,7 @@ export default class LogWrapper {
|
||||
* @param {string} module The module being logged
|
||||
* @param {*[]} messageOrObject The data to log
|
||||
*/
|
||||
public debug(...messageOrObject: any[]) {
|
||||
public debug(...messageOrObject: MsgType[]) {
|
||||
LogService.debug(this.module, ...messageOrObject);
|
||||
}
|
||||
|
||||
@ -77,7 +79,7 @@ export default class LogWrapper {
|
||||
* Logs to the ERROR channel
|
||||
* @param {*[]} messageOrObject The data to log
|
||||
*/
|
||||
public error(...messageOrObject: any[]) {
|
||||
public error(...messageOrObject: MsgType[]) {
|
||||
LogService.error(this.module, ...messageOrObject);
|
||||
}
|
||||
|
||||
@ -85,7 +87,7 @@ export default class LogWrapper {
|
||||
* Logs to the INFO channel
|
||||
* @param {*[]} messageOrObject The data to log
|
||||
*/
|
||||
public info(...messageOrObject: any[]) {
|
||||
public info(...messageOrObject: MsgType[]) {
|
||||
LogService.info(this.module, ...messageOrObject);
|
||||
}
|
||||
|
||||
@ -93,7 +95,7 @@ export default class LogWrapper {
|
||||
* Logs to the WARN channel
|
||||
* @param {*[]} messageOrObject The data to log
|
||||
*/
|
||||
public warn(...messageOrObject: any[]) {
|
||||
public warn(...messageOrObject: MsgType[]) {
|
||||
LogService.warn(this.module, ...messageOrObject);
|
||||
}
|
||||
}
|
||||
|
@ -106,6 +106,10 @@ export class GitHubWatcher extends EventEmitter implements NotificationWatcherTa
|
||||
log.warn("review_requested was missing subject.url_data.number");
|
||||
continue;
|
||||
}
|
||||
if (!rawEvent.repository.owner) {
|
||||
log.warn("review_requested was missing repository.owner");
|
||||
continue;
|
||||
}
|
||||
rawEvent.subject.requested_reviewers = (await this.octoKit.pulls.listRequestedReviewers({
|
||||
pull_number: rawEvent.subject.url_data.number,
|
||||
owner: rawEvent.repository.owner.login,
|
||||
|
@ -5,15 +5,17 @@ import LogWrapper from "./LogWrapper";
|
||||
import { AdminRoom } from "./AdminRoom";
|
||||
import markdown from "markdown-it";
|
||||
import { FormatUtil } from "./FormatUtil";
|
||||
import { IssuesListAssigneesResponseData, PullsGetResponseData, IssuesGetResponseData, PullsListRequestedReviewersResponseData, PullsListReviewsResponseData, IssuesGetCommentResponseData } from "@octokit/types";
|
||||
import { PullGetResponseData, IssuesGetResponseData, PullsListRequestedReviewersResponseData, PullsListReviewsResponseData, IssuesGetCommentResponseData } from "./Github/Types";
|
||||
import { GitHubUserNotification } from "./Github/Types";
|
||||
import { components } from "@octokit/openapi-types/dist-types/generated/types";
|
||||
|
||||
|
||||
const log = new LogWrapper("GithubBridge");
|
||||
const md = new markdown();
|
||||
|
||||
export interface IssueDiff {
|
||||
state: null|string;
|
||||
assignee: null|IssuesListAssigneesResponseData;
|
||||
assignee: null|(components["schemas"]["simple-user"][]);
|
||||
title: null|string;
|
||||
merged: boolean;
|
||||
mergedBy: null|{
|
||||
@ -34,7 +36,7 @@ export interface CachedReviewData {
|
||||
reviews: PullsListReviewsResponseData;
|
||||
}
|
||||
|
||||
type PROrIssue = IssuesGetResponseData|PullsGetResponseData;
|
||||
type PROrIssue = IssuesGetResponseData|PullGetResponseData;
|
||||
|
||||
export class NotificationProcessor {
|
||||
|
||||
@ -66,12 +68,13 @@ export class NotificationProcessor {
|
||||
plain += `\n\n Title changed to: ${diff.title}`;
|
||||
}
|
||||
if (diff.assignee) {
|
||||
plain += `\n\n Assigned to: ${diff.assignee[0].login}`;
|
||||
plain += `\n\n Assigned to: ${diff.assignee.map(l => l?.login).join(", ")}`;
|
||||
}
|
||||
}
|
||||
if (newComment) {
|
||||
const comment = notif.subject.latest_comment_url_data as IssuesGetCommentResponseData;
|
||||
plain += `\n\n ${NotificationProcessor.formatUser(comment.user)}:\n\n > ${comment.body}`;
|
||||
const user = comment.user ? NotificationProcessor.formatUser(comment.user) : 'user';
|
||||
plain += `\n\n ${user}:\n\n > ${comment.body}`;
|
||||
}
|
||||
return {
|
||||
plain,
|
||||
@ -187,9 +190,12 @@ export class NotificationProcessor {
|
||||
private diffIssueChanges(curr: PROrIssue, prev: PROrIssue): IssueDiff {
|
||||
let merged = false;
|
||||
let mergedBy = null;
|
||||
if ((curr as PullsGetResponseData).merged !== (prev as PullsGetResponseData).merged) {
|
||||
if ((curr as PullGetResponseData).merged !== (prev as PullGetResponseData).merged) {
|
||||
merged = true;
|
||||
mergedBy = (curr as PullsGetResponseData).merged_by;
|
||||
mergedBy = (curr as PullGetResponseData).merged_by;
|
||||
}
|
||||
if (!curr.user) {
|
||||
throw Error('No user for issue');
|
||||
}
|
||||
const diff: IssueDiff = {
|
||||
state: curr.state === prev.state ? null : curr.state,
|
||||
@ -217,7 +223,7 @@ export class NotificationProcessor {
|
||||
(await this.storage.getLastNotifCommentUrl(notif.repository.full_name, issueNumber, roomId));
|
||||
|
||||
const formatted = NotificationProcessor.formatNotification(notif, diff, newComment);
|
||||
let body: any = {
|
||||
let body = {
|
||||
msgtype: "m.text",
|
||||
body: formatted.plain,
|
||||
formatted_body: formatted.html,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { MemoryStorageProvider as MSP } from "matrix-bot-sdk";
|
||||
import { IStorageProvider } from "./StorageProvider";
|
||||
import { IssuesGetResponseData } from "@octokit/types";
|
||||
import { IssuesGetResponseData } from "../Github/Types";
|
||||
|
||||
export class MemoryStorageProvider extends MSP implements IStorageProvider {
|
||||
private issues: Map<string, IssuesGetResponseData> = new Map();
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { IssuesGetResponseData } from "@octokit/types";
|
||||
import { IssuesGetResponseData } from "../Github/Types";
|
||||
import { Redis, default as redis } from "ioredis";
|
||||
import LogWrapper from "../LogWrapper";
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { IAppserviceStorageProvider } from "matrix-bot-sdk";
|
||||
import { IssuesGetResponseData } from "@octokit/types";
|
||||
import { IssuesGetResponseData } from "../Github/Types";
|
||||
|
||||
export interface IStorageProvider extends IAppserviceStorageProvider {
|
||||
setGithubIssue(repo: string, issueNumber: string, data: IssuesGetResponseData, scope?: string): Promise<void>;
|
||||
|
@ -46,12 +46,14 @@ export class UserTokenStore {
|
||||
if (existingToken) {
|
||||
return existingToken;
|
||||
}
|
||||
let obj;
|
||||
try {
|
||||
let obj;
|
||||
if (type === "github") {
|
||||
obj = await this.intent.underlyingClient.getAccountData(key);
|
||||
obj = await this.intent.underlyingClient.getAccountData<{encrypted: string}>(key);
|
||||
} else if (type === "gitlab") {
|
||||
obj = await this.intent.underlyingClient.getAccountData(key);
|
||||
obj = await this.intent.underlyingClient.getAccountData<{encrypted: string}>(key);
|
||||
} else {
|
||||
throw Error('Unknown type');
|
||||
}
|
||||
const encryptedTextB64 = obj.encrypted;
|
||||
const encryptedText = Buffer.from(encryptedTextB64, "base64");
|
||||
|
@ -2,7 +2,7 @@ import { h, render } from 'preact';
|
||||
import 'preact/devtools';
|
||||
import App from './App';
|
||||
import "./styling.css";
|
||||
import "fontsource-open-sans/files/open-sans-latin-400-normal.woff2";
|
||||
import "@fontsource/open-sans/files/open-sans-latin-400-normal.woff2";
|
||||
|
||||
const root = document.getElementsByTagName('main')[0];
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
@import "fontsource-open-sans/400-normal.css";
|
||||
@import "../node_modules/@fontsource/open-sans/400.css";
|
||||
@import "mini.css";
|
||||
|
||||
body {
|
||||
|
Loading…
x
Reference in New Issue
Block a user