UNPKG

@warriorteam/redai-zalo-sdk

Version:

Comprehensive TypeScript/JavaScript SDK for Zalo APIs - Official Account, ZNS, Consultation Service, Group Messaging, and Social APIs

396 lines (325 loc) 10.3 kB
# Article Management Service The `ArticleService` and `VideoUploadService` provide comprehensive article management capabilities for Zalo Official Account (OA). ## Features ### ArticleService - ✅ Create normal articles with rich content - ✅ Create video articles - ✅ Update existing articles - ✅ **Update article status only** (new feature) - ✅ Get article details and lists - ✅ Remove articles - ✅ Track article creation/update progress - ✅ Comprehensive validation ### VideoUploadService - ✅ Upload video files for articles - ✅ Check video processing status - ✅ Wait for upload completion with polling - ✅ Upload videos from URLs - ✅ Get video information ## Prerequisites 1. **OA Requirements:** - OA must have permission to create articles - Access token must have "manage_article" scope - OA must have active status and be verified 2. **Content Limits:** - Title: max 150 characters - Author: max 50 characters (normal articles only) - Description: max 300 characters - Image size: max 1MB per image - Video size: max 50MB per video - Video formats: MP4, AVI only ## Usage ### Initialize SDK ```typescript import { ZaloSDK } from 'redai-zalo-sdk'; const sdk = new ZaloSDK({ appId: 'your_app_id', appSecret: 'your_app_secret', }); const article = sdk.article; const videoUpload = sdk.videoUpload; ``` ### 1. Create Normal Article ```typescript import { ArticleType, ArticleStatus, CommentStatus, CoverType, BodyItemType } from 'redai-zalo-sdk'; const normalArticle = { type: ArticleType.NORMAL, title: "Welcome to Our Service", author: "RedAI Team", description: "This is a comprehensive guide to our new features", cover: { cover_type: CoverType.PHOTO, photo_url: "https://example.com/cover.jpg", status: ArticleStatus.SHOW }, body: [ { type: BodyItemType.TEXT, content: "Welcome to our new service! Here's what you need to know..." }, { type: BodyItemType.IMAGE, url: "https://example.com/image1.jpg" }, { type: BodyItemType.TEXT, content: "For more information, please contact us." } ], tracking_link: "https://your-website.com/tracking", status: ArticleStatus.SHOW, comment: CommentStatus.SHOW }; const result = await article.createNormalArticle(accessToken, normalArticle); console.log(`Article creation token: ${result.token}`); ``` ### 2. Create Video Article ```typescript const videoArticle = { type: ArticleType.VIDEO, title: "Product Demo Video", description: "Watch our latest product demonstration", video_id: "your_video_id", // Get from video upload avatar: "https://example.com/thumbnail.jpg", status: ArticleStatus.SHOW, comment: CommentStatus.SHOW }; const result = await article.createVideoArticle(accessToken, videoArticle); console.log(`Video article creation token: ${result.token}`); ``` ### 3. Upload Video for Articles ```typescript // Upload video file const videoFile = new File([videoBuffer], 'demo.mp4', { type: 'video/mp4' }); const uploadResult = await videoUpload.uploadVideo(accessToken, videoFile); // Wait for processing completion const finalResult = await videoUpload.waitForUploadCompletion( accessToken, uploadResult.token, 5 * 60 * 1000, // 5 minutes timeout 5 * 1000 // 5 seconds polling interval ); console.log(`Video ID: ${finalResult.video_id}`); ``` ### 4. Upload Video from URL ```typescript const uploadResult = await videoUpload.uploadVideoFromUrl( accessToken, 'https://example.com/video.mp4' ); const finalResult = await videoUpload.waitForUploadCompletion( accessToken, uploadResult.token ); ``` ### 5. Check Article Creation Progress ```typescript const progress = await article.checkArticleProcess(accessToken, token); switch (progress.status) { case 'processing': console.log('Article is still being processed...'); break; case 'success': console.log(`Article created with ID: ${progress.article_id}`); break; case 'failed': console.error(`Article creation failed: ${progress.error_message}`); break; } ``` ### 6. Get Article Details ```typescript const articleDetail = await article.getArticleDetail(accessToken, articleId); console.log('Article details:', articleDetail); ``` ### 7. Get Article List ```typescript const articleList = await article.getArticleList(accessToken, { offset: 0, limit: 20, type: 'normal' // or 'video' }); console.log(`Found ${articleList.data.total} articles`); articleList.data.articles.forEach(article => { console.log(`- ${article.title} (${article.total_view} views)`); }); ``` ### 8. Update Article ```typescript const updateData = { id: articleId, type: ArticleType.NORMAL, title: "Updated Article Title", author: "Updated Author", description: "Updated description", cover: { cover_type: CoverType.PHOTO, photo_url: "https://example.com/new-cover.jpg", status: ArticleStatus.SHOW }, body: [ { type: BodyItemType.TEXT, content: "Updated content..." } ], status: ArticleStatus.SHOW }; const updateResult = await article.updateNormalArticle(accessToken, updateData); console.log(`Update token: ${updateResult.token}`); ``` ### 9. Remove Article ```typescript const removeResult = await article.removeArticle(accessToken, articleId); console.log(removeResult.message); ``` ### 10. Check Video Status ```typescript const videoStatus = await videoUpload.checkVideoStatus(accessToken, token); console.log(`Status: ${videoStatus.status}`); console.log(`Progress: ${videoStatus.convert_percent}%`); if (videoStatus.video_id) { console.log(`Video ID: ${videoStatus.video_id}`); } ``` ## Error Handling ```typescript import { ZaloSDKError } from 'redai-zalo-sdk'; try { const result = await article.createNormalArticle(accessToken, articleData); console.log('Success:', result); } catch (error) { if (error instanceof ZaloSDKError) { console.error('Zalo API Error:', error.message, error.code); console.error('Details:', error.details); } else { console.error('Unexpected error:', error); } } ``` ## Complete Example ```typescript import { ZaloSDK, ArticleType, CoverType, BodyItemType, ArticleStatus } from 'redai-zalo-sdk'; class ArticleManager { private sdk: ZaloSDK; constructor() { this.sdk = new ZaloSDK({ appId: process.env.ZALO_APP_ID!, appSecret: process.env.ZALO_APP_SECRET!, }); } async createCompleteArticle(accessToken: string) { try { // 1. Upload video first (if needed) const videoFile = new File([videoBuffer], 'demo.mp4'); const videoUpload = await this.sdk.videoUpload.uploadVideo(accessToken, videoFile); const videoResult = await this.sdk.videoUpload.waitForUploadCompletion( accessToken, videoUpload.token ); // 2. Create article with video const article = await this.sdk.article.createNormalArticle(accessToken, { type: ArticleType.NORMAL, title: "Complete Guide", author: "RedAI Team", description: "A complete guide with video content", cover: { cover_type: CoverType.PHOTO, photo_url: "https://example.com/cover.jpg", status: ArticleStatus.SHOW }, body: [ { type: BodyItemType.TEXT, content: "Introduction to our service..." }, { type: BodyItemType.VIDEO, video_id: videoResult.video_id }, { type: BodyItemType.TEXT, content: "Thank you for watching!" } ], status: ArticleStatus.SHOW }); // 3. Wait for article creation const articleProgress = await this.sdk.article.checkArticleProcess( accessToken, article.token ); return articleProgress; } catch (error) { console.error('Article creation error:', error); throw error; } } } ``` ### Update Article Status Update only the status of an existing article without modifying other content: ```typescript import { ArticleStatus, CommentStatus } from 'redai-zalo-sdk'; // Update article status to 'show' (publish) const publishResult = await article.updateArticleStatus( accessToken, 'article_id', ArticleStatus.SHOW ); // Update article status to 'hide' and disable comments const hideResult = await article.updateArticleStatus( accessToken, 'article_id', ArticleStatus.HIDE, CommentStatus.HIDE ); // Check update progress const progress = await article.checkArticleProcess( accessToken, publishResult.token ); ``` **Method Signature:** ```typescript updateArticleStatus( accessToken: string, articleId: string, status: ArticleStatus, comment?: CommentStatus ): Promise<ArticleUpdateResponse> ``` **Parameters:** - `accessToken`: OA access token - `articleId`: ID of the article to update - `status`: New article status (`'show'` or `'hide'`) - `comment`: Optional comment status (`'show'` or `'hide'`) **How it works:** 1. Retrieves current article details using `getArticleDetail()` 2. Preserves all existing content (title, body, cover, etc.) 3. Updates only the status and optionally comment status 4. Calls the appropriate update method based on article type **Benefits:** - ✅ Simple status-only updates without content modification - ✅ Preserves all existing article data - ✅ Automatic type detection (normal vs video articles) - ✅ Optional comment status control - ✅ Same progress tracking as full updates ## Validation Rules ### Normal Articles - Title: required, max 150 characters - Author: required, max 50 characters - Description: required, max 300 characters - Cover: required, must specify type and corresponding URL/ID - Body: required, at least one item ### Video Articles - Title: required, max 150 characters - Description: required, max 300 characters - Video ID: required, must be valid uploaded video - Avatar: required, thumbnail URL ### Video Files - Formats: MP4, AVI only - Size: max 50MB - Processing: asynchronous, use polling to check status ## API Reference For detailed API documentation, see the TypeScript definitions in the source code. All methods include comprehensive JSDoc comments with parameter descriptions and return types.