@tgify/tgify 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +356 -0
  3. package/filters.d.ts +1 -0
  4. package/filters.js +1 -0
  5. package/format.d.ts +1 -0
  6. package/format.js +1 -0
  7. package/future.d.ts +1 -0
  8. package/future.js +1 -0
  9. package/lib/button.js +100 -0
  10. package/lib/cli.mjs +105 -0
  11. package/lib/composer.js +582 -0
  12. package/lib/context.js +1219 -0
  13. package/lib/core/helpers/args.js +57 -0
  14. package/lib/core/helpers/check.js +55 -0
  15. package/lib/core/helpers/compact.js +16 -0
  16. package/lib/core/helpers/deunionize.js +12 -0
  17. package/lib/core/helpers/formatting.js +91 -0
  18. package/lib/core/helpers/util.js +50 -0
  19. package/lib/core/network/client.js +330 -0
  20. package/lib/core/network/error.js +21 -0
  21. package/lib/core/network/multipart-stream.js +71 -0
  22. package/lib/core/network/polling.js +87 -0
  23. package/lib/core/network/webhook.js +54 -0
  24. package/lib/core/types/typegram.js +27 -0
  25. package/lib/filters.js +69 -0
  26. package/lib/format.js +38 -0
  27. package/lib/future.js +149 -0
  28. package/lib/index.js +58 -0
  29. package/lib/input.js +61 -0
  30. package/lib/markup.js +121 -0
  31. package/lib/middleware.js +2 -0
  32. package/lib/reactions.js +84 -0
  33. package/lib/router.js +46 -0
  34. package/lib/scenes/base.js +39 -0
  35. package/lib/scenes/context.js +104 -0
  36. package/lib/scenes/index.js +21 -0
  37. package/lib/scenes/stage.js +49 -0
  38. package/lib/scenes/wizard/context.js +31 -0
  39. package/lib/scenes/wizard/index.js +45 -0
  40. package/lib/scenes.js +17 -0
  41. package/lib/session.js +166 -0
  42. package/lib/telegraf.js +256 -0
  43. package/lib/telegram-types.js +6 -0
  44. package/lib/telegram.js +1240 -0
  45. package/lib/types.js +2 -0
  46. package/lib/utils.js +5 -0
  47. package/markup.d.ts +1 -0
  48. package/markup.js +1 -0
  49. package/package.json +140 -0
  50. package/scenes.d.ts +1 -0
  51. package/scenes.js +1 -0
  52. package/session.d.ts +1 -0
  53. package/session.js +1 -0
  54. package/src/button.ts +182 -0
  55. package/src/composer.ts +1008 -0
  56. package/src/context.ts +1661 -0
  57. package/src/core/helpers/args.ts +63 -0
  58. package/src/core/helpers/check.ts +71 -0
  59. package/src/core/helpers/compact.ts +18 -0
  60. package/src/core/helpers/deunionize.ts +26 -0
  61. package/src/core/helpers/formatting.ts +119 -0
  62. package/src/core/helpers/util.ts +96 -0
  63. package/src/core/network/client.ts +396 -0
  64. package/src/core/network/error.ts +29 -0
  65. package/src/core/network/multipart-stream.ts +45 -0
  66. package/src/core/network/polling.ts +94 -0
  67. package/src/core/network/webhook.ts +58 -0
  68. package/src/core/types/typegram.ts +54 -0
  69. package/src/filters.ts +109 -0
  70. package/src/format.ts +110 -0
  71. package/src/future.ts +213 -0
  72. package/src/index.ts +17 -0
  73. package/src/input.ts +59 -0
  74. package/src/markup.ts +142 -0
  75. package/src/middleware.ts +24 -0
  76. package/src/reactions.ts +118 -0
  77. package/src/router.ts +55 -0
  78. package/src/scenes/base.ts +52 -0
  79. package/src/scenes/context.ts +136 -0
  80. package/src/scenes/index.ts +21 -0
  81. package/src/scenes/stage.ts +71 -0
  82. package/src/scenes/wizard/context.ts +58 -0
  83. package/src/scenes/wizard/index.ts +63 -0
  84. package/src/scenes.ts +1 -0
  85. package/src/session.ts +204 -0
  86. package/src/telegraf.ts +354 -0
  87. package/src/telegram-types.ts +219 -0
  88. package/src/telegram.ts +1635 -0
  89. package/src/types.ts +2 -0
  90. package/src/utils.ts +1 -0
  91. package/types.d.ts +1 -0
  92. package/types.js +1 -0
  93. package/typings/button.d.ts +36 -0
  94. package/typings/button.d.ts.map +1 -0
  95. package/typings/composer.d.ts +227 -0
  96. package/typings/composer.d.ts.map +1 -0
  97. package/typings/context.d.ts +655 -0
  98. package/typings/context.d.ts.map +1 -0
  99. package/typings/core/helpers/args.d.ts +11 -0
  100. package/typings/core/helpers/args.d.ts.map +1 -0
  101. package/typings/core/helpers/check.d.ts +56 -0
  102. package/typings/core/helpers/check.d.ts.map +1 -0
  103. package/typings/core/helpers/compact.d.ts +4 -0
  104. package/typings/core/helpers/compact.d.ts.map +1 -0
  105. package/typings/core/helpers/deunionize.d.ts +18 -0
  106. package/typings/core/helpers/deunionize.d.ts.map +1 -0
  107. package/typings/core/helpers/formatting.d.ts +30 -0
  108. package/typings/core/helpers/formatting.d.ts.map +1 -0
  109. package/typings/core/helpers/util.d.ts +26 -0
  110. package/typings/core/helpers/util.d.ts.map +1 -0
  111. package/typings/core/network/client.d.ts +53 -0
  112. package/typings/core/network/client.d.ts.map +1 -0
  113. package/typings/core/network/error.d.ts +16 -0
  114. package/typings/core/network/error.d.ts.map +1 -0
  115. package/typings/core/network/multipart-stream.d.ts +16 -0
  116. package/typings/core/network/multipart-stream.d.ts.map +1 -0
  117. package/typings/core/network/polling.d.ts +16 -0
  118. package/typings/core/network/polling.d.ts.map +1 -0
  119. package/typings/core/network/webhook.d.ts +6 -0
  120. package/typings/core/network/webhook.d.ts.map +1 -0
  121. package/typings/core/types/typegram.d.ts +42 -0
  122. package/typings/core/types/typegram.d.ts.map +1 -0
  123. package/typings/filters.d.ts +18 -0
  124. package/typings/filters.d.ts.map +1 -0
  125. package/typings/format.d.ts +22 -0
  126. package/typings/format.d.ts.map +1 -0
  127. package/typings/future.d.ts +12 -0
  128. package/typings/future.d.ts.map +1 -0
  129. package/typings/index.d.ts +15 -0
  130. package/typings/index.d.ts.map +1 -0
  131. package/typings/input.d.ts +50 -0
  132. package/typings/input.d.ts.map +1 -0
  133. package/typings/markup.d.ts +27 -0
  134. package/typings/markup.d.ts.map +1 -0
  135. package/typings/middleware.d.ts +8 -0
  136. package/typings/middleware.d.ts.map +1 -0
  137. package/typings/reactions.d.ts +32 -0
  138. package/typings/reactions.d.ts.map +1 -0
  139. package/typings/router.d.ts +21 -0
  140. package/typings/router.d.ts.map +1 -0
  141. package/typings/scenes/base.d.ts +22 -0
  142. package/typings/scenes/base.d.ts.map +1 -0
  143. package/typings/scenes/context.d.ts +36 -0
  144. package/typings/scenes/context.d.ts.map +1 -0
  145. package/typings/scenes/index.d.ts +11 -0
  146. package/typings/scenes/index.d.ts.map +1 -0
  147. package/typings/scenes/stage.d.ts +24 -0
  148. package/typings/scenes/stage.d.ts.map +1 -0
  149. package/typings/scenes/wizard/context.d.ts +29 -0
  150. package/typings/scenes/wizard/context.d.ts.map +1 -0
  151. package/typings/scenes/wizard/index.d.ts +16 -0
  152. package/typings/scenes/wizard/index.d.ts.map +1 -0
  153. package/typings/scenes.d.ts +2 -0
  154. package/typings/scenes.d.ts.map +1 -0
  155. package/typings/session.d.ts +55 -0
  156. package/typings/session.d.ts.map +1 -0
  157. package/typings/telegraf.d.ts +115 -0
  158. package/typings/telegraf.d.ts.map +1 -0
  159. package/typings/telegram-types.d.ts +117 -0
  160. package/typings/telegram-types.d.ts.map +1 -0
  161. package/typings/telegram.d.ts +675 -0
  162. package/typings/telegram.d.ts.map +1 -0
  163. package/typings/types.d.ts +3 -0
  164. package/typings/types.d.ts.map +1 -0
  165. package/typings/utils.d.ts +2 -0
  166. package/typings/utils.d.ts.map +1 -0
  167. package/utils.d.ts +1 -0
  168. package/utils.js +1 -0
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.argsParser = argsParser;
4
+ const SINGLE_QUOTE = "'";
5
+ const DOUBLE_QUOTE = '"';
6
+ function argsParser(str, entities = [], entityOffset = 0) {
7
+ const mentions = {};
8
+ for (const entity of entities) // extract all text_mentions into an { offset: length } map
9
+ if (entity.type === 'text_mention' || entity.type === 'text_link')
10
+ mentions[entity.offset - entityOffset] = entity.length;
11
+ const args = [];
12
+ let done = 0;
13
+ let inside = undefined;
14
+ let buf = '';
15
+ function flush(to) {
16
+ if (done !== to)
17
+ args.push(buf + str.slice(done, to)), (inside = undefined);
18
+ buf = '';
19
+ done = to + 1;
20
+ }
21
+ for (let i = 0; i < str.length; i++) {
22
+ const char = str[i];
23
+ // quick lookup length of mention starting at i
24
+ const mention = mentions[i];
25
+ if (mention) {
26
+ // if we're inside a quote, eagerly flush existing state
27
+ flush(i);
28
+ // this also consumes current index, so decrement
29
+ done--;
30
+ // fast forward to end of mention
31
+ i += mention;
32
+ flush(i);
33
+ }
34
+ else if (char === SINGLE_QUOTE || char === DOUBLE_QUOTE)
35
+ if (inside)
36
+ if (inside === char)
37
+ flush(i);
38
+ else
39
+ continue;
40
+ else
41
+ flush(i), (inside = char);
42
+ else if (char === ' ')
43
+ if (inside)
44
+ continue;
45
+ else
46
+ flush(i);
47
+ else if (char === '\n')
48
+ flush(i);
49
+ else if (char === '\\')
50
+ (buf += str.slice(done, i)), (done = ++i); // skip parsing the next char
51
+ else
52
+ continue;
53
+ }
54
+ if (done < str.length)
55
+ flush(str.length);
56
+ return args;
57
+ }
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.hasProp = hasProp;
4
+ exports.hasPropType = hasPropType;
5
+ exports.is2D = is2D;
6
+ /**
7
+ * Checks if a given object has a property with a given name.
8
+ *
9
+ * Example invocation:
10
+ * ```js
11
+ * let obj = { 'foo': 'bar', 'baz': () => {} }
12
+ * hasProp(obj, 'foo') // true
13
+ * hasProp(obj, 'baz') // true
14
+ * hasProp(obj, 'abc') // false
15
+ * ```
16
+ *
17
+ * @param obj An object to test
18
+ * @param prop The name of the property
19
+ */
20
+ function hasProp(obj, prop) {
21
+ return obj !== undefined && prop in obj;
22
+ }
23
+ /**
24
+ * Checks if a given object has a property with a given name.
25
+ * Furthermore performs a `typeof` check on the property if it exists.
26
+ *
27
+ * Example invocation:
28
+ * ```js
29
+ * let obj = { 'foo': 'bar', 'baz': () => {} }
30
+ * hasPropType(obj, 'foo', 'string') // true
31
+ * hasPropType(obj, 'baz', 'function') // true
32
+ * hasPropType(obj, 'abc', 'number') // false
33
+ * ```
34
+ *
35
+ * @param obj An object to test
36
+ * @param prop The name of the property
37
+ * @param type The type the property is expected to have
38
+ */
39
+ function hasPropType(obj, prop, type) {
40
+ return hasProp(obj, prop) && type === typeof obj[prop];
41
+ }
42
+ /**
43
+ * Checks if the supplied array has two dimensions or not.
44
+ *
45
+ * Example invocations:
46
+ * is2D([]) // false
47
+ * is2D([[]]) // true
48
+ * is2D([[], []]) // true
49
+ * is2D([42]) // false
50
+ *
51
+ * @param arr an array with one or two dimensions
52
+ */
53
+ function is2D(arr) {
54
+ return Array.isArray(arr[0]);
55
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.compactOptions = compactOptions;
4
+ function compactOptions(options) {
5
+ if (!options) {
6
+ return options;
7
+ }
8
+ const compacted = {};
9
+ for (const key in options)
10
+ if (
11
+ // todo(mkr): replace with Object.hasOwn in v5 (Node 16+)
12
+ Object.prototype.hasOwnProperty.call(options, key) &&
13
+ options[key] !== undefined)
14
+ compacted[key] = options[key];
15
+ return compacted;
16
+ }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deunionize = deunionize;
4
+ /**
5
+ * Expose properties from all union variants.
6
+ * @deprectated
7
+ * @see https://github.com/telegraf/telegraf/issues/1388#issuecomment-791573609
8
+ * @see https://millsp.github.io/ts-toolbelt/modules/union_strict.html
9
+ */
10
+ function deunionize(t) {
11
+ return t;
12
+ }
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.linkOrMention = exports.join = exports.FmtString = void 0;
4
+ exports.createFmt = createFmt;
5
+ const util_1 = require("./util");
6
+ class FmtString {
7
+ constructor(text, entities) {
8
+ this.text = text;
9
+ if (entities) {
10
+ this.entities = entities;
11
+ // force parse_mode to undefined if entities are present
12
+ this.parse_mode = undefined;
13
+ }
14
+ }
15
+ static normalise(content) {
16
+ if (content instanceof FmtString)
17
+ return content;
18
+ return new FmtString(String(content));
19
+ }
20
+ }
21
+ exports.FmtString = FmtString;
22
+ const isArray = Array.isArray;
23
+ /** Given a base FmtString and something to append to it, mutates the base */
24
+ const _add = (base, next) => {
25
+ var _a;
26
+ const len = base.text.length;
27
+ if (next instanceof FmtString) {
28
+ base.text = `${base.text}${next.text}`;
29
+ // next.entities could be undefined and condition will fail
30
+ for (let i = 0; i < (((_a = next.entities) === null || _a === void 0 ? void 0 : _a.length) || 0); i++) {
31
+ // because of the above condition, next.entities[i] cannot be undefined
32
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
33
+ const entity = next.entities[i];
34
+ // base.entities is ensured by caller
35
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
36
+ base.entities.push({ ...entity, offset: entity.offset + len });
37
+ }
38
+ }
39
+ else
40
+ base.text = `${base.text}${next}`;
41
+ };
42
+ /**
43
+ * Given an `Iterable<FmtString | string | Any>` and a separator, flattens the list into a single FmtString.
44
+ * Analogous to Array#join -> string, but for FmtString
45
+ */
46
+ const join = (fragments, separator) => {
47
+ const result = new FmtString('');
48
+ // ensure entities array so loop doesn't need to check
49
+ result.entities = [];
50
+ const iter = fragments[Symbol.iterator]();
51
+ let curr = iter.next();
52
+ while (!curr.done) {
53
+ _add(result, curr.value);
54
+ curr = iter.next();
55
+ if (separator && !curr.done)
56
+ _add(result, separator);
57
+ }
58
+ // set parse_mode: undefined if entities are present
59
+ if (result.entities.length)
60
+ result.parse_mode = undefined;
61
+ // remove entities array if not relevant
62
+ else
63
+ delete result.entities;
64
+ return result;
65
+ };
66
+ exports.join = join;
67
+ /** Internal constructor for all fmt helpers */
68
+ function createFmt(kind, opts) {
69
+ return function fmt(parts, ...items) {
70
+ var _a;
71
+ parts = isArray(parts) ? parts : [parts];
72
+ const result = (0, exports.join)((0, util_1.zip)(parts, items));
73
+ if (kind) {
74
+ (_a = result.entities) !== null && _a !== void 0 ? _a : (result.entities = []);
75
+ result.entities.unshift({
76
+ type: kind,
77
+ offset: 0,
78
+ length: result.text.length,
79
+ ...opts,
80
+ });
81
+ result.parse_mode = undefined;
82
+ }
83
+ return result;
84
+ };
85
+ }
86
+ const linkOrMention = (content, data) => {
87
+ const { text, entities = [] } = FmtString.normalise(content);
88
+ entities.unshift(Object.assign(data, { offset: 0, length: text.length }));
89
+ return new FmtString(text, entities);
90
+ };
91
+ exports.linkOrMention = linkOrMention;
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.env = void 0;
4
+ exports.fmtCaption = fmtCaption;
5
+ exports.zip = zip;
6
+ exports.indexed = indexed;
7
+ exports.env = process.env;
8
+ function fmtCaption(extra) {
9
+ if (!extra)
10
+ return;
11
+ const caption = extra.caption;
12
+ if (!caption || typeof caption === 'string')
13
+ return extra;
14
+ const { text, entities } = caption;
15
+ return {
16
+ ...extra,
17
+ caption: text,
18
+ ...(entities && {
19
+ caption_entities: entities,
20
+ parse_mode: undefined,
21
+ }),
22
+ };
23
+ }
24
+ function* zip(xs, ys) {
25
+ const x = xs[Symbol.iterator]();
26
+ const y = ys[Symbol.iterator]();
27
+ let x1 = x.next();
28
+ let y1 = y.next();
29
+ while (!x1.done) {
30
+ yield x1.value;
31
+ if (!y1.done)
32
+ yield y1.value;
33
+ x1 = x.next();
34
+ y1 = y.next();
35
+ }
36
+ while (!y1.done) {
37
+ yield y1.value;
38
+ y1 = y.next();
39
+ }
40
+ }
41
+ function indexed(target, indexer) {
42
+ return new Proxy(target, {
43
+ get: function (target, prop, receiver) {
44
+ if ((typeof prop === 'string' || typeof prop === 'number') &&
45
+ !isNaN(+prop))
46
+ return indexer.call(target, +prop);
47
+ return Reflect.get(target, prop, receiver);
48
+ },
49
+ });
50
+ }
@@ -0,0 +1,330 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ /* eslint @typescript-eslint/restrict-template-expressions: [ "error", { "allowNumber": true, "allowBoolean": true } ] */
40
+ const crypto = __importStar(require("crypto"));
41
+ const fs = __importStar(require("fs"));
42
+ const promises_1 = require("fs/promises");
43
+ const https = __importStar(require("https"));
44
+ const path = __importStar(require("path"));
45
+ const node_fetch_1 = __importDefault(require("node-fetch"));
46
+ const check_1 = require("../helpers/check");
47
+ const compact_1 = require("../helpers/compact");
48
+ const multipart_stream_1 = __importDefault(require("./multipart-stream"));
49
+ const error_1 = __importDefault(require("./error"));
50
+ const url_1 = require("url");
51
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
52
+ const debug = require('debug')('telegraf:client');
53
+ const { isStream } = multipart_stream_1.default;
54
+ const WEBHOOK_REPLY_METHOD_ALLOWLIST = new Set([
55
+ 'answerCallbackQuery',
56
+ 'answerInlineQuery',
57
+ 'deleteMessage',
58
+ 'leaveChat',
59
+ 'sendChatAction',
60
+ ]);
61
+ const DEFAULT_EXTENSIONS = {
62
+ audio: 'mp3',
63
+ photo: 'jpg',
64
+ sticker: 'webp',
65
+ video: 'mp4',
66
+ animation: 'mp4',
67
+ video_note: 'mp4',
68
+ voice: 'ogg',
69
+ };
70
+ const DEFAULT_OPTIONS = {
71
+ apiRoot: 'https://api.telegram.org',
72
+ apiMode: 'bot',
73
+ webhookReply: true,
74
+ agent: new https.Agent({
75
+ keepAlive: true,
76
+ keepAliveMsecs: 10000,
77
+ }),
78
+ attachmentAgent: undefined,
79
+ testEnv: false,
80
+ };
81
+ function includesMedia(payload) {
82
+ return Object.entries(payload).some(([key, value]) => {
83
+ if (key === 'link_preview_options')
84
+ return false;
85
+ if (Array.isArray(value)) {
86
+ return value.some(({ media }) => media && typeof media === 'object' && (media.source || media.url));
87
+ }
88
+ return (value &&
89
+ typeof value === 'object' &&
90
+ (((0, check_1.hasProp)(value, 'source') && value.source) ||
91
+ ((0, check_1.hasProp)(value, 'url') && value.url) ||
92
+ ((0, check_1.hasPropType)(value, 'media', 'object') &&
93
+ (((0, check_1.hasProp)(value.media, 'source') && value.media.source) ||
94
+ ((0, check_1.hasProp)(value.media, 'url') && value.media.url)))));
95
+ });
96
+ }
97
+ function replacer(_, value) {
98
+ if (value == null)
99
+ return undefined;
100
+ return value;
101
+ }
102
+ function buildJSONConfig(payload) {
103
+ return Promise.resolve({
104
+ method: 'POST',
105
+ compress: true,
106
+ headers: { 'content-type': 'application/json', connection: 'keep-alive' },
107
+ body: JSON.stringify(payload, replacer),
108
+ });
109
+ }
110
+ const FORM_DATA_JSON_FIELDS = [
111
+ 'results',
112
+ 'reply_markup',
113
+ 'mask_position',
114
+ 'shipping_options',
115
+ 'errors',
116
+ ];
117
+ async function buildFormDataConfig(payload, agent) {
118
+ for (const field of FORM_DATA_JSON_FIELDS) {
119
+ if ((0, check_1.hasProp)(payload, field) && typeof payload[field] !== 'string') {
120
+ payload[field] = JSON.stringify(payload[field]);
121
+ }
122
+ }
123
+ const boundary = crypto.randomBytes(32).toString('hex');
124
+ const formData = new multipart_stream_1.default(boundary);
125
+ await Promise.all(Object.keys(payload).map((key) =>
126
+ // @ts-expect-error payload[key] can obviously index payload, but TS doesn't trust us
127
+ attachFormValue(formData, key, payload[key], agent)));
128
+ return {
129
+ method: 'POST',
130
+ compress: true,
131
+ headers: {
132
+ 'content-type': `multipart/form-data; boundary=${boundary}`,
133
+ connection: 'keep-alive',
134
+ },
135
+ body: formData,
136
+ };
137
+ }
138
+ async function attachFormValue(form, id, value, agent) {
139
+ if (value == null) {
140
+ return;
141
+ }
142
+ if (typeof value === 'string' ||
143
+ typeof value === 'boolean' ||
144
+ typeof value === 'number') {
145
+ form.addPart({
146
+ headers: { 'content-disposition': `form-data; name="${id}"` },
147
+ body: `${value}`,
148
+ });
149
+ return;
150
+ }
151
+ if (id === 'thumb' || id === 'thumbnail') {
152
+ const attachmentId = crypto.randomBytes(16).toString('hex');
153
+ await attachFormMedia(form, value, attachmentId, agent);
154
+ return form.addPart({
155
+ headers: { 'content-disposition': `form-data; name="${id}"` },
156
+ body: `attach://${attachmentId}`,
157
+ });
158
+ }
159
+ if (Array.isArray(value)) {
160
+ const items = await Promise.all(value.map(async (item) => {
161
+ var _a;
162
+ if (typeof item.media !== 'object') {
163
+ return await Promise.resolve(item);
164
+ }
165
+ const attachmentId = crypto.randomBytes(16).toString('hex');
166
+ await attachFormMedia(form, item.media, attachmentId, agent);
167
+ const thumb = (_a = item.thumb) !== null && _a !== void 0 ? _a : item.thumbnail;
168
+ if (typeof thumb === 'object') {
169
+ const thumbAttachmentId = crypto.randomBytes(16).toString('hex');
170
+ await attachFormMedia(form, thumb, thumbAttachmentId, agent);
171
+ return {
172
+ ...item,
173
+ media: `attach://${attachmentId}`,
174
+ thumbnail: `attach://${thumbAttachmentId}`,
175
+ };
176
+ }
177
+ return { ...item, media: `attach://${attachmentId}` };
178
+ }));
179
+ return form.addPart({
180
+ headers: { 'content-disposition': `form-data; name="${id}"` },
181
+ body: JSON.stringify(items),
182
+ });
183
+ }
184
+ if (value &&
185
+ typeof value === 'object' &&
186
+ (0, check_1.hasProp)(value, 'media') &&
187
+ (0, check_1.hasProp)(value, 'type') &&
188
+ typeof value.media !== 'undefined' &&
189
+ typeof value.type !== 'undefined') {
190
+ const attachmentId = crypto.randomBytes(16).toString('hex');
191
+ await attachFormMedia(form, value.media, attachmentId, agent);
192
+ return form.addPart({
193
+ headers: { 'content-disposition': `form-data; name="${id}"` },
194
+ body: JSON.stringify({
195
+ ...value,
196
+ media: `attach://${attachmentId}`,
197
+ }),
198
+ });
199
+ }
200
+ return await attachFormMedia(form, value, id, agent);
201
+ }
202
+ async function attachFormMedia(form, media, id, agent) {
203
+ var _a, _b, _c;
204
+ let fileName = (_a = media.filename) !== null && _a !== void 0 ? _a : `${id}.${(_b = DEFAULT_EXTENSIONS[id]) !== null && _b !== void 0 ? _b : 'dat'}`;
205
+ if ('url' in media && media.url !== undefined) {
206
+ const timeout = 500000; // ms
207
+ const res = await (0, node_fetch_1.default)(media.url, { agent, timeout });
208
+ return form.addPart({
209
+ headers: {
210
+ 'content-disposition': `form-data; name="${id}"; filename="${fileName}"`,
211
+ },
212
+ body: res.body,
213
+ });
214
+ }
215
+ if ('source' in media && media.source) {
216
+ let mediaSource = media.source;
217
+ if (typeof media.source === 'string') {
218
+ const source = await (0, promises_1.realpath)(media.source);
219
+ if ((await (0, promises_1.stat)(source)).isFile()) {
220
+ fileName = (_c = media.filename) !== null && _c !== void 0 ? _c : path.basename(media.source);
221
+ mediaSource = await fs.createReadStream(media.source);
222
+ }
223
+ else {
224
+ throw new TypeError(`Unable to upload '${media.source}', not a file`);
225
+ }
226
+ }
227
+ if (isStream(mediaSource) || Buffer.isBuffer(mediaSource)) {
228
+ form.addPart({
229
+ headers: {
230
+ 'content-disposition': `form-data; name="${id}"; filename="${fileName}"`,
231
+ },
232
+ body: mediaSource,
233
+ });
234
+ }
235
+ }
236
+ }
237
+ async function answerToWebhook(response, payload, options) {
238
+ if (!includesMedia(payload)) {
239
+ if (!response.headersSent) {
240
+ response.setHeader('content-type', 'application/json');
241
+ }
242
+ response.end(JSON.stringify(payload), 'utf-8');
243
+ return true;
244
+ }
245
+ const { headers, body } = await buildFormDataConfig(payload, options.attachmentAgent);
246
+ if (!response.headersSent) {
247
+ for (const [key, value] of Object.entries(headers)) {
248
+ response.setHeader(key, value);
249
+ }
250
+ }
251
+ await new Promise((resolve) => {
252
+ response.on('finish', resolve);
253
+ body.pipe(response);
254
+ });
255
+ return true;
256
+ }
257
+ function redactToken(error) {
258
+ error.message = error.message.replace(/\/(bot|user)(\d+):[^/]+\//, '/$1$2:[REDACTED]/');
259
+ throw error;
260
+ }
261
+ class ApiClient {
262
+ constructor(token, options, response) {
263
+ this.token = token;
264
+ this.response = response;
265
+ this.options = {
266
+ ...DEFAULT_OPTIONS,
267
+ ...(0, compact_1.compactOptions)(options),
268
+ };
269
+ if (this.options.apiRoot.startsWith('http://')) {
270
+ this.options.agent = undefined;
271
+ }
272
+ }
273
+ /**
274
+ * If set to `true`, first _eligible_ call will avoid performing a POST request.
275
+ * Note that such a call:
276
+ * 1. cannot report errors or return meaningful values,
277
+ * 2. resolves before bot API has a chance to process it,
278
+ * 3. prematurely confirms the update as processed.
279
+ *
280
+ * https://core.telegram.org/bots/faq#how-can-i-make-requests-in-response-to-updates
281
+ * https://github.com/telegraf/telegraf/pull/1250
282
+ */
283
+ set webhookReply(enable) {
284
+ this.options.webhookReply = enable;
285
+ }
286
+ get webhookReply() {
287
+ return this.options.webhookReply;
288
+ }
289
+ async callApi(method, payload, { signal } = {}) {
290
+ const { token, options, response } = this;
291
+ if (options.webhookReply &&
292
+ (response === null || response === void 0 ? void 0 : response.writableEnded) === false &&
293
+ WEBHOOK_REPLY_METHOD_ALLOWLIST.has(method)) {
294
+ debug('Call via webhook', method, payload);
295
+ // @ts-expect-error using webhookReply is an optimisation that doesn't respond with normal result
296
+ // up to the user to deal with this
297
+ return await answerToWebhook(response, { method, ...payload }, options);
298
+ }
299
+ if (!token) {
300
+ throw new error_1.default({
301
+ error_code: 401,
302
+ description: 'Bot Token is required',
303
+ });
304
+ }
305
+ debug('HTTP call', method, payload);
306
+ const config = includesMedia(payload)
307
+ ? await buildFormDataConfig({ method, ...payload }, options.attachmentAgent)
308
+ : await buildJSONConfig(payload);
309
+ const apiUrl = new url_1.URL(`./${options.apiMode}${token}${options.testEnv ? '/test' : ''}/${method}`, options.apiRoot);
310
+ config.agent = options.agent;
311
+ // @ts-expect-error AbortSignal shim is missing some props from Request.AbortSignal
312
+ config.signal = signal;
313
+ config.timeout = 500000; // ms
314
+ const res = await (0, node_fetch_1.default)(apiUrl, config).catch(redactToken);
315
+ if (res.status >= 500) {
316
+ const errorPayload = {
317
+ error_code: res.status,
318
+ description: res.statusText,
319
+ };
320
+ throw new error_1.default(errorPayload, { method, payload });
321
+ }
322
+ const data = await res.json();
323
+ if (!data.ok) {
324
+ debug('API call failed', data);
325
+ throw new error_1.default(data, { method, payload });
326
+ }
327
+ return data.result;
328
+ }
329
+ }
330
+ exports.default = ApiClient;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TelegramError = void 0;
4
+ class TelegramError extends Error {
5
+ constructor(response, on = {}) {
6
+ super(`${response.error_code}: ${response.description}`);
7
+ this.response = response;
8
+ this.on = on;
9
+ }
10
+ get code() {
11
+ return this.response.error_code;
12
+ }
13
+ get description() {
14
+ return this.response.description;
15
+ }
16
+ get parameters() {
17
+ return this.response.parameters;
18
+ }
19
+ }
20
+ exports.TelegramError = TelegramError;
21
+ exports.default = TelegramError;