@persian-caesar/aparat.js
Version:
The aparat website services for npm package.
182 lines (181 loc) • 8.41 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.VideoService = void 0;
const enums_1 = require("../types/enums");
const fs_1 = require("fs");
const endpoints_1 = require("../utils/endpoints");
const error_handler_1 = require("../utils/error-handler");
const https = __importStar(require("https"));
class VideoService {
constructor(api) {
this.api = api;
}
/**
* Searches for videos matching a query string.
* It filters and maps the API response to an array of SearchVideo objects.
*
* @param query - The search term used to find videos.
* @returns A Promise that resolves to an array of SearchVideo objects.
*/
async search(query) {
try {
const data = await this.api.fetch(enums_1.BaseApiUrlTypes.ApiV1, endpoints_1.Endpoints.V1.SearchVideo(query));
// Filter items to include only videos and map them to the SearchVideo interface
const results = data.included
.filter(item => item.type === "Video")
.map(item => {
return {
id: parseInt(item.attributes.id),
hash_id: item.attributes.uid,
title: item.attributes.title,
description: item.attributes.description,
url: `https://www.aparat.com/v/${item.attributes.uid}`,
views: parseInt(item.attributes.visit_cnt_int),
likes: parseInt(item.attributes.like_cnt),
duration: parseInt(item.attributes.duration),
thumbnail: item.attributes.big_poster,
preview: item.attributes.preview_src,
frame: item.attributes.frame,
publish_at: new Date(item.attributes.sdate_timediff),
uploader: {
id: item.attributes.userid,
name: item.attributes.sender_name,
username: item.attributes.username,
icon: item.attributes.profilePhoto,
is_official: item.attributes.official === "yes" ? true : false
}
};
});
return results;
}
catch (error) {
// Throw a custom APIError if the search fails
throw new error_handler_1.APIError(enums_1.ErrorCodes.SEARCH_ERROR, "Faild to search the video");
}
}
/**
* Retrieves detailed information about a video by its hash.
*
* @param hash - The unique hash identifier for the video.
* @returns A Promise that resolves to a GetVideo object containing video details.
*/
async get(hash) {
try {
const data = await this.api.fetch(enums_1.BaseApiUrlTypes.ApiBase, endpoints_1.Endpoints.Base.GetVideo(hash));
// Construct and return a GetVideo object based on API response data
return {
id: parseInt(data.video.id),
hash_id: data.video.uid,
title: data.video.title,
duration: data.video.duration,
views: data.video.visit_cnt,
thumbnail: data.video.big_poster,
publish_at: new Date(data.video.sdate_timediff),
description: data.video.description,
frame: data.video.frame,
likes: data.video.like_cnt,
tags: data.video.tags,
url: `https://www.aparat.com/v/${data.video.uid}`,
uploader: {
id: data.video.userid,
name: data.video.sender_name,
username: data.video.username,
icon: data.video.profilePhoto
},
is_download_able: data.video.can_download,
download_link: data.video.file_link,
download_links: data.video.file_link_all.map(a => ({ quality: a.profile, url: a.urls[0] }))
};
}
catch (error) {
// If fetching video details fails, wrap the error in an APIError
throw new error_handler_1.APIError(enums_1.ErrorCodes.SEARCH_ERROR, "Faild to search the video");
}
}
/**
* Downloads a video file by streaming it from a provided download URL.
* It checks for download availability and selects the appropriate quality.
*
* @param hash - The unique hash of the video.
* @param quality - The desired video quality (default is P720).
* @param outputPath - The file path prefix where the video will be saved.
* @returns A Promise that resolves when the video is successfully downloaded.
*/
async download(hash, quality = enums_1.VideoQuality.P720, outputPath = "./video.mp4") {
try {
const video = await this.get(hash);
// Verify if the video is available for download
if (!video.is_download_able)
throw new error_handler_1.APIError(enums_1.ErrorCodes.DOWNLOAD_ERROR, "This video is not download able!");
// Select the download link matching the specified quality or fallback to the first available link
const downloadLinkObj = video.download_links.find(link => link.quality === quality) ||
{ quality: "unknown quality", url: video.download_link };
if (!downloadLinkObj) {
throw new error_handler_1.APIError(enums_1.ErrorCodes.DOWNLOAD_ERROR, "No download link to this video");
}
// Stream the video file and save it locally
await new Promise((resolve, reject) => {
const file = (0, fs_1.createWriteStream)(outputPath);
https
.get(downloadLinkObj.url, (response) => {
response.pipe(file);
file.on("finish", () => {
file.close();
resolve();
});
})
.on("error", (err) => {
// Remove incomplete file on error and reject the promise with an APIError
(0, fs_1.unlink)(outputPath, () => { });
reject(new error_handler_1.APIError(enums_1.ErrorCodes.DOWNLOAD_ERROR, err.message));
});
});
}
catch (error) {
// Wrap any download-related errors into an APIError and throw
throw new error_handler_1.APIError(enums_1.ErrorCodes.DOWNLOAD_ERROR, error instanceof Error ? error.message : "Faild to download the video!");
}
}
}
exports.VideoService = VideoService;
/**
* @copyright
* Code by Sobhan-SRZA (mr.sinre) | https://github.com/Sobhan-SRZA
* Developed for Persian Caesar | https://github.com/Persian-Caesar | https://dsc.gg/persian-caesar
*
* If you encounter any issues or need assistance with this code,
* please make sure to credit "Persian Caesar" in your documentation or communications.
*/