Skip to content

Commit

Permalink
Send attachments as urls if the file exceeds 8MB
Browse files Browse the repository at this point in the history
  • Loading branch information
Half-Shot committed Apr 28, 2018
1 parent d868a93 commit d123d5f
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 41 deletions.
43 changes: 12 additions & 31 deletions src/bot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import * as Discord from "discord.js";
import * as log from "npmlog";
import * as Bluebird from "bluebird";
import * as mime from "mime";
import * as path from "path";
import { Provisioner } from "./provisioner";

// Due to messages often arriving before we get a response from the send call,
Expand Down Expand Up @@ -181,15 +180,13 @@ export class DiscordBot {
}
const embed = this.mxEventProcessor.EventToEmbed(event, profile, chan);
const opts: Discord.MessageOptions = {};
const hasAttachment = ["m.image", "m.audio", "m.video", "m.file"].indexOf(event.content.msgtype) !== -1;
if (hasAttachment) {
const attachment = await Util.DownloadFile(mxClient.mxcUrlToHttp(event.content.url));
const name = this.GetFilenameForMediaEvent(event.content);
opts.file = {
name,
attachment,
};
const file = await this.mxEventProcessor.HandleAttachment(event, mxClient);
if (typeof(file) === "string") {
embed.description += " " + file;
} else {
opts.file = file;
}

let msg = null;
let hook: Discord.Webhook ;
if (botUser) {
Expand All @@ -207,18 +204,12 @@ export class DiscordBot {
try {
if (!botUser) {
msg = await chan.send(embed.description, opts);
} else if (hook && !hasAttachment) {
const hookOpts: Discord.WebhookMessageOptions = {
username: embed.author.name,
avatarURL: embed.author.icon_url,
};
// Uncomment this and remove !hasAttachment above after https://github.com/hydrabolt/discord.js/pull/1449 pulled
// if (hasAttachment) {
// hookOpts.file = opts.file;
// msg = await hook.send(embed.description, hookOpts);
// } else {
msg = await hook.send(embed.description, hookOpts);
// }
} else if (hook) {
msg = await hook.send(embed.description, {
username: embed.author.name,
avatarURL: embed.author.icon_url,
file: opts.file,
});
} else {
opts.embed = embed;
msg = await chan.send("", opts);
Expand Down Expand Up @@ -329,16 +320,6 @@ export class DiscordBot {
return dbEmoji.MxcUrl;
}

private GetFilenameForMediaEvent(content): string {
if (content.body) {
if (path.extname(content.body) !== "") {
return content.body;
}
return path.basename(content.body) + "." + mime.extension(content.info.mimetype);
}
return "matrix-media." + mime.extension(content.info.mimetype);
}

private GetRoomIdsFromChannel(channel: Discord.Channel): Promise<string[]> {
return this.bridge.getRoomStore().getEntriesByRemoteRoomData({
discord_channel: channel.id,
Expand Down
41 changes: 41 additions & 0 deletions src/matrixeventprocessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ import {MessageProcessorOpts, MessageProcessor} from "./messageprocessor";
import {DiscordBot} from "./bot";
import {DiscordBridgeConfig} from "./config";
import * as escapeStringRegexp from "escape-string-regexp";
import {Util} from "./util";
import * as path from "path";
import * as mime from "mime";
import * as log from "npmlog";

const MaxFileSize = 8000000;

export class MatrixEventProcessorOpts {
constructor(
Expand Down Expand Up @@ -85,4 +91,39 @@ export class MatrixEventProcessor {
return body;
}

public async HandleAttachment(event: any, mxClient: any): Promise<string|Discord.FileOptions> {
const hasAttachment = ["m.image", "m.audio", "m.video", "m.file"].indexOf(event.content.msgtype) !== -1;
if (!hasAttachment) {
return "";
}
if (event.content.info == null) {
log.info("Event was an attachment type but was missing a content.info");
return "";
}

let size = event.content.info.size || 0;
const url = mxClient.mxcUrlToHttp(event.content.url);
const name = this.GetFilenameForMediaEvent(event.content);
if (size < MaxFileSize) {
const attachment = await Util.DownloadFile(url);
size = attachment.byteLength;
if (size < MaxFileSize) {
return {
name,
attachment,
};
}
}
return `[${name}](${url})`;
}

private GetFilenameForMediaEvent(content: any): string {
if (content.body) {
if (path.extname(content.body) !== "") {
return content.body;
}
return path.basename(content.body) + "." + mime.extension(content.info.mimetype);
}
return "matrix-media." + mime.extension(content.info.mimetype);
}
}
99 changes: 89 additions & 10 deletions test/test_matrixeventprocessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import * as log from "npmlog";
import * as Discord from "discord.js";
import * as Proxyquire from "proxyquire";

// import * as Proxyquire from "proxyquire";
import { PresenceHandler } from "../src/presencehandler";
import { DiscordBot } from "../src/bot";
import { MockGuild } from "./mocks/guild";
Expand All @@ -29,17 +28,19 @@ const bot = {
},
};

const mxClient = {
mxcUrlToHttp: (url) => {
return url.replace("mxc://", "https://");
},
};

function createMatrixEventProcessor
(disableMentions: boolean = false, disableEveryone = false, disableHere = false): MatrixEventProcessor {
const bridge = {
getClientFactory: () => {
return {
getClientAs: () => {
return {
mxcUrlToHttp: () => {
return "https://madeup.com";
},
};
return mxClient;
},
};
},
Expand All @@ -48,7 +49,16 @@ function createMatrixEventProcessor
config.bridge.disableDiscordMentions = disableMentions;
config.bridge.disableEveryoneMention = disableEveryone;
config.bridge.disableHereMention = disableHere;
return new MatrixEventProcessor(
return new (Proxyquire("../src/matrixeventprocessor", {
"./util": {
Util: {
DownloadFile: (name: string) => {
const size = parseInt(name.substring(name.lastIndexOf("/")+1), undefined);
return Buffer.alloc(size);
},
},
},
})).MatrixEventProcessor(
new MatrixEventProcessorOpts(
config,
bridge,
Expand All @@ -71,7 +81,7 @@ describe("MatrixEventProcessor", () => {
avatar_url: "mxc://localhost/avatarurl",
}, mockChannel as any);
Chai.assert.equal(evt.author.name, "Test User");
Chai.assert.equal(evt.author.icon_url, "https://madeup.com");
Chai.assert.equal(evt.author.icon_url, "https://localhost/avatarurl");
Chai.assert.equal(evt.author.url, "https://matrix.to/#/@test:localhost");
});

Expand Down Expand Up @@ -109,9 +119,9 @@ describe("MatrixEventProcessor", () => {
content: {
body: "testcontent",
},
}, {avatar_url: "test"}, mockChannel as any);
}, {avatar_url: "mxc://localhost/test"}, mockChannel as any);
Chai.assert.equal(evt.author.name, "@test:localhost");
Chai.assert.equal(evt.author.icon_url, "https://madeup.com");
Chai.assert.equal(evt.author.icon_url, "https://localhost/test");
Chai.assert.equal(evt.author.url, "https://matrix.to/#/@test:localhost");
});

Expand Down Expand Up @@ -235,4 +245,73 @@ describe("MatrixEventProcessor", () => {
Chai.assert.equal(content, "Welcome thatman");
});
});
describe("HandleAttachment", () => {
it("message without an attachment", () => {
const processor = createMatrixEventProcessor();
return expect(processor.HandleAttachment({
content: {
msgtype: "m.text",
},
}, mxClient)).to.eventually.eq("");
});
it("message without an info", () => {
const processor = createMatrixEventProcessor();
return expect(processor.HandleAttachment({
content: {
msgtype: "m.video",
},
}, mxClient)).to.eventually.eq("");
});
it("message without an info", () => {
const processor = createMatrixEventProcessor();
return expect(processor.HandleAttachment({
content: {
msgtype: "m.video",
},
}, mxClient)).to.eventually.eq("");
});
it("message with a large info.size", () => {
const processor = createMatrixEventProcessor();
return expect(processor.HandleAttachment({
content: {
msgtype: "m.video",
info: {
size: 8000000,
},
body: "filename.webm",
url: "mxc://localhost/8000000"
},
}, mxClient)).to.eventually.eq("[filename.webm](https://localhost/8000000)");
});
it("message with a small info.size", () => {
const processor = createMatrixEventProcessor();
return expect(processor.HandleAttachment({
content: {
msgtype: "m.video",
info: {
size: 200,
},
body: "filename.webm",
url: "mxc://localhost/200"
},
}, mxClient)).to.eventually.satisfy((attachment) => {
expect(attachment.name).to.eq("filename.webm");
expect(attachment.attachment.length).to.eq(200);
return true;
});
});
it("message with a small info.size but a larger file", () => {
const processor = createMatrixEventProcessor();
return expect(processor.HandleAttachment({
content: {
msgtype: "m.video",
info: {
size: 200,
},
body: "filename.webm",
url: "mxc://localhost/8000000"
},
}, mxClient)).to.eventually.eq("[filename.webm](https://localhost/8000000)");
});
});
});

0 comments on commit d123d5f

Please sign in to comment.