Files
game-server-watcher/node_modules/grammy/out/core/client.js
Smith a5f3794527 include prod deps in vcs with some exceptions
* cloudno.de has problems installing new dependencies lately..
2022-06-30 22:59:51 +02:00

181 lines
7.3 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createRawApi = void 0;
const platform_node_js_1 = require("../platform.node.js");
const error_js_1 = require("./error.js");
const payload_js_1 = require("./payload.js");
const debug = (0, platform_node_js_1.debug)("grammy:core");
// Transformer base functions
function concatTransformer(prev, trans) {
return (method, payload, signal) => trans(prev, method, payload, signal);
}
class ApiClient {
constructor(token, options = {}, webhookReplyEnvelope = {}) {
var _a, _b, _c, _d, _e;
this.token = token;
this.webhookReplyEnvelope = webhookReplyEnvelope;
this.hasUsedWebhookReply = false;
this.installedTransformers = [];
this.call = async (method, p, signal) => {
const payload = p !== null && p !== void 0 ? p : {};
debug(`Calling ${method}`);
// General config
const opts = this.options;
const formDataRequired = (0, payload_js_1.requiresFormDataUpload)(payload);
// Short-circuit on webhook reply
if (this.webhookReplyEnvelope.send !== undefined &&
!this.hasUsedWebhookReply &&
!formDataRequired &&
opts.canUseWebhookReply(method)) {
this.hasUsedWebhookReply = true;
const config = (0, payload_js_1.createJsonPayload)({ ...payload, method });
await this.webhookReplyEnvelope.send(config.body);
return { ok: true, result: true };
}
// Handle timeouts and errors in the underlying form-data stream
const controller = createAbortControllerFromSignal(signal);
const timeout = createTimeout(controller, opts.timeoutSeconds, method);
const streamErr = createStreamError(controller);
// Build request URL and config
const url = opts.buildUrl(opts.apiRoot, this.token, method);
const config = formDataRequired
? (0, payload_js_1.createFormDataPayload)(payload, (err) => streamErr.catch(err))
: (0, payload_js_1.createJsonPayload)(payload);
const sig = controller.signal;
const options = { ...opts.baseFetchConfig, signal: sig, ...config };
// Perform fetch call, and handle networking errors
const successPromise = (0, shim_node_js_1.fetch)(url instanceof URL ? url.href : url, options).catch((0, error_js_1.toHttpError)(method, opts.sensitiveLogs));
// Those are the three possible outcomes of the fetch call:
const operations = [successPromise, streamErr.promise, timeout.promise];
// Wait for result
try {
const res = await Promise.race(operations);
return await res.json();
}
finally {
if (timeout.handle !== undefined)
clearTimeout(timeout.handle);
}
};
const apiRoot = (_a = options.apiRoot) !== null && _a !== void 0 ? _a : "https://api.telegram.org";
this.options = {
apiRoot,
buildUrl: (_b = options.buildUrl) !== null && _b !== void 0 ? _b : ((root, token, method) => `${root}/bot${token}/${method}`),
timeoutSeconds: (_c = options.timeoutSeconds) !== null && _c !== void 0 ? _c : 500,
baseFetchConfig: {
...(0, platform_node_js_1.baseFetchConfig)(apiRoot),
...options.baseFetchConfig,
},
canUseWebhookReply: (_d = options.canUseWebhookReply) !== null && _d !== void 0 ? _d : (() => false),
sensitiveLogs: (_e = options.sensitiveLogs) !== null && _e !== void 0 ? _e : false,
};
if (this.options.apiRoot.endsWith("/")) {
throw new Error(`Remove the trailing '/' from the 'apiRoot' option (use '${this.options.apiRoot.substring(0, this.options.apiRoot.length - 1)}' instead of '${this.options.apiRoot}')`);
}
}
use(...transformers) {
this.call = transformers.reduce(concatTransformer, this.call);
this.installedTransformers.push(...transformers);
return this;
}
async callApi(method, payload, signal) {
const data = await this.call(method, payload, signal);
if (data.ok)
return data.result;
else
throw (0, error_js_1.toGrammyError)(data, method, payload);
}
}
/**
* Creates a new transformable API, i.e. an object that lets you perform raw API
* calls to the Telegram Bot API server but pass the calls through a stack of
* transformers before. This will create a new API client instance under the
* hood that will be used to connect to the Telegram servers. You therefore need
* to pass the bot token. In addition, you may pass API client options as well
* as a webhook reply envelope that allows the client to perform up to one HTTP
* request in response to a webhook call if this is desired.
*
* @param token The bot's token
* @param options A number of options to pass to the created API client
* @param webhookReplyEnvelope The webhook reply envelope that will be used
*/
function createRawApi(token, options, webhookReplyEnvelope) {
const client = new ApiClient(token, options, webhookReplyEnvelope);
const proxyHandler = {
get(_, m) {
return m === "toJSON"
? "__internal"
: client.callApi.bind(client, m);
},
...proxyMethods,
};
const raw = new Proxy({}, proxyHandler);
const installedTransformers = client.installedTransformers;
const api = {
raw,
installedTransformers,
use: (...t) => {
client.use(...t);
return api;
},
};
return api;
}
exports.createRawApi = createRawApi;
const proxyMethods = {
set() {
return false;
},
defineProperty() {
return false;
},
deleteProperty() {
return false;
},
ownKeys() {
return [];
},
};
/** Creates a timeout error which aborts a given controller */
function createTimeout(controller, seconds, method) {
let handle = undefined;
const promise = new Promise((_, reject) => {
handle = setTimeout(() => {
const msg = `Request to '${method}' timed out after ${seconds} seconds`;
reject(new Error(msg));
controller.abort();
}, 1000 * seconds);
});
return { promise, handle };
}
/** Creates a stream error which abort a given controller */
function createStreamError(abortController) {
let onError = (err) => {
// Re-throw by default, but will be overwritten immediately
throw err;
};
const promise = new Promise((_, reject) => {
onError = (err) => {
reject(err);
abortController.abort();
};
});
return { promise, catch: onError };
}
function createAbortControllerFromSignal(signal) {
const abortController = new shim_node_js_1.AbortController();
if (signal === undefined)
return abortController;
const sig = signal;
function abort() {
abortController.abort();
sig.removeEventListener("abort", abort);
}
if (sig.aborted)
abort();
else
sig.addEventListener("abort", abort);
return { abort, signal: abortController.signal };
}
const shim_node_js_1 = require("../shim.node.js");