-
Notifications
You must be signed in to change notification settings - Fork 26
Description
Пакет: @maxhub/max-bot-api v0.2.1
Описание
Загрузка видео через api.upload.video({ source: buffer }) падает с ошибкой:
SyntaxError: Unexpected token '<', "<retval>1</retval>" is not valid JSON
Проблема в методе Upload.uploadFromBuffer (dist/core/helpers/upload.js). После загрузки файла на upload URL (шаг 2) он вызывает res.json() на ответе сервера. Однако MAX API для видео возвращает XML <retval>1</retval>, а не JSON.
Корневая причина
В потоке загрузки два бага:
Баг 1: В типе GetUploadUrlResponse отсутствует поле token
В dist/core/network/api/modules/uploads/types.d.ts:
export type GetUploadUrlResponse = {
url: string; // ← token отсутствует!
};Реальный ответ MAX API на POST /uploads?type=video:
{ "url": "https://...", "token": "f9LHodD0cOLK4f2L47RB..." }token уже возвращается на шаге 1, но SDK его игнорирует, потому что в типе его нет.
Баг 2: uploadFromBuffer парсит ответ шага 2 как JSON
В dist/core/helpers/upload.js:
this.uploadFromBuffer = async ({ file, uploadUrl, abortController }) => {
const formData = new FormData();
formData.append('data', new Blob([file.buffer]), file.fileName);
const res = await fetch(uploadUrl, {
method: 'POST',
body: formData,
signal: abortController?.signal,
});
return await res.json(); // ← БАГ: ответ — XML, не JSON
};Upload-эндпоинт (шаг 2) возвращает <retval>1</retval> (XML-подтверждение), а не JSON с { id, token }. Токен нужно брать из ответа шага 1.
Аналогичная проблема есть в uploadFromStream, который тоже вызывает uploadData = await uploadRes.json() на промежуточных ответах загрузки.
Ожидаемое поведение
Метод upload должен:
- Извлекать
tokenиз ответаPOST /uploads(шаг 1) — он там уже есть - Не пытаться парсить ответ шага 2 как JSON (это XML)
- Возвращать
{ token }из шага 1
Предлагаемое исправление
this.upload = async (type, file, options) => {
// Шаг 1: getUploadUrl возвращает { url, token }
const { url: uploadUrl, token } = await this.api.raw.uploads.getUploadUrl({ type });
// ... загрузка файла на uploadUrl (шаг 2) ...
// Возвращаем token из шага 1, а не из ответа шага 2
return { token };
};И обновить тип:
export type GetUploadUrlResponse = {
url: string;
token: string;
};Воспроизведение
import { Bot } from '@maxhub/max-bot-api'
import fs from 'fs'
const bot = new Bot('BOT_TOKEN')
const videoBuffer = fs.readFileSync('video.mp4')
const result = await bot.api.upload.video({ source: videoBuffer })
// Падает: SyntaxError: Unexpected token '<', "<retval>1</retval>" is not valid JSONОбходное решение
Вызывать MAX API напрямую, минуя хелпер загрузки SDK:
// Шаг 1: Получаем upload URL и token
const res1 = await fetch(`https://botapi.max.ru/uploads?access_token=${botToken}&type=video`, { method: 'POST' })
const { url, token } = await res1.json()
// Шаг 2: Загружаем файл (ответ — XML, не парсим)
const formData = new FormData()
formData.append('data', new Blob([buffer], { type: 'video/mp4' }), 'video.mp4')
await fetch(url, { method: 'POST', body: formData })
// Шаг 3: Используем token из шага 1
const attachment = new VideoAttachment({ token })Окружение
@maxhub/max-bot-api: 0.2.1- Node.js: 22.x
- ОС: Linux (Docker)