@mtkruto/node 0.1.157 → 0.1.160
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.
- package/esm/4_constants.d.ts +2 -2
- package/esm/4_constants.js +2 -2
- package/esm/client/1_composer.d.ts +2 -2
- package/esm/client/1_composer.js +4 -4
- package/esm/client/1_file_manager.js +53 -56
- package/esm/client/2_message_manager.js +8 -11
- package/esm/client/4_client.d.ts +2 -2
- package/esm/client/4_client.js +4 -4
- package/esm/tl/2_types.d.ts +596 -1
- package/esm/tl/2_types.js +1824 -319
- package/esm/tl/3_functions.d.ts +374 -2
- package/esm/tl/3_functions.js +943 -31
- package/esm/types/0__file_id.d.ts +79 -54
- package/esm/types/0__file_id.js +259 -277
- package/esm/types/0_chat_photo.js +15 -21
- package/esm/types/0_giveaway_parameters.d.ts +5 -0
- package/esm/types/0_login_url.d.ts +4 -0
- package/esm/types/0_message_reference.d.ts +2 -0
- package/esm/types/0_price_tag.d.ts +2 -0
- package/esm/types/0_thumbnail.js +16 -14
- package/esm/types/1_giveaway.d.ts +2 -0
- package/esm/types/1_inline_query_result_button.d.ts +3 -0
- package/esm/types/1_photo.js +20 -14
- package/esm/types/1_poll.d.ts +13 -0
- package/esm/types/1_reaction_count.d.ts +2 -0
- package/esm/types/1_reply_quote.d.ts +3 -0
- package/esm/types/1_user.d.ts +13 -13
- package/esm/types/2_chosen_inline_result.d.ts +5 -0
- package/esm/types/2_game.d.ts +6 -0
- package/esm/types/2_game.js +11 -7
- package/esm/types/2_inactive_chat.d.ts +3 -0
- package/esm/types/2_inline_query.d.ts +6 -0
- package/esm/types/2_message_interactions.d.ts +5 -0
- package/esm/types/2_message_reaction_count.d.ts +4 -0
- package/esm/types/2_message_reactions.d.ts +7 -0
- package/esm/types/2_story_content.js +4 -7
- package/esm/types/4_inline_query_result.js +5 -5
- package/esm/types/4_message.js +21 -17
- package/esm/types/5_callback_query.d.ts +7 -0
- package/esm/utilities/0_buffer.d.ts +1 -1
- package/esm/utilities/0_buffer.js +26 -24
- package/package.json +1 -1
- package/script/4_constants.d.ts +2 -2
- package/script/4_constants.js +2 -2
- package/script/client/1_composer.d.ts +2 -2
- package/script/client/1_composer.js +4 -4
- package/script/client/1_file_manager.js +52 -55
- package/script/client/2_message_manager.js +6 -9
- package/script/client/4_client.d.ts +2 -2
- package/script/client/4_client.js +4 -4
- package/script/tl/2_types.d.ts +596 -1
- package/script/tl/2_types.js +1904 -345
- package/script/tl/3_functions.d.ts +374 -2
- package/script/tl/3_functions.js +977 -41
- package/script/types/0__file_id.d.ts +79 -54
- package/script/types/0__file_id.js +263 -280
- package/script/types/0_chat_photo.js +14 -20
- package/script/types/0_giveaway_parameters.d.ts +5 -0
- package/script/types/0_login_url.d.ts +4 -0
- package/script/types/0_message_reference.d.ts +2 -0
- package/script/types/0_price_tag.d.ts +2 -0
- package/script/types/0_thumbnail.js +15 -13
- package/script/types/1_giveaway.d.ts +2 -0
- package/script/types/1_inline_query_result_button.d.ts +3 -0
- package/script/types/1_photo.js +19 -13
- package/script/types/1_poll.d.ts +13 -0
- package/script/types/1_reaction_count.d.ts +2 -0
- package/script/types/1_reply_quote.d.ts +3 -0
- package/script/types/1_user.d.ts +13 -13
- package/script/types/2_chosen_inline_result.d.ts +5 -0
- package/script/types/2_game.d.ts +6 -0
- package/script/types/2_game.js +10 -6
- package/script/types/2_inactive_chat.d.ts +3 -0
- package/script/types/2_inline_query.d.ts +6 -0
- package/script/types/2_message_interactions.d.ts +5 -0
- package/script/types/2_message_reaction_count.d.ts +4 -0
- package/script/types/2_message_reactions.d.ts +7 -0
- package/script/types/2_story_content.js +3 -6
- package/script/types/4_inline_query_result.js +4 -4
- package/script/types/4_message.js +20 -16
- package/script/types/5_callback_query.d.ts +7 -0
- package/script/utilities/0_buffer.d.ts +1 -1
- package/script/utilities/0_buffer.js +26 -24
package/esm/4_constants.d.ts
CHANGED
|
@@ -3,8 +3,8 @@ export declare const ACK_THRESHOLD = 10;
|
|
|
3
3
|
export type PublicKeys = readonly [bigint, [bigint, bigint]][];
|
|
4
4
|
export declare const PUBLIC_KEYS: PublicKeys;
|
|
5
5
|
export declare const INITIAL_DC: DC;
|
|
6
|
-
export declare const LAYER =
|
|
7
|
-
export declare const APP_VERSION = "MTKruto 0.1.
|
|
6
|
+
export declare const LAYER = 176;
|
|
7
|
+
export declare const APP_VERSION = "MTKruto 0.1.160";
|
|
8
8
|
export declare const DEVICE_MODEL: string;
|
|
9
9
|
export declare const LANG_CODE: string;
|
|
10
10
|
export declare const LANG_PACK = "";
|
package/esm/4_constants.js
CHANGED
|
@@ -52,8 +52,8 @@ export const PUBLIC_KEYS = Object.freeze([
|
|
|
52
52
|
],
|
|
53
53
|
]);
|
|
54
54
|
export const INITIAL_DC = "2";
|
|
55
|
-
export const LAYER =
|
|
56
|
-
export const APP_VERSION = "MTKruto 0.1.
|
|
55
|
+
export const LAYER = 176;
|
|
56
|
+
export const APP_VERSION = "MTKruto 0.1.160";
|
|
57
57
|
// @ts-ignore: lib
|
|
58
58
|
export const DEVICE_MODEL = typeof dntShim.Deno === "undefined" ? typeof navigator === "undefined" ? typeof process === "undefined" ? "Unknown" : process.platform + "-" + process.arch : navigator.userAgent.split(" ")[0] : dntShim.Deno.build.os + "-" + dntShim.Deno.build.arch;
|
|
59
59
|
export const LANG_CODE = typeof navigator === "undefined" || typeof navigator.language !== "string" ? "en" : navigator.language.split("-")[0];
|
|
@@ -21,10 +21,10 @@ export declare class Composer<C extends {
|
|
|
21
21
|
branch(predicate: (ctx: UpdateIntersection<C>) => MaybePromise<boolean>, trueHandler_: Middleware<UpdateIntersection<C>>, falseHandler_: Middleware<UpdateIntersection<C>>): Composer<C>;
|
|
22
22
|
filter<D extends C>(predicate: (ctx: UpdateIntersection<C>) => ctx is D, ...middleware: Middleware<D>[]): Composer<D>;
|
|
23
23
|
filter(predicate: (ctx: UpdateIntersection<C>) => MaybePromise<boolean>, ...middleware: Middleware<UpdateIntersection<C>>[]): Composer<C>;
|
|
24
|
-
on<Q extends FilterQuery>(filter: Q, ...
|
|
24
|
+
on<Q extends FilterQuery>(filter: Q, ...middleware: Middleware<WithFilter<C, Q>>[]): Composer<UpdateIntersection<WithFilter<C, Q>>>;
|
|
25
25
|
command(commands: string | RegExp | (string | RegExp)[] | {
|
|
26
26
|
names: string | RegExp | (string | RegExp)[];
|
|
27
27
|
prefixes: string | string[];
|
|
28
|
-
}, ...
|
|
28
|
+
}, ...middleware: Middleware<WithFilter<C, "message:text">>[]): Composer<WithFilter<C, "message:text">>;
|
|
29
29
|
}
|
|
30
30
|
export {};
|
package/esm/client/1_composer.js
CHANGED
|
@@ -68,12 +68,12 @@ export class Composer {
|
|
|
68
68
|
this.branch(predicate, composer, skip);
|
|
69
69
|
return composer;
|
|
70
70
|
}
|
|
71
|
-
on(filter, ...
|
|
71
|
+
on(filter, ...middleware) {
|
|
72
72
|
return this.filter((ctx) => {
|
|
73
73
|
return match(filter, ctx);
|
|
74
|
-
}, ...
|
|
74
|
+
}, ...middleware);
|
|
75
75
|
}
|
|
76
|
-
command(commands, ...
|
|
76
|
+
command(commands, ...middleware) {
|
|
77
77
|
const commands__ = typeof commands === "object" && "names" in commands ? commands.names : commands;
|
|
78
78
|
const commands_ = Array.isArray(commands__) ? commands__ : [commands__];
|
|
79
79
|
const prefixes_ = typeof commands === "object" && "prefixes" in commands ? commands.prefixes : (__classPrivateFieldGet(this, _Composer_prefixes, "f") ?? []);
|
|
@@ -114,7 +114,7 @@ export class Composer {
|
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
return false;
|
|
117
|
-
}, ...
|
|
117
|
+
}, ...middleware);
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
_Composer_handle = new WeakMap(), _Composer_prefixes = new WeakMap();
|
|
@@ -13,7 +13,7 @@ var _FileManager_instances, _FileManager_c, _FileManager_Lupload, _FileManager_d
|
|
|
13
13
|
import { extension } from "../0_deps.js";
|
|
14
14
|
import { drop, getLogger, getRandomId, mod, UNREACHABLE } from "../1_utilities.js";
|
|
15
15
|
import { as, types } from "../2_tl.js";
|
|
16
|
-
import { constructDocument,
|
|
16
|
+
import { constructDocument, deserializeFileId, FileType, PhotoSourceType, serializeFileId, toUniqueFileId } from "../3_types.js";
|
|
17
17
|
import { FloodWait } from "../4_errors.js";
|
|
18
18
|
import { ConnectionError } from "./0_types.js";
|
|
19
19
|
export class FileManager {
|
|
@@ -99,55 +99,48 @@ export class FileManager {
|
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
async *download(fileId, params) {
|
|
102
|
-
const fileId_ =
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
102
|
+
const fileId_ = deserializeFileId(fileId);
|
|
103
|
+
if (fileId_.location.type == "photo") {
|
|
104
|
+
switch (fileId_.type) {
|
|
105
|
+
case FileType.ProfilePhoto: {
|
|
106
|
+
if (fileId_.location.source.type != PhotoSourceType.ChatPhotoBig && fileId_.location.source.type != PhotoSourceType.ChatPhotoSmall) {
|
|
107
|
+
UNREACHABLE();
|
|
108
|
+
}
|
|
109
|
+
const big = fileId_.location.source.type == PhotoSourceType.ChatPhotoBig;
|
|
110
|
+
const peer = await __classPrivateFieldGet(this, _FileManager_c, "f").getInputPeer(Number(fileId_.location.source.chatId)); // TODO: use access hash from source?
|
|
111
|
+
const location = new types.InputPeerPhotoFileLocation({ big: big ? true : undefined, peer, photo_id: fileId_.location.id });
|
|
112
|
+
for await (const chunk of __classPrivateFieldGet(this, _FileManager_instances, "m", _FileManager_downloadInner).call(this, location, fileId_.dcId, params)) {
|
|
113
|
+
yield chunk;
|
|
114
|
+
}
|
|
115
|
+
break;
|
|
116
116
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
117
|
+
case FileType.Photo: {
|
|
118
|
+
const location = new types.InputPhotoFileLocation({
|
|
119
|
+
id: fileId_.location.id,
|
|
120
|
+
access_hash: fileId_.location.accessHash,
|
|
121
|
+
file_reference: fileId_.fileReference ?? new Uint8Array(),
|
|
122
|
+
thumb_size: "thumbnailType" in fileId_.location.source ? String.fromCharCode(fileId_.location.source.thumbnailType) : "",
|
|
123
|
+
});
|
|
124
|
+
for await (const chunk of __classPrivateFieldGet(this, _FileManager_instances, "m", _FileManager_downloadInner).call(this, location, fileId_.dcId, params)) {
|
|
125
|
+
yield chunk;
|
|
126
|
+
}
|
|
127
|
+
break;
|
|
125
128
|
}
|
|
126
|
-
break;
|
|
127
129
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
const location = new types.InputDocumentFileLocation({
|
|
139
|
-
id: fileId_.params.mediaId,
|
|
140
|
-
access_hash: fileId_.params.accessHash,
|
|
141
|
-
file_reference: fileId_.params.fileReference,
|
|
142
|
-
thumb_size: fileId_.params.thumbnailSize,
|
|
143
|
-
});
|
|
144
|
-
for await (const chunk of __classPrivateFieldGet(this, _FileManager_instances, "m", _FileManager_downloadInner).call(this, location, fileId_.dcId, params)) {
|
|
145
|
-
yield chunk;
|
|
146
|
-
}
|
|
147
|
-
break;
|
|
130
|
+
}
|
|
131
|
+
else if (fileId_.location.type == "common") {
|
|
132
|
+
const location = new types.InputDocumentFileLocation({
|
|
133
|
+
id: fileId_.location.id,
|
|
134
|
+
access_hash: fileId_.location.accessHash,
|
|
135
|
+
file_reference: fileId_.fileReference ?? new Uint8Array(),
|
|
136
|
+
thumb_size: "", // TODO?
|
|
137
|
+
});
|
|
138
|
+
for await (const chunk of __classPrivateFieldGet(this, _FileManager_instances, "m", _FileManager_downloadInner).call(this, location, fileId_.dcId, params)) {
|
|
139
|
+
yield chunk;
|
|
148
140
|
}
|
|
149
|
-
|
|
150
|
-
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
UNREACHABLE();
|
|
151
144
|
}
|
|
152
145
|
}
|
|
153
146
|
async getCustomEmojiDocuments(id) {
|
|
@@ -161,12 +154,14 @@ export class FileManager {
|
|
|
161
154
|
const maybeDocument = await __classPrivateFieldGet(this, _FileManager_c, "f").messageStorage.getCustomEmojiDocument(BigInt(id_));
|
|
162
155
|
if (maybeDocument != null && Date.now() - maybeDocument[1].getTime() <= 30 * 60 * 1000) {
|
|
163
156
|
const document_ = maybeDocument[0];
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
accessHash: document_.access_hash,
|
|
157
|
+
const fileId_ = {
|
|
158
|
+
type: FileType.Document,
|
|
159
|
+
dcId: document_.dc_id,
|
|
168
160
|
fileReference: document_.file_reference,
|
|
169
|
-
|
|
161
|
+
location: { type: "common", id: document_.id, accessHash: document_.access_hash },
|
|
162
|
+
};
|
|
163
|
+
const fileUniqueId = toUniqueFileId(fileId_);
|
|
164
|
+
const fileId = serializeFileId(fileId_);
|
|
170
165
|
const document = constructDocument(document_, new types.DocumentAttributeFilename({ file_name: `${id[i] ?? "customEmoji"}.${extension(document_.mime_type)}` }), fileId, fileUniqueId);
|
|
171
166
|
documents.push(document);
|
|
172
167
|
}
|
|
@@ -181,12 +176,14 @@ export class FileManager {
|
|
|
181
176
|
const documents_ = await __classPrivateFieldGet(this, _FileManager_c, "f").api.messages.getCustomEmojiDocuments({ document_id: id.map(BigInt) }).then((v) => v.map((v) => v[as](types.Document)));
|
|
182
177
|
for (const [i, document_] of documents_.entries()) {
|
|
183
178
|
await __classPrivateFieldGet(this, _FileManager_c, "f").messageStorage.setCustomEmojiDocument(document_.id, document_);
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
accessHash: document_.access_hash,
|
|
179
|
+
const fileId_ = {
|
|
180
|
+
type: FileType.Document,
|
|
181
|
+
dcId: document_.dc_id,
|
|
188
182
|
fileReference: document_.file_reference,
|
|
189
|
-
|
|
183
|
+
location: { type: "common", id: document_.id, accessHash: document_.access_hash },
|
|
184
|
+
};
|
|
185
|
+
const fileUniqueId = toUniqueFileId(fileId_);
|
|
186
|
+
const fileId = serializeFileId(fileId_);
|
|
190
187
|
const document = constructDocument(document_, new types.DocumentAttributeFilename({ file_name: `${id[i] ?? "customEmoji"}.${extension(document_.mime_type)}` }), fileId, fileUniqueId);
|
|
191
188
|
documents.push(document);
|
|
192
189
|
}
|
|
@@ -13,8 +13,8 @@ var _MessageManager_instances, _MessageManager_c, _MessageManager_LresolveFileId
|
|
|
13
13
|
import { contentType } from "../0_deps.js";
|
|
14
14
|
import { getLogger, getRandomId, toUnixTimestamp, UNREACHABLE } from "../1_utilities.js";
|
|
15
15
|
import { as, getChannelChatId, peerToChatId, types } from "../2_tl.js";
|
|
16
|
-
import { constructChatMemberUpdated, constructInviteLink } from "../3_types.js";
|
|
17
|
-
import { assertMessageType, chatMemberRightsToTlObject, constructChatMember, constructMessage as constructMessage_, deserializeInlineMessageId,
|
|
16
|
+
import { constructChatMemberUpdated, constructInviteLink, deserializeFileId } from "../3_types.js";
|
|
17
|
+
import { assertMessageType, chatMemberRightsToTlObject, constructChatMember, constructMessage as constructMessage_, deserializeInlineMessageId, FileType, messageEntityToTlObject, reactionEqual, reactionToTlObject, replyMarkupToTlObject } from "../3_types.js";
|
|
18
18
|
import { STICKER_SET_NAME_TTL } from "../4_constants.js";
|
|
19
19
|
import { messageSearchFilterToTlObject } from "../types/0_message_search_filter.js";
|
|
20
20
|
import { parseHtml } from "./0_html.js";
|
|
@@ -363,7 +363,7 @@ export class MessageManager {
|
|
|
363
363
|
return assertMessageType(message, "audio");
|
|
364
364
|
}
|
|
365
365
|
async sendVoice(chatId, voice, params) {
|
|
366
|
-
const message = await __classPrivateFieldGet(this, _MessageManager_instances, "m", _MessageManager_sendDocumentInner).call(this, chatId, voice, params, FileType.
|
|
366
|
+
const message = await __classPrivateFieldGet(this, _MessageManager_instances, "m", _MessageManager_sendDocumentInner).call(this, chatId, voice, params, FileType.VoiceNote, [
|
|
367
367
|
new types.DocumentAttributeAudio({
|
|
368
368
|
voice: true,
|
|
369
369
|
duration: params?.duration ?? 0,
|
|
@@ -426,22 +426,19 @@ export class MessageManager {
|
|
|
426
426
|
resolveFileId(maybeFileId, expectedFileType) {
|
|
427
427
|
let fileId = null;
|
|
428
428
|
try {
|
|
429
|
-
fileId =
|
|
429
|
+
fileId = deserializeFileId(maybeFileId);
|
|
430
430
|
}
|
|
431
431
|
catch (err) {
|
|
432
432
|
__classPrivateFieldGet(this, _MessageManager_LresolveFileId, "f").warning(err);
|
|
433
433
|
}
|
|
434
434
|
if (fileId != null) {
|
|
435
|
-
if (fileId.
|
|
436
|
-
UNREACHABLE();
|
|
437
|
-
}
|
|
438
|
-
if (fileId.params.mediaId == undefined || fileId.params.accessHash == undefined || fileId.params.fileReference == undefined) {
|
|
435
|
+
if (fileId.type != expectedFileType) {
|
|
439
436
|
UNREACHABLE();
|
|
440
437
|
}
|
|
441
438
|
return {
|
|
442
|
-
id: fileId.
|
|
443
|
-
access_hash: fileId.
|
|
444
|
-
file_reference: fileId.
|
|
439
|
+
id: "id" in fileId.location ? fileId.location.id : UNREACHABLE(),
|
|
440
|
+
access_hash: fileId.location.accessHash,
|
|
441
|
+
file_reference: fileId.fileReference ?? new Uint8Array(),
|
|
445
442
|
};
|
|
446
443
|
}
|
|
447
444
|
return null;
|
package/esm/client/4_client.d.ts
CHANGED
|
@@ -269,11 +269,11 @@ export declare class Client<C extends Context = Context> extends ClientAbstract
|
|
|
269
269
|
branch(predicate: (ctx: UpdateIntersection<C>) => MaybePromise<boolean>, trueHandler_: Middleware<UpdateIntersection<C>>, falseHandler_: Middleware<UpdateIntersection<C>>): Composer<C>;
|
|
270
270
|
filter<D extends C>(predicate: (ctx: UpdateIntersection<C>) => ctx is D, ...middleware: Middleware<D>[]): Composer<D>;
|
|
271
271
|
filter(predicate: (ctx: UpdateIntersection<C>) => MaybePromise<boolean>, ...middleware: Middleware<UpdateIntersection<C>>[]): Composer<C>;
|
|
272
|
-
on<Q extends FilterQuery>(filter: Q, ...
|
|
272
|
+
on<Q extends FilterQuery>(filter: Q, ...middleware: Middleware<WithFilter<C, Q>>[]): Composer<UpdateIntersection<WithFilter<C, Q>>>;
|
|
273
273
|
command(commands: string | RegExp | (string | RegExp)[] | {
|
|
274
274
|
names: string | RegExp | (string | RegExp)[];
|
|
275
275
|
prefixes: string | string[];
|
|
276
|
-
}, ...
|
|
276
|
+
}, ...middleware: Middleware<WithFilter<C, "message:text">>[]): Composer<WithFilter<C, "message:text">>;
|
|
277
277
|
/**
|
|
278
278
|
* Send a text message.
|
|
279
279
|
*
|
package/esm/client/4_client.js
CHANGED
|
@@ -1391,12 +1391,12 @@ export class Client extends ClientAbstract {
|
|
|
1391
1391
|
this.branch(predicate, composer, skip);
|
|
1392
1392
|
return composer;
|
|
1393
1393
|
}
|
|
1394
|
-
on(filter, ...
|
|
1394
|
+
on(filter, ...middleware) {
|
|
1395
1395
|
return this.filter((ctx) => {
|
|
1396
1396
|
return match(filter, ctx);
|
|
1397
|
-
}, ...
|
|
1397
|
+
}, ...middleware);
|
|
1398
1398
|
}
|
|
1399
|
-
command(commands, ...
|
|
1399
|
+
command(commands, ...middleware) {
|
|
1400
1400
|
const commands__ = typeof commands === "object" && "names" in commands ? commands.names : commands;
|
|
1401
1401
|
const commands_ = Array.isArray(commands__) ? commands__ : [commands__];
|
|
1402
1402
|
const prefixes_ = typeof commands === "object" && "prefixes" in commands ? commands.prefixes : (__classPrivateFieldGet(this, _Client_prefixes, "f") ?? []);
|
|
@@ -1437,7 +1437,7 @@ export class Client extends ClientAbstract {
|
|
|
1437
1437
|
}
|
|
1438
1438
|
}
|
|
1439
1439
|
return false;
|
|
1440
|
-
}, ...
|
|
1440
|
+
}, ...middleware);
|
|
1441
1441
|
}
|
|
1442
1442
|
//#endregion
|
|
1443
1443
|
/**
|