Support mentions and images

This commit is contained in:
Half-Shot 2019-08-06 15:04:58 +01:00
parent 91e2a4b72a
commit ec04907b06
2 changed files with 54 additions and 9 deletions

View File

@ -13,20 +13,27 @@
},
"dependencies": {
"@octokit/rest": "^16.28.7",
"@types/express": "^4.17.0",
"@types/ioredis": "^4.0.13",
"@types/markdown-it": "^0.0.8",
"express": "^4.17.1",
"ioredis": "^4.14.0",
"markdown-it": "^9.0.1",
"matrix-bot-sdk": "^0.3.9",
"micromatch": "^4.0.2",
"mime": "^2.4.4",
"mocha": "^6.2.0",
"node-emoji": "^1.10.0",
"request-promise-native": "^1.0.7",
"winston": "^3.2.1",
"yaml": "^1.6.0"
},
"devDependencies": {
"@types/express": "^4.17.0",
"@types/ioredis": "^4.0.13",
"@types/markdown-it": "^0.0.8",
"@types/micromatch": "^3.1.0",
"@types/mime": "^2.0.1",
"@types/node": "^12.6.9",
"@types/node-emoji": "^1.8.1",
"@types/request-promise-native": "^1.0.16",
"@types/yaml": "^1.0.2",
"typescript": "^3.5.3"
}

View File

@ -1,9 +1,13 @@
import { IssuesGetCommentResponse } from "@octokit/rest";
import { Appservice } from "matrix-bot-sdk";
import request from "request-promise-native";
import markdown from "markdown-it";
import mime from "mime";
import emoji from "node-emoji";
const md = new markdown();
const REGEX_MENTION = /(^|\s)(@[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38})(\s|$)/ig;
const REGEX_IMAGES = /!\[.*]\((.*\.(\w+))\)/gm;
interface IMatrixCommentEvent {
msgtype: string;
@ -19,15 +23,16 @@ interface IMatrixCommentEvent {
export class CommentProcessor {
constructor (private as: Appservice) {}
public getEventBodyForComment(comment: IssuesGetCommentResponse): IMatrixCommentEvent {
public async getEventBodyForComment(comment: IssuesGetCommentResponse): Promise<IMatrixCommentEvent> {
let body = comment.body;
body = body.replace(REGEX_MENTION, (_match: string, _part1: string, githubId: string) => {
const userId = this.as.getUserIdForSuffix(githubId.substr(1));
return `[$2](https://matrix.to/#/${userId})`;
});
body = this.replaceMentions(body);
body = await this.replaceImages(body);
body = emoji.emojify(body);
let htmlBody = md.render(body);
console.log(body, htmlBody);
return {
body,
formatted_body: md.render(body),
formatted_body: htmlBody,
msgtype: "m.text",
format: "org.matrix.custom.html",
external_url: comment.html_url,
@ -36,4 +41,37 @@ export class CommentProcessor {
},
}
}
private replaceMentions(body: string): string {
return body.replace(REGEX_MENTION, (_match: string, _part1: string, githubId: string) => {
const userId = this.as.getUserIdForSuffix(githubId.substr(1));
return `[$2](https://matrix.to/#/${userId})`;
});
}
private async replaceImages(body: string): Promise<string> {
let match;
let bodyCopy = body;
let urlMatches: string[] = [];
while(match = REGEX_IMAGES.exec(bodyCopy)) {
bodyCopy = bodyCopy.replace(match[1], "");
const contentType = mime.getType(match[1]) || "none";
if (!contentType.startsWith("image") && !contentType.startsWith("video") && !contentType.startsWith("audio")) {
// Not handling media.
continue;
}
urlMatches.push(match[1]);
}
for (const rawUrl of urlMatches) {
try {
const imageData = await request.get(rawUrl, { encoding: null});
const contentType = mime.getType(rawUrl) || "application/octet-stream";
const url = await this.as.botIntent.underlyingClient.uploadContent(imageData, contentType);
body = body.replace(rawUrl, url);
} catch (ex) {
console.warn("Failed to upload file");
}
}
return body;
}
}