my-youtube-api 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -0
- package/dist/youtube-handlers/youtube-video-poster.d.ts +7 -1
- package/dist/youtube-handlers/youtube-video-poster.js +40 -1
- package/package.json +1 -1
- package/src/index.ts +4 -0
- package/src/youtube-handlers/youtube-video-poster.ts +48 -6
- package/src/youtube-handlers copy/youtube-video-poster.ts +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -4,4 +4,5 @@ import { YoutubeVideoHandler } from "./youtube-handlers/youtube-video-handler";
|
|
|
4
4
|
import { YoutubeVideoPoster } from "./youtube-handlers/youtube-video-poster";
|
|
5
5
|
export * from "./errors/youtube-api-errors";
|
|
6
6
|
import { isValidAccessToken, fetchNewAccessToken } from './utils';
|
|
7
|
+
export declare const createYoutubeVideoPoster: (access_token: string) => YoutubeVideoPoster;
|
|
7
8
|
export { YoutubeAccountHandler, YoutubeChannelHandler, YoutubeVideoHandler, YoutubeVideoPoster, isValidAccessToken, fetchNewAccessToken };
|
package/dist/index.js
CHANGED
|
@@ -10,4 +10,7 @@ in nextjs go to this package/"my-youtube-api-1.0.0.tgz"
|
|
|
10
10
|
*/
|
|
11
11
|
export * from "./errors/youtube-api-errors";
|
|
12
12
|
import { isValidAccessToken, fetchNewAccessToken } from './utils';
|
|
13
|
+
export const createYoutubeVideoPoster = (access_token) => {
|
|
14
|
+
return new YoutubeVideoPoster(access_token);
|
|
15
|
+
};
|
|
13
16
|
export { YoutubeAccountHandler, YoutubeChannelHandler, YoutubeVideoHandler, YoutubeVideoPoster, isValidAccessToken, fetchNewAccessToken };
|
|
@@ -47,7 +47,13 @@ export declare class YoutubeVideoPoster {
|
|
|
47
47
|
/**
|
|
48
48
|
* Upload a video from a Cloudinary URL to YouTube
|
|
49
49
|
*/
|
|
50
|
-
|
|
50
|
+
uploadFromCloudUrl2(videoUrl: string, metadata: VideoMetadata): Promise<YouTubeUploadResult>;
|
|
51
|
+
/**
|
|
52
|
+
* Upload a video from a Cloudinary URL to YouTube
|
|
53
|
+
* @param videoUrl URL of the video on Cloudinary
|
|
54
|
+
* @param metadata Video metadata
|
|
55
|
+
*/
|
|
56
|
+
uploadFromCloudUrl(videoUrl: string, metadata: VideoMetadata): Promise<youtube_v3.Schema$Video>;
|
|
51
57
|
/**
|
|
52
58
|
* Get video details
|
|
53
59
|
*/
|
|
@@ -227,7 +227,7 @@ export class YoutubeVideoPoster {
|
|
|
227
227
|
/**
|
|
228
228
|
* Upload a video from a Cloudinary URL to YouTube
|
|
229
229
|
*/
|
|
230
|
-
async
|
|
230
|
+
async uploadFromCloudUrl2(videoUrl, metadata) {
|
|
231
231
|
let videoStream = null;
|
|
232
232
|
try {
|
|
233
233
|
// Validate metadata first
|
|
@@ -292,6 +292,45 @@ export class YoutubeVideoPoster {
|
|
|
292
292
|
this.handleYouTubeError(error, "Unexpected error during YouTube video upload");
|
|
293
293
|
}
|
|
294
294
|
}
|
|
295
|
+
/**
|
|
296
|
+
* Upload a video from a Cloudinary URL to YouTube
|
|
297
|
+
* @param videoUrl URL of the video on Cloudinary
|
|
298
|
+
* @param metadata Video metadata
|
|
299
|
+
*/
|
|
300
|
+
async uploadFromCloudUrl(videoUrl, metadata) {
|
|
301
|
+
try {
|
|
302
|
+
// Fetch video as stream from Cloudinary
|
|
303
|
+
const response = await axios.get(videoUrl, { responseType: "stream" });
|
|
304
|
+
const videoStream = response.data;
|
|
305
|
+
// Prepare metadata payload
|
|
306
|
+
const metadataPayload = {
|
|
307
|
+
part: ["snippet", "status"],
|
|
308
|
+
requestBody: {
|
|
309
|
+
snippet: {
|
|
310
|
+
title: metadata.title.substring(0, 100),
|
|
311
|
+
description: (metadata.description || "").substring(0, 5000),
|
|
312
|
+
tags: (metadata.tags || []).slice(0, 5),
|
|
313
|
+
categoryId: metadata.categoryId || "22"
|
|
314
|
+
},
|
|
315
|
+
status: {
|
|
316
|
+
privacyStatus: metadata.privacyStatus || "private",
|
|
317
|
+
embeddable: metadata.embeddable !== false,
|
|
318
|
+
publicStatsViewable: metadata.publicStatsViewable !== false,
|
|
319
|
+
license: metadata.license || "youtube",
|
|
320
|
+
selfDeclaredMadeForKids: metadata.madeForKids || false
|
|
321
|
+
}
|
|
322
|
+
},
|
|
323
|
+
media: { body: videoStream }
|
|
324
|
+
};
|
|
325
|
+
// Upload video
|
|
326
|
+
const res = await this.youtube.videos.insert(metadataPayload);
|
|
327
|
+
return res.data;
|
|
328
|
+
}
|
|
329
|
+
catch (error) {
|
|
330
|
+
console.error("YouTube upload failed:", error.response?.data || error.message);
|
|
331
|
+
throw new Error(`YouTube upload failed: ${error.response?.data?.error?.message || error.message}`);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
295
334
|
/**
|
|
296
335
|
* Get video details
|
|
297
336
|
*/
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -12,6 +12,10 @@ in nextjs go to this package/"my-youtube-api-1.0.0.tgz"
|
|
|
12
12
|
export * from "./errors/youtube-api-errors";
|
|
13
13
|
import { isValidAccessToken, fetchNewAccessToken } from './utils'
|
|
14
14
|
|
|
15
|
+
export const createYoutubeVideoPoster = (access_token: string) => {
|
|
16
|
+
return new YoutubeVideoPoster(access_token);
|
|
17
|
+
}
|
|
18
|
+
|
|
15
19
|
export {
|
|
16
20
|
YoutubeAccountHandler,
|
|
17
21
|
YoutubeChannelHandler,
|
|
@@ -63,24 +63,24 @@ export class YoutubeVideoPoster {
|
|
|
63
63
|
case 'invalidCredentials':
|
|
64
64
|
case 'required':
|
|
65
65
|
throw new YouTubeAuthenticationError(message, apiError);
|
|
66
|
-
|
|
66
|
+
|
|
67
67
|
case 'quotaExceeded':
|
|
68
68
|
case 'dailyLimitExceeded':
|
|
69
69
|
case 'userRateLimitExceeded':
|
|
70
70
|
throw new YouTubeQuotaError(message, apiError);
|
|
71
|
-
|
|
71
|
+
|
|
72
72
|
case 'rateLimitExceeded':
|
|
73
73
|
case 'userRateLimitExceeded':
|
|
74
74
|
throw new YouTubeRateLimitError(message, apiError);
|
|
75
|
-
|
|
75
|
+
|
|
76
76
|
case 'invalidValue':
|
|
77
77
|
case 'invalid':
|
|
78
78
|
throw new YouTubeValidationError(message, apiError);
|
|
79
|
-
|
|
79
|
+
|
|
80
80
|
case 'processingFailed':
|
|
81
81
|
case 'failed':
|
|
82
82
|
throw new YouTubeProcessingError(message, apiError);
|
|
83
|
-
|
|
83
|
+
|
|
84
84
|
default:
|
|
85
85
|
throw new YouTubeApiError(message, `YOUTUBE_${reason?.toUpperCase()}`, error.code, apiError);
|
|
86
86
|
}
|
|
@@ -295,7 +295,7 @@ export class YoutubeVideoPoster {
|
|
|
295
295
|
/**
|
|
296
296
|
* Upload a video from a Cloudinary URL to YouTube
|
|
297
297
|
*/
|
|
298
|
-
public async
|
|
298
|
+
public async uploadFromCloudUrl2(videoUrl: string, metadata: VideoMetadata): Promise<YouTubeUploadResult> {
|
|
299
299
|
let videoStream: Readable | null = null;
|
|
300
300
|
|
|
301
301
|
try {
|
|
@@ -376,6 +376,48 @@ export class YoutubeVideoPoster {
|
|
|
376
376
|
}
|
|
377
377
|
}
|
|
378
378
|
|
|
379
|
+
/**
|
|
380
|
+
* Upload a video from a Cloudinary URL to YouTube
|
|
381
|
+
* @param videoUrl URL of the video on Cloudinary
|
|
382
|
+
* @param metadata Video metadata
|
|
383
|
+
*/
|
|
384
|
+
public async uploadFromCloudUrl(videoUrl: string, metadata: VideoMetadata): Promise<youtube_v3.Schema$Video> {
|
|
385
|
+
try {
|
|
386
|
+
// Fetch video as stream from Cloudinary
|
|
387
|
+
const response = await axios.get(videoUrl, { responseType: "stream" });
|
|
388
|
+
const videoStream = response.data as Readable;
|
|
389
|
+
|
|
390
|
+
// Prepare metadata payload
|
|
391
|
+
const metadataPayload: youtube_v3.Params$Resource$Videos$Insert = {
|
|
392
|
+
part: ["snippet", "status"],
|
|
393
|
+
requestBody: {
|
|
394
|
+
snippet: {
|
|
395
|
+
title: metadata.title.substring(0, 100),
|
|
396
|
+
description: (metadata.description || "").substring(0, 5000),
|
|
397
|
+
tags: (metadata.tags || []).slice(0, 5),
|
|
398
|
+
categoryId: metadata.categoryId || "22"
|
|
399
|
+
},
|
|
400
|
+
status: {
|
|
401
|
+
privacyStatus: metadata.privacyStatus || "private",
|
|
402
|
+
embeddable: metadata.embeddable !== false,
|
|
403
|
+
publicStatsViewable: metadata.publicStatsViewable !== false,
|
|
404
|
+
license: metadata.license || "youtube",
|
|
405
|
+
selfDeclaredMadeForKids: metadata.madeForKids || false
|
|
406
|
+
}
|
|
407
|
+
},
|
|
408
|
+
media: { body: videoStream }
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
// Upload video
|
|
412
|
+
const res = await this.youtube.videos.insert(metadataPayload);
|
|
413
|
+
return res.data;
|
|
414
|
+
|
|
415
|
+
} catch (error: any) {
|
|
416
|
+
console.error("YouTube upload failed:", error.response?.data || error.message);
|
|
417
|
+
throw new Error(`YouTube upload failed: ${error.response?.data?.error?.message || error.message}`);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
379
421
|
/**
|
|
380
422
|
* Get video details
|
|
381
423
|
*/
|
|
@@ -9,7 +9,7 @@ export interface VideoMetadata {
|
|
|
9
9
|
categoryId?: string;
|
|
10
10
|
privacyStatus?: "public" | "private" | "unlisted";
|
|
11
11
|
madeForKids?: boolean;
|
|
12
|
-
license?: "youtube" | "creativeCommon";
|
|
12
|
+
license?: "youtube" | "creativeCommon";
|
|
13
13
|
embeddable?: boolean;
|
|
14
14
|
publicStatsViewable?: boolean;
|
|
15
15
|
}
|