diff --git a/matrix/file.js b/matrix/file.js index bf5a588..2dd64f1 100644 --- a/matrix/file.js +++ b/matrix/file.js @@ -13,6 +13,13 @@ const IMAGE_SIZE = 1024 /** @type {Map>} */ const inflight = new Map() +/** + * @param {string} url + */ +function _removeExpiryParams(url) { + return url.replace(/\?(?:(?:ex|is|sg|hm)=[a-f0-9]+&?)*$/, "") +} + /** * @param {string} path */ @@ -26,14 +33,17 @@ async function uploadDiscordFileToMxc(path) { url = DISCORD_IMAGES_BASE + path } + // Discord attachment content is always the same no matter what their ?ex parameter is. + const urlNoExpiry = _removeExpiryParams(url) + // Are we uploading this file RIGHT NOW? Return the same inflight promise with the same resolution - const existingInflight = inflight.get(url) + const existingInflight = inflight.get(urlNoExpiry) if (existingInflight) { return existingInflight } // Has this file already been uploaded in the past? Grab the existing copy from the database. - const existingFromDb = select("file", "mxc_url", "WHERE discord_url = ?").pluck().get(url) + const existingFromDb = select("file", "mxc_url", "WHERE discord_url = ?").pluck().get(urlNoExpiry) if (typeof existingFromDb === "string") { return existingFromDb } @@ -41,15 +51,15 @@ async function uploadDiscordFileToMxc(path) { // Download from Discord const promise = fetch(url, {}).then(/** @param {import("node-fetch").Response} res */ async res => { // Upload to Matrix - const root = await module.exports._actuallyUploadDiscordFileToMxc(url, res) + const root = await module.exports._actuallyUploadDiscordFileToMxc(urlNoExpiry, res) // Store relationship in database - db.prepare("INSERT INTO file (discord_url, mxc_url) VALUES (?, ?)").run(url, root.content_uri) - inflight.delete(url) + db.prepare("INSERT INTO file (discord_url, mxc_url) VALUES (?, ?)").run(urlNoExpiry, root.content_uri) + inflight.delete(urlNoExpiry) return root.content_uri }) - inflight.set(url, promise) + inflight.set(urlNoExpiry, promise) return promise } @@ -108,3 +118,4 @@ module.exports.stickerFormat = stickerFormat module.exports.sticker = sticker module.exports.uploadDiscordFileToMxc = uploadDiscordFileToMxc module.exports._actuallyUploadDiscordFileToMxc = _actuallyUploadDiscordFileToMxc +module.exports._removeExpiryParams = _removeExpiryParams diff --git a/matrix/file.test.js b/matrix/file.test.js new file mode 100644 index 0000000..2d59dbc --- /dev/null +++ b/matrix/file.test.js @@ -0,0 +1,22 @@ +// @ts-check + +const {test} = require("supertape") +const file = require("./file") + +test("removeExpiryParams: url without params is unchanged", t => { + const url = "https://cdn.discordapp.com/attachments/1154455830591176734/1157034603496882267/59ce542f-bf66-4d9a-83b7-ad6d05a69bac.jpg" + const result = file._removeExpiryParams(url) + t.equal(result, url) +}) + +test("removeExpiryParams: params are removed", t => { + const url = "https://cdn.discordapp.com/attachments/112760669178241024/1157363960518029322/image.png?ex=651856ae&is=6517052e&hm=88353defb15cbd833e6977817e8f72f4ff28f4edfd26b8ad5f267a4f2b946e69&" + const result = file._removeExpiryParams(url) + t.equal(result, "https://cdn.discordapp.com/attachments/112760669178241024/1157363960518029322/image.png") +}) + +test("removeExpiryParams: rearranged params are removed", t => { + const url = "https://cdn.discordapp.com/attachments/112760669178241024/1157363960518029322/image.png?hm=88353defb15cbd833e6977817e8f72f4ff28f4edfd26b8ad5f267a4f2b946e69&ex=651856ae&is=6517052e" + const result = file._removeExpiryParams(url) + t.equal(result, "https://cdn.discordapp.com/attachments/112760669178241024/1157363960518029322/image.png") +})