feat: complete Ancestor quote bot with production-ready Docker support

This commit is contained in:
unfunny
2026-09-13 14:14:38 -04:00
parent f2016da05a
commit fe7351a7dc
1145 changed files with 30890 additions and 97684 deletions

View File

@@ -1,5 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getHttpUriForMxc = getHttpUriForMxc;
var _utils = require("./utils");
/*
Copyright 2015 - 2024 The Matrix.org Foundation C.I.C.
Copyright 2015 - 2021 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,22 +21,6 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Validation based on https://spec.matrix.org/v1.12/appendices/#server-name
// We do not use the validation described in https://spec.matrix.org/v1.12/client-server-api/#security-considerations-5
// as it'd wrongly make all MXCs invalid due to not allowing `[].:` in server names.
const serverNameRegex = /^(?:(?:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})|(?:\[[\dA-Fa-f:.]{2,45}])|(?:[A-Za-z\d\-.]{1,255}))(?::\d{1,5})?$/;
function validateServerName(serverName) {
const matches = serverNameRegex.exec(serverName);
return matches?.[0] === serverName;
}
// Validation based on https://spec.matrix.org/v1.12/client-server-api/#security-considerations-5
const mediaIdRegex = /^[\w-]+$/;
function validateMediaId(mediaId) {
const matches = mediaIdRegex.exec(mediaId);
return matches?.[0] === mediaId;
}
/**
* Get the HTTP URL for an MXC URI.
* @param baseUrl - The base homeserver url which has a content repo.
@@ -42,64 +33,43 @@ function validateMediaId(mediaId) {
* directly. Fetching such URLs will leak information about the user to
* anyone they share a room with. If false, will return the emptry string
* for such URLs.
* @param allowRedirects - If true, the caller supports the URL being 307 or
* 308 redirected to another resource upon request. If false, redirects
* are not expected. Implied `true` when `useAuthentication` is `true`.
* @param useAuthentication - If true, the caller supports authenticated
* media and wants an authentication-required URL. Note that server support
* for authenticated media will *not* be checked - it is the caller's responsibility
* to do so before calling this function. Note also that `useAuthentication`
* implies `allowRedirects`. Defaults to false (unauthenticated endpoints).
* @param animated - Whether the desired thumbnail should be animated.
* @returns The complete URL to the content, may be an empty string if the provided mxc is not valid.
* @returns The complete URL to the content.
*/
export function getHttpUriForMxc(baseUrl, mxc, width, height, resizeMethod, allowDirectLinks = false, allowRedirects, useAuthentication, animated) {
function getHttpUriForMxc(baseUrl, mxc, width, height, resizeMethod, allowDirectLinks = false) {
if (typeof mxc !== "string" || !mxc) {
return "";
}
if (!mxc.startsWith("mxc://")) {
if (mxc.indexOf("mxc://") !== 0) {
if (allowDirectLinks) {
return mxc;
} else {
return "";
}
}
const [serverName, mediaId, ...rest] = mxc.slice(6).split("/");
if (rest.length > 0 || !validateServerName(serverName) || !validateMediaId(mediaId)) {
return "";
}
if (useAuthentication) {
allowRedirects = true; // per docs (MSC3916 always expects redirects)
// Dev note: MSC3916 removes `allow_redirect` entirely, but
// for explicitness we set it here. This makes it slightly more obvious to
// callers, hopefully.
}
let prefix;
const isThumbnailRequest = !!width || !!height || !!resizeMethod;
const verb = isThumbnailRequest ? "thumbnail" : "download";
if (useAuthentication) {
prefix = `/_matrix/client/v1/media/${verb}`;
} else {
prefix = `/_matrix/media/v3/${verb}`;
}
const url = new URL(`${prefix}/${serverName}/${mediaId}`, baseUrl);
let serverAndMediaId = mxc.slice(6); // strips mxc://
let prefix = "/_matrix/media/r0/download/";
const params = {};
if (width) {
url.searchParams.set("width", Math.round(width).toString());
params["width"] = Math.round(width).toString();
}
if (height) {
url.searchParams.set("height", Math.round(height).toString());
params["height"] = Math.round(height).toString();
}
if (resizeMethod) {
url.searchParams.set("method", resizeMethod);
params["method"] = resizeMethod;
}
if (animated !== undefined) {
url.searchParams.set("animated", String(animated));
if (Object.keys(params).length > 0) {
// these are thumbnailing params so they probably want the
// thumbnailing API...
prefix = "/_matrix/media/r0/thumbnail/";
}
if (typeof allowRedirects === "boolean") {
// We add this after, so we don't convert everything to a thumbnail request.
url.searchParams.set("allow_redirect", JSON.stringify(allowRedirects));
const fragmentOffset = serverAndMediaId.indexOf("#");
let fragment = "";
if (fragmentOffset >= 0) {
fragment = serverAndMediaId.slice(fragmentOffset);
serverAndMediaId = serverAndMediaId.slice(0, fragmentOffset);
}
return url.href;
const urlParams = Object.keys(params).length === 0 ? "" : "?" + (0, _utils.encodeParams)(params);
return baseUrl + prefix + serverAndMediaId + urlParams + fragment;
}
//# sourceMappingURL=content-repo.js.map