UNPKG

cloudapp-dl

Version:

CloudApp/Zight API client and CLI. Use as a CLI tool to download videos or as a programmatic library to interact with the Zight API.

433 lines (382 loc) 12.7 kB
import { performLogin } from './auth.js'; import * as api from './api.js'; /** * ZightClient - Programmatic client for Zight/CloudApp API * * @example * // Initialize with email/password * const client = new ZightClient({ email: 'user@example.com', password: 'pass' }); * await client.login(); * * @example * // Initialize with existing session * const client = new ZightClient({ sessionId: 'abc123' }); * * @example * // Enable debug logging * const client = new ZightClient({ email: '...', password: '...', debug: true }); * * @example * // Use API methods * const account = await client.getAccountDetails(); * const notifications = await client.getNotifications({ limit: 10 }); */ export class ZightClient { /** * Create a new ZightClient instance * @param {Object} options - Configuration options * @param {string} [options.email] - Email for authentication * @param {string} [options.password] - Password for authentication * @param {string} [options.sessionId] - Existing session ID (alternative to email/password) * @param {string} [options.sessionExpiry] - Session expiry ISO string (optional) * @param {boolean} [options.debug=false] - Enable debug logging */ constructor(options = {}) { const { email, password, sessionId, sessionExpiry, debug = false } = options; this._email = email || null; this._password = password || null; this._sessionId = sessionId || null; this._sessionExpiry = sessionExpiry || null; this._userId = null; this._userName = null; this._debug = debug; } /** * Log a debug message (only if debug mode is enabled) * @private */ _log(...args) { if (this._debug) { console.log('[ZightClient]', ...args); } } /** * Get the session context for API calls * @private * @returns {Object} Session context */ _getContext() { return { sessionId: this._sessionId, sessionExpiry: this._sessionExpiry, email: this._email, password: this._password, debug: this._debug, log: this._log.bind(this), onSessionUpdate: (sessionInfo) => { this._sessionId = sessionInfo.sessionId; this._sessionExpiry = sessionInfo.sessionExpiry; this._log('Session updated, expires:', sessionInfo.sessionExpiry); } }; } /** * Check if the client has a valid session * @returns {boolean} */ get isAuthenticated() { return !!this._sessionId; } /** * Get the current session ID * @returns {string|null} */ get sessionId() { return this._sessionId; } /** * Get the session expiry * @returns {string|null} */ get sessionExpiry() { return this._sessionExpiry; } /** * Get the user ID (available after getAccountDetails) * @returns {string|null} */ get userId() { return this._userId; } /** * Get the user name (available after getAccountDetails) * @returns {string|null} */ get userName() { return this._userName; } /** * Login with email and password * @returns {Promise<Object>} Login result with sessionId and sessionExpiry */ async login() { if (!this._email || !this._password) { throw new Error('Email and password are required for login'); } this._log('Logging in...'); const result = await performLogin(this._email, this._password); this._sessionId = result.sessionId; this._sessionExpiry = result.sessionExpiry; this._log('Login successful, session expires:', this._sessionExpiry); return { success: true, sessionId: this._sessionId, sessionExpiry: this._sessionExpiry }; } /** * Set session directly (for when you already have a session ID) * @param {string} sessionId - The session ID * @param {string} [sessionExpiry] - Optional expiry ISO string */ setSession(sessionId, sessionExpiry = null) { this._sessionId = sessionId; this._sessionExpiry = sessionExpiry; } /** * Clear the current session */ logout() { this._sessionId = null; this._sessionExpiry = null; this._userId = null; this._userName = null; } // ==================== Account Methods ==================== /** * Get current user account details * @returns {Promise<Object>} User account data */ async getAccountDetails() { const response = await api.getAccountDetails(this._getContext()); // Store user info if (response.data?.user) { this._userId = response.data.user.id; this._userName = response.data.user.attributes?.name; } return response; } /** * Get organization details * @param {string} [orgId] - Organization ID (optional) * @returns {Promise<Object>} Organization data */ async getOrganization(orgId = null) { return await api.getOrganization(orgId, this._getContext()); } // ==================== Items/Drops Methods ==================== /** * Get list of drops (files/items) * @param {Object} [options] - Query options * @param {number} [options.page=1] - Page number * @param {number} [options.perPage=20] - Items per page * @param {string} [options.filter] - Filter type * @returns {Promise<Object>} Drops data */ async getDrops(options = {}) { return await api.getDrops(options, this._getContext()); } /** * Get details of a specific drop * @param {string} dropId - The drop ID * @returns {Promise<Object>} Drop data */ async getDrop(dropId) { return await api.getDrop(dropId, this._getContext()); } /** * Get single item/drop details * @param {string} itemId - The item ID * @returns {Promise<Object>} Item details */ async getItem(itemId) { return await api.getItem(itemId, this._getContext()); } /** * Search drops * @param {string} query - Search query * @param {Object} [options] - Search options * @returns {Promise<Object>} Search results */ async searchDrops(query, options = {}) { return await api.searchDrops(query, options, this._getContext()); } /** * Get items from dashboard with pagination * @param {Object} [options] - Options * @param {number} [options.page=1] - Starting page number * @param {number} [options.perPage=12] - Items per page * @param {Function} [options.onProgress] - Progress callback * @returns {Promise<Object>} Items and pagination info */ async getItemsFromDashboard(options = {}) { return await api.getItemsFromDashboard(options, this._getContext()); } /** * Get ALL items from dashboard * @param {Object} [options] - Options * @param {Function} [options.onProgress] - Progress callback * @param {number} [options.startPage=1] - Start from this page * @param {number} [options.endPage] - End at this page * @returns {Promise<Object>} All items and metadata */ async getAllItems(options = {}) { return await api.getAllItems(options, this._getContext()); } // ==================== Collections Methods ==================== /** * Get list of collections * @param {Object} [options] - Options * @returns {Promise<Object>} Collections data */ async getCollections(options = {}) { return await api.getCollections(options, this._getContext()); } /** * Get all collections * @returns {Promise<Array>} Array of all collections */ async getAllCollections() { return await api.getAllCollections(this._getContext()); } // ==================== Video Request Methods ==================== /** * Create a video recording request link * @param {Object} options - Request options * @param {string} options.name - Title of the request (required) * @param {string} options.message - Message/instructions (required) * @param {string} [options.customId] - Custom identifier * @param {string} [options.expiresAt] - Expiration date ISO format * @param {string} [options.collectionId] - Collection ID * @param {boolean} [options.collectLogs=false] - Collect logs * @returns {Promise<Object>} Request content data with link */ async createVideoRequest(options) { return await api.createVideoRequest(options, this._getContext()); } /** * Get list of video requests * @param {Object} [options] - Options * @returns {Promise<Object>} Video requests data */ async getVideoRequests(options = {}) { return await api.getVideoRequests(options, this._getContext()); } /** * Get a specific video request by ID * @param {string} requestId - The request ID * @returns {Promise<Object|null>} Request data or null */ async getVideoRequest(requestId) { return await api.getVideoRequest(requestId, this._getContext()); } /** * Update a video request * @param {string} requestId - The request ID * @param {Object} options - Update options * @returns {Promise<Object>} Updated request data */ async updateVideoRequest(requestId, options) { return await api.updateVideoRequest(requestId, options, this._getContext()); } /** * Delete a video request * @param {string} requestId - The request ID * @returns {Promise<Object>} Deleted request data */ async deleteVideoRequest(requestId) { return await api.deleteVideoRequest(requestId, this._getContext()); } // ==================== Upload Methods ==================== /** * Upload a file to Zight * @param {string} filePath - Path to the file * @param {Function} [onProgress] - Progress callback * @returns {Promise<Object>} Uploaded item data with share URL */ async uploadFile(filePath, onProgress = null) { return await api.uploadFile(filePath, onProgress, this._getContext()); } /** * Create an upload request (step 1 of upload process) * @param {string} filename - The filename * @param {number} fileSize - File size in bytes * @param {string} contentType - MIME type * @returns {Promise<Object>} Upload credentials */ async createUploadRequest(filename, fileSize, contentType) { return await api.createUploadRequest(filename, fileSize, contentType, this._getContext()); } /** * Confirm upload completion (step 3 of upload process) * @param {string} slug - The item slug * @param {string} s3Key - The S3 key * @param {string} checksum - The checksum * @returns {Promise<Object>} Completed item data */ async confirmUploadComplete(slug, s3Key, checksum) { return await api.confirmUploadComplete(slug, s3Key, checksum, this._getContext()); } // ==================== Delete/Trash Methods ==================== /** * Delete an item * @param {string} itemId - The item ID * @param {boolean} [permanent=false] - Permanently delete * @returns {Promise<Object>} Delete response */ async deleteItem(itemId, permanent = false) { return await api.deleteItem(itemId, permanent, this._getContext()); } /** * Restore an item from trash * @param {string} itemId - The item ID * @returns {Promise<Object>} Restore response */ async restoreItem(itemId) { return await api.restoreItem(itemId, this._getContext()); } /** * Get items from trash * @returns {Promise<Array>} Array of trash items */ async getTrashItems() { return await api.getTrashItems(this._getContext()); } /** * Empty the trash * @param {Function} [onProgress] - Progress callback * @returns {Promise<Object>} Results summary */ async emptyTrash(onProgress = null) { return await api.emptyTrash(onProgress, this._getContext()); } // ==================== Notification Methods ==================== /** * Get notifications * @param {Object} [options] - Options * @param {string} [options.viewed='no'] - 'yes', 'no', or 'all' * @param {number} [options.limit=20] - Number to fetch * @param {string} [options.createdBefore] - ISO date for pagination * @returns {Promise<Object>} Notifications data */ async getNotifications(options = {}) { return await api.getNotifications(options, this._getContext()); } /** * Mark a notification as viewed * @param {string} notificationId - The notification ID * @returns {Promise<Object>} Response */ async markNotificationViewed(notificationId) { return await api.markNotificationViewed(notificationId, this._getContext()); } /** * Mark all notifications as viewed * @param {Function} [onProgress] - Progress callback * @returns {Promise<Object>} Results summary */ async markAllNotificationsViewed(onProgress = null) { return await api.markAllNotificationsViewed(onProgress, this._getContext()); } } export default ZightClient;