-
Notifications
You must be signed in to change notification settings - Fork 8
Open
Description
Thanks for you api investigation!
I'd like to share video & image uploading methods. It's in typescript, but i suppose you can understand it and adopt into your lib.
Main client methods, request is the main call method with auth headers etc.
async request<T>(method: string, endpoint: string, data?: any): Promise<T> {
await this.auth();
const res = await fetch(`https://api.boosty.to${endpoint}`, {
method,
headers: this.headers,
body: data,
});
if (!res.ok) {
throw new Error(`Request failed with status ${res.status} ${res.body ? await res.text() : ""}`);
}
return (await res.json()) as T;
}
async uploadImage(file: string): Promise<ImageUpload> {
let type = "image/jpeg";
if (file.endsWith(".png")) type = "image/png";
if (file.endsWith(".webp")) type = "image/webp";
if (file.endsWith(".gif")) type = "image/gif";
if (file.endsWith(".jpeg")) type = "image/jpeg";
const file_data = new File([Deno.readFileSync(file)], basename(file), { type });
const res = await fetch("https://uploadimg.boosty.to/v1/media_data/image/", {
method: "POST",
headers: this.headers,
body: file_data,
});
if (!res.ok) {
throw new Error(`Image upload failed with status ${res.status} ${res.body ? await res.text() : ""}`);
}
const data = await res.json();
return data;
}
getVideoUploadUrl(file_name: string): Promise<VideoUploadUrl> {
return this.request("GET", `/v1/media_data/video/upload_url?${new URLSearchParams({ file_name })}`);
}
videoUploadFinish(video_id: string): Promise<VideoUploadFinish> {
return this.request("POST", `/v1/media_data/video/${video_id}/finish`);
}
async uploadVideo(file: string, preview_file?: string, onProgress?: (progress: number) => void): Promise<Video> {
const upload_url = await this.getVideoUploadUrl(basename(file));
const file_size = await uploader(file, upload_url.uploadUrl, onProgress);
const upload_finish = await this.videoUploadFinish(upload_url.id);
const image = { } as any;
if (preview_file) {
const image_upload = await this.uploadImage(preview_file);
image.preview = image_upload.url;
image.previewId = image_upload.id;
}
return {
complete: upload_finish.complete,
id: upload_url.id,
size: file_size,
title: "Video",
type: "ok_video",
url: "",
vid: upload_url.videoId,
playerUrls: [],
...image,
duration: upload_finish.duration,
timeCode: 0,
viewsCounter: 0,
uploadStatus: "ok",
showViewsCounter: true,
};And uploader method to upload to OK cdn
// 1024 * 1024
const CHUNK_SIZE = 1048576;
export async function uploader(file: string, url: string, onProgress?: (progress: number) => void): Promise<number> {
const file_size = Deno.statSync(file).size;
const file_name = basename(file);
const handle = Deno.openSync(file, { read: true });
let cur = 0;
while (true) {
const range = [cur, Math.min(file_size, cur + CHUNK_SIZE)];
await handle.seek(range[0], Deno.SeekMode.Start);
const buf = new Uint8Array(CHUNK_SIZE);
await handle.read(buf);
const headers = {
"Content-Disposition": `attachment; filename=${file_name}`,
"Content-Length": `${range[1] - range[0]}`,
"Content-Range": `bytes ${range[0]}-${range[1] - 1}/${file_size}`,
"Content-Type": "application/octet-stream",
"Origin": "https://boosty.to",
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36",
"X-Uploading-Mode": "parallel",
};
const res = await fetch(url, {
method: "POST",
headers,
body: buf,
});
if (!res.ok) {
throw new Error(`Upload failed with status ${res.status} ${res.body ? await res.text() : ""}`);
}
if (onProgress) {
onProgress(Math.round((cur * 100) / file_size) / 100);
}
cur = range[1];
if (range[1] >= file_size - 1) {
break;
}
}
return file_size;
}Metadata
Metadata
Assignees
Labels
No labels