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,7 +1,13 @@
import _objectSpread from "@babel/runtime/helpers/objectSpread2";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.MatrixError = exports.HTTPError = exports.ConnectionError = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
/*
Copyright 2022 - 2024 The Matrix.org Foundation C.I.C.
Copyright 2022 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.
@@ -16,79 +22,27 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import { NamespacedValue } from "../NamespacedValue.js";
import { hasRequiredStringProperty, isRecord } from "../@types/type-guards.js";
/**
* Construct a generic HTTP error. This is a JavaScript Error with additional information
* specific to HTTP responses.
* @param msg - The error message to include.
* @param httpStatus - The HTTP response status code.
* @param httpHeaders - The HTTP response headers.
*/
export class HTTPError extends Error {
constructor(msg, httpStatus, httpHeaders) {
class HTTPError extends Error {
constructor(msg, httpStatus) {
super(msg);
this.httpStatus = httpStatus;
this.httpHeaders = httpHeaders;
}
/**
* Check if this error was due to rate-limiting on the server side (and should therefore be retried after a delay).
*
* If this returns `true`, {@link getRetryAfterMs} can be called to retrieve the server-side
* recommendation for the retry period.
*
* @returns Whether this error is due to rate-limiting.
*/
isRateLimitError() {
return this.httpStatus === 429;
}
/**
* @returns The recommended delay in milliseconds to wait before retrying
* the request that triggered this error, or null if no delay is recommended.
* @throws Error if the recommended delay is an invalid value.
* @see {@link safeGetRetryAfterMs} for a version of this check that doesn't throw.
*/
getRetryAfterMs() {
const retryAfter = this.httpHeaders?.get("Retry-After");
if (retryAfter != null) {
if (/^\d+$/.test(retryAfter)) {
const ms = Number.parseInt(retryAfter) * 1000;
if (!Number.isFinite(ms)) {
throw new Error("Retry-After header integer value is too large");
}
return ms;
}
const date = new Date(retryAfter);
if (date.toUTCString() !== retryAfter) {
throw new Error("Retry-After header value is not a valid HTTP-date or non-negative decimal integer");
}
return date.getTime() - Date.now();
}
return null;
}
}
/**
* Check if the given (JSON-parsed) response body looks like a Matrix error
* response as specified in https://spec.matrix.org/v1.19/client-server-api/#standard-error-response
*
* @param response - the parsed response body to check
* @returns whether the response is a valid {@link MatrixError}
*/
export function isMatrixErrorResponse(response) {
return isRecord(response) && hasRequiredStringProperty(response, "error") && hasRequiredStringProperty(response, "errcode");
}
export class MatrixError extends HTTPError {
exports.HTTPError = HTTPError;
class MatrixError extends HTTPError {
/**
* Construct a Matrix error. This is a JavaScript Error with additional
* information specific to the standard Matrix error response.
* @param errorJson - The Matrix error JSON returned from the homeserver.
* @param httpStatus - The numeric HTTP status code given
* @param httpHeaders - The HTTP response headers given
*/
constructor(errorJson = {}, httpStatus, url, event, httpHeaders) {
constructor(errorJson = {}, httpStatus, url, event) {
let message = errorJson.error || "Unknown message";
if (httpStatus) {
message = `[${httpStatus}] ${message}`;
@@ -96,83 +50,18 @@ export class MatrixError extends HTTPError {
if (url) {
message = `${message} (${url})`;
}
super(`MatrixError: ${message}`, httpStatus, httpHeaders);
// The Matrix 'errcode' value, e.g. "M_FORBIDDEN".
_defineProperty(this, "errcode", void 0);
// The Matrix 'error' value.
_defineProperty(this, "error", void 0);
// The raw Matrix error JSON used to construct this object.
_defineProperty(this, "data", void 0);
super(`MatrixError: ${message}`, httpStatus);
this.httpStatus = httpStatus;
this.url = url;
this.event = event;
// The Matrix 'errcode' value, e.g. "M_FORBIDDEN".
(0, _defineProperty2.default)(this, "errcode", void 0);
// The raw Matrix error JSON used to construct this object.
(0, _defineProperty2.default)(this, "data", void 0);
this.errcode = errorJson.errcode;
this.error = errorJson.error;
this.name = errorJson.errcode || "Unknown error code";
this.data = errorJson;
}
isRateLimitError() {
return this.errcode === "M_LIMIT_EXCEEDED" || (this.errcode === "M_UNKNOWN" || this.errcode === undefined) && super.isRateLimitError();
}
getRetryAfterMs() {
const headerValue = super.getRetryAfterMs();
if (headerValue !== null) {
return headerValue;
}
// Note: retry_after_ms is deprecated as of spec version v1.10
if (this.errcode === "M_LIMIT_EXCEEDED" && "retry_after_ms" in this.data) {
if (!Number.isInteger(this.data.retry_after_ms)) {
throw new Error("retry_after_ms is not an integer");
}
return this.data.retry_after_ms;
}
return null;
}
/**
* @returns this error expressed as a JSON payload
* for use by Widget API error responses.
*/
asWidgetApiErrorData() {
const headers = {};
if (this.httpHeaders) {
for (const [name, value] of this.httpHeaders) {
headers[name] = value;
}
}
return {
http_status: this.httpStatus ?? 400,
http_headers: headers,
url: this.url ?? "",
response: _objectSpread({
errcode: this.errcode ?? "M_UNKNOWN",
error: this.data.error ?? "Unknown message"
}, this.data)
};
}
/**
* @returns a new {@link MatrixError} from a JSON payload
* received from Widget API error responses.
*/
static fromWidgetApiErrorData(data) {
return new MatrixError(data.response, data.http_status, data.url, undefined, new Headers(data.http_headers));
}
}
/**
* @returns The recommended delay in milliseconds to wait before retrying the request.
* @param error - The error to check for a retry delay.
* @param defaultMs - The delay to use if the error was not due to rate-limiting or if no valid delay is recommended.
*/
export function safeGetRetryAfterMs(error, defaultMs) {
if (!(error instanceof HTTPError) || !error.isRateLimitError()) {
return defaultMs;
}
try {
return error.getRetryAfterMs() ?? defaultMs;
} catch {
return defaultMs;
}
}
/**
@@ -181,7 +70,8 @@ export function safeGetRetryAfterMs(error, defaultMs) {
* CORS was not correctly configured on the server, the server didn't response,
* the request timed out, or the internet connection on the client side went down.
*/
export class ConnectionError extends Error {
exports.MatrixError = MatrixError;
class ConnectionError extends Error {
constructor(message, cause) {
super(message + (cause ? `: ${cause.message}` : ""));
}
@@ -189,58 +79,5 @@ export class ConnectionError extends Error {
return "ConnectionError";
}
}
/**
* Construct a TokenRefreshError. This indicates that a request failed due to the token being expired,
* and attempting to refresh said token also failed but in a way which was not indicative of token invalidation.
* Assumed to be a temporary failure.
*/
export class TokenRefreshError extends Error {
constructor(cause) {
super(cause?.message ?? "");
}
get name() {
return "TokenRefreshError";
}
}
/**
* Construct a TokenRefreshError. This indicates that a request failed due to the token being expired,
* and attempting to refresh said token failed in a way indicative of token invalidation.
*/
export class TokenRefreshLogoutError extends Error {
constructor(cause) {
super(cause?.message ?? "");
}
get name() {
return "TokenRefreshLogoutError";
}
}
export const MatrixSafetyErrorCode = new NamespacedValue(null, "ORG.MATRIX.MSC4387_SAFETY");
/***
* This error is thrown when the homeserver refuses to handle an action due to a
* safety concern.
* @see https://github.com/matrix-org/matrix-spec-proposals/pull/4387
*/
export class MatrixSafetyError extends MatrixError {
constructor(...props) {
super(...props);
/**
* The kinds of harms detected by the server.
* @see https://github.com/matrix-org/matrix-spec-proposals/pull/4387 for a list of spec defined harms.
*/
_defineProperty(this, "harms", void 0);
/**
* The date at which a request can be reattempted.
*/
_defineProperty(this, "expiry", void 0);
const body = props[0];
this.harms = new Set(body && "harms" in body && Array.isArray(body.harms) ? body.harms : []);
this.message = `${super.message} (${[...this.harms].join(", ")})`;
if (body && "expiry" in body && typeof body.expiry === "number") {
this.expiry = new Date(body.expiry);
}
}
}
exports.ConnectionError = ConnectionError;
//# sourceMappingURL=errors.js.map