@inline-chat/realtime-sdk 0.0.5 → 0.0.7
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/dist/sdk/inline-sdk-client.js +118 -27
- package/package.json +1 -1
|
@@ -175,18 +175,28 @@ export class InlineSdkClient {
|
|
|
175
175
|
}
|
|
176
176
|
const peerId = this.inputPeerFromTarget(params, "sendMessage");
|
|
177
177
|
const media = params.media != null ? toInputMedia(params.media) : undefined;
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
178
|
+
let result;
|
|
179
|
+
try {
|
|
180
|
+
result = await this.invoke(Method.SEND_MESSAGE, {
|
|
181
|
+
oneofKind: "sendMessage",
|
|
182
|
+
sendMessage: {
|
|
183
|
+
peerId,
|
|
184
|
+
...(hasText ? { message: params.text } : {}),
|
|
185
|
+
...(media != null ? { media } : {}),
|
|
186
|
+
...(params.replyToMsgId != null ? { replyToMsgId: asInlineId(params.replyToMsgId, "replyToMsgId") } : {}),
|
|
187
|
+
...(params.parseMarkdown != null ? { parseMarkdown: params.parseMarkdown } : {}),
|
|
188
|
+
...(params.entities != null ? { entities: params.entities } : {}),
|
|
189
|
+
...(params.sendMode === "silent" ? { sendMode: MessageSendMode.MODE_SILENT } : {}),
|
|
190
|
+
},
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
const target = "chatId" in params ? `chat:${String(params.chatId)}` : `user:${String(params.userId)}`;
|
|
195
|
+
const mediaKind = params.media?.kind ?? "none";
|
|
196
|
+
const textLen = hasText ? params.text.length : 0;
|
|
197
|
+
const detail = extractErrorMessage(error);
|
|
198
|
+
throw new Error(`sendMessage: request failed (${detail}; target=${target}; media=${mediaKind}; textLen=${textLen}; replyTo=${params.replyToMsgId != null ? String(params.replyToMsgId) : "none"})`, { cause: error });
|
|
199
|
+
}
|
|
190
200
|
const messageId = extractFirstMessageId(result.sendMessage.updates);
|
|
191
201
|
return { messageId };
|
|
192
202
|
}
|
|
@@ -195,11 +205,16 @@ export class InlineSdkClient {
|
|
|
195
205
|
form.set("type", params.type);
|
|
196
206
|
const fileName = normalizeUploadFileName(params.fileName, params.type);
|
|
197
207
|
const fileContentType = resolveUploadContentType(params.type, params.contentType);
|
|
198
|
-
form.set("file",
|
|
208
|
+
form.set("file", toUploadMultipartFile(params.file, fileName, fileContentType), fileName);
|
|
209
|
+
const fileSize = getBinaryInputSize(params.file);
|
|
210
|
+
let thumbnailName;
|
|
211
|
+
let thumbnailContentType;
|
|
212
|
+
let thumbnailSize;
|
|
199
213
|
if (params.thumbnail != null) {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
214
|
+
thumbnailName = normalizeUploadFileName(params.thumbnailFileName, "photo");
|
|
215
|
+
thumbnailContentType = resolveUploadContentType("photo", params.thumbnailContentType);
|
|
216
|
+
thumbnailSize = getBinaryInputSize(params.thumbnail);
|
|
217
|
+
form.set("thumbnail", toUploadMultipartFile(params.thumbnail, thumbnailName, thumbnailContentType), thumbnailName);
|
|
203
218
|
}
|
|
204
219
|
if (params.type === "video") {
|
|
205
220
|
const width = normalizePositiveInt(params.width, "width") ?? defaultVideoWidth;
|
|
@@ -209,29 +224,56 @@ export class InlineSdkClient {
|
|
|
209
224
|
form.set("height", String(height));
|
|
210
225
|
form.set("duration", String(duration));
|
|
211
226
|
}
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
227
|
+
const uploadUrl = resolveUploadFileUrl(this.httpBaseUrl);
|
|
228
|
+
const requestContext = describeUploadContext({
|
|
229
|
+
type: params.type,
|
|
230
|
+
fileName,
|
|
231
|
+
fileContentType,
|
|
232
|
+
fileSize,
|
|
233
|
+
...(thumbnailName ? { thumbnailName } : {}),
|
|
234
|
+
...(thumbnailContentType ? { thumbnailContentType } : {}),
|
|
235
|
+
...(thumbnailSize != null ? { thumbnailSize } : {}),
|
|
236
|
+
...(params.type === "video"
|
|
237
|
+
? {
|
|
238
|
+
width: params.width ?? defaultVideoWidth,
|
|
239
|
+
height: params.height ?? defaultVideoHeight,
|
|
240
|
+
duration: params.duration ?? defaultVideoDuration,
|
|
241
|
+
}
|
|
242
|
+
: {}),
|
|
243
|
+
uploadUrl: uploadUrl.toString(),
|
|
218
244
|
});
|
|
245
|
+
let response;
|
|
246
|
+
try {
|
|
247
|
+
response = await this.fetchImpl(uploadUrl, {
|
|
248
|
+
method: "POST",
|
|
249
|
+
headers: {
|
|
250
|
+
authorization: `Bearer ${this.options.token}`,
|
|
251
|
+
},
|
|
252
|
+
body: form,
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
const detail = extractErrorMessage(error);
|
|
257
|
+
throw new Error(`uploadFile: network request failed (${detail}; ${requestContext})`, {
|
|
258
|
+
cause: error,
|
|
259
|
+
});
|
|
260
|
+
}
|
|
219
261
|
const payload = await parseJsonResponse(response);
|
|
220
262
|
if (!response.ok) {
|
|
221
263
|
const detail = describeUploadFailure(payload);
|
|
222
|
-
throw new Error(`uploadFile: request failed with status ${response.status}${detail ? ` (${detail})` : ""}`);
|
|
264
|
+
throw new Error(`uploadFile: request failed with status ${response.status}${detail ? ` (${detail})` : ""}; ${requestContext}`);
|
|
223
265
|
}
|
|
224
266
|
if (!isRecord(payload) || payload.ok !== true) {
|
|
225
267
|
const detail = describeUploadFailure(payload);
|
|
226
|
-
throw new Error(`uploadFile: API error${detail ? ` (${detail})` : ""}`);
|
|
268
|
+
throw new Error(`uploadFile: API error${detail ? ` (${detail})` : ""}; ${requestContext}`);
|
|
227
269
|
}
|
|
228
270
|
const result = payload.result;
|
|
229
271
|
if (!isRecord(result)) {
|
|
230
|
-
throw new Error(
|
|
272
|
+
throw new Error(`uploadFile: malformed success payload; ${requestContext}`);
|
|
231
273
|
}
|
|
232
274
|
const fileUniqueId = typeof result.fileUniqueId === "string" ? result.fileUniqueId.trim() : "";
|
|
233
275
|
if (!fileUniqueId) {
|
|
234
|
-
throw new Error(
|
|
276
|
+
throw new Error(`uploadFile: response missing fileUniqueId; ${requestContext}`);
|
|
235
277
|
}
|
|
236
278
|
const photoId = parseOptionalBigInt(result.photoId, "photoId");
|
|
237
279
|
const videoId = parseOptionalBigInt(result.videoId, "videoId");
|
|
@@ -653,7 +695,7 @@ function normalizeHttpBaseUrl(baseUrl) {
|
|
|
653
695
|
return url.toString().replace(/\/$/, "");
|
|
654
696
|
}
|
|
655
697
|
function normalizeUploadFileName(raw, type) {
|
|
656
|
-
const trimmed = raw
|
|
698
|
+
const trimmed = sanitizeUploadFileName(raw);
|
|
657
699
|
if (trimmed)
|
|
658
700
|
return trimmed;
|
|
659
701
|
switch (type) {
|
|
@@ -684,6 +726,55 @@ function toBlob(input, type) {
|
|
|
684
726
|
}
|
|
685
727
|
return new Blob([input], { type });
|
|
686
728
|
}
|
|
729
|
+
function toUploadMultipartFile(input, fileName, type) {
|
|
730
|
+
const blob = toBlob(input, type);
|
|
731
|
+
if (typeof File === "undefined")
|
|
732
|
+
return blob;
|
|
733
|
+
return new File([blob], fileName, { type });
|
|
734
|
+
}
|
|
735
|
+
function sanitizeUploadFileName(raw) {
|
|
736
|
+
const trimmed = raw?.trim();
|
|
737
|
+
if (!trimmed)
|
|
738
|
+
return "";
|
|
739
|
+
const normalized = trimmed.replace(/\\/g, "/");
|
|
740
|
+
const leaf = normalized.split("/").pop() ?? normalized;
|
|
741
|
+
const noQuery = leaf.split(/[?#]/, 1)[0] ?? leaf;
|
|
742
|
+
return noQuery.trim();
|
|
743
|
+
}
|
|
744
|
+
function getBinaryInputSize(input) {
|
|
745
|
+
if (input instanceof Blob)
|
|
746
|
+
return input.size;
|
|
747
|
+
if (input instanceof Uint8Array)
|
|
748
|
+
return input.byteLength;
|
|
749
|
+
return input.byteLength;
|
|
750
|
+
}
|
|
751
|
+
function describeUploadContext(params) {
|
|
752
|
+
const parts = [
|
|
753
|
+
`type=${params.type}`,
|
|
754
|
+
`fileName=${params.fileName}`,
|
|
755
|
+
`fileContentType=${params.fileContentType}`,
|
|
756
|
+
`fileSize=${params.fileSize}`,
|
|
757
|
+
`uploadUrl=${params.uploadUrl}`,
|
|
758
|
+
];
|
|
759
|
+
if (params.thumbnailName)
|
|
760
|
+
parts.push(`thumbnailName=${params.thumbnailName}`);
|
|
761
|
+
if (params.thumbnailContentType)
|
|
762
|
+
parts.push(`thumbnailContentType=${params.thumbnailContentType}`);
|
|
763
|
+
if (params.thumbnailSize != null)
|
|
764
|
+
parts.push(`thumbnailSize=${params.thumbnailSize}`);
|
|
765
|
+
if (params.width != null)
|
|
766
|
+
parts.push(`width=${params.width}`);
|
|
767
|
+
if (params.height != null)
|
|
768
|
+
parts.push(`height=${params.height}`);
|
|
769
|
+
if (params.duration != null)
|
|
770
|
+
parts.push(`duration=${params.duration}`);
|
|
771
|
+
return parts.join(", ");
|
|
772
|
+
}
|
|
773
|
+
function extractErrorMessage(error) {
|
|
774
|
+
if (error instanceof Error)
|
|
775
|
+
return error.message;
|
|
776
|
+
return String(error);
|
|
777
|
+
}
|
|
687
778
|
function normalizePositiveInt(value, field) {
|
|
688
779
|
if (value == null)
|
|
689
780
|
return undefined;
|