my-youtube-api 1.0.0

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.
@@ -0,0 +1,16 @@
1
+ export declare const YOUTUBE_BASE_URL = "https://www.googleapis.com";
2
+ export declare const RUPLOAD_URL = "https://rupload.facebook.com";
3
+ export declare enum FacebookErrorCode {
4
+ NO_ACCOUNT = "NO_ACCOUNT",
5
+ ACCESS_TOKEN_EXPIRED = "ACCESS_TOKEN_EXPIRED",
6
+ FAILED_GET_PAGES = "FAILED_GET_PAGES",
7
+ ACCESS_TOKEN_INVALID = "ACCESS_TOKEN_INVALID",
8
+ PAGE_NOT_FOUND = "PAGE_NOT_FOUND",
9
+ PAGE_ACCESS_TOKEN_EXPIRE = "PAGE_ACCESS_TOKEN_EXPIRE",
10
+ FAILED_FETCH_PAGES_FROM_API = "FAILED_FETCH_PAGES_FROM_API"
11
+ }
12
+ export declare class FacebookError extends Error {
13
+ code: FacebookErrorCode;
14
+ originalError?: any;
15
+ constructor(code: FacebookErrorCode, originalError?: any);
16
+ }
@@ -0,0 +1,29 @@
1
+ export const YOUTUBE_BASE_URL = "https://www.googleapis.com";
2
+ export const RUPLOAD_URL = 'https://rupload.facebook.com';
3
+ export var FacebookErrorCode;
4
+ (function (FacebookErrorCode) {
5
+ FacebookErrorCode["NO_ACCOUNT"] = "NO_ACCOUNT";
6
+ FacebookErrorCode["ACCESS_TOKEN_EXPIRED"] = "ACCESS_TOKEN_EXPIRED";
7
+ FacebookErrorCode["FAILED_GET_PAGES"] = "FAILED_GET_PAGES";
8
+ FacebookErrorCode["ACCESS_TOKEN_INVALID"] = "ACCESS_TOKEN_INVALID";
9
+ FacebookErrorCode["PAGE_NOT_FOUND"] = "PAGE_NOT_FOUND";
10
+ FacebookErrorCode["PAGE_ACCESS_TOKEN_EXPIRE"] = "PAGE_ACCESS_TOKEN_EXPIRE";
11
+ FacebookErrorCode["FAILED_FETCH_PAGES_FROM_API"] = "FAILED_FETCH_PAGES_FROM_API";
12
+ })(FacebookErrorCode || (FacebookErrorCode = {}));
13
+ const errorMessages = {
14
+ [FacebookErrorCode.NO_ACCOUNT]: 'Facebook account not connected',
15
+ [FacebookErrorCode.ACCESS_TOKEN_EXPIRED]: 'Facebook access token has expired',
16
+ [FacebookErrorCode.FAILED_GET_PAGES]: 'Failed to fetch Facebook pages',
17
+ [FacebookErrorCode.ACCESS_TOKEN_INVALID]: 'Facebook access token is invalid',
18
+ [FacebookErrorCode.PAGE_NOT_FOUND]: 'Facebook page not found',
19
+ [FacebookErrorCode.PAGE_ACCESS_TOKEN_EXPIRE]: 'Facebook page access token has expired',
20
+ [FacebookErrorCode.FAILED_FETCH_PAGES_FROM_API]: 'Failed to fetch pages from Facebook API'
21
+ };
22
+ export class FacebookError extends Error {
23
+ constructor(code, originalError) {
24
+ super(errorMessages[code]);
25
+ this.code = code;
26
+ this.originalError = originalError;
27
+ this.name = 'FacebookError';
28
+ }
29
+ }
@@ -0,0 +1,6 @@
1
+ import { YoutubeAccountHandler } from "./youtube-handlers/youtube-account-handler";
2
+ import { YoutubeChannelHandler } from "./youtube-handlers/youtube-channel-handler";
3
+ import { YoutubeVideoHandler } from "./youtube-handlers/youtube-video-handler";
4
+ import { YoutubeVideoPoster } from "./youtube-handlers/youtube-video-poster";
5
+ import { isValidAccessToken, fetchNewAccessToken } from './utils';
6
+ export { YoutubeAccountHandler, YoutubeChannelHandler, YoutubeVideoHandler, YoutubeVideoPoster, isValidAccessToken, fetchNewAccessToken };
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ import { YoutubeAccountHandler } from "./youtube-handlers/youtube-account-handler";
2
+ import { YoutubeChannelHandler } from "./youtube-handlers/youtube-channel-handler";
3
+ import { YoutubeVideoHandler } from "./youtube-handlers/youtube-video-handler";
4
+ import { YoutubeVideoPoster } from "./youtube-handlers/youtube-video-poster";
5
+ /*
6
+ npm run build
7
+ npm pack
8
+
9
+ in nextjs go to this package/"my-youtube-api-1.0.0.tgz"
10
+ */
11
+ import { isValidAccessToken, fetchNewAccessToken } from './utils';
12
+ export { YoutubeAccountHandler, YoutubeChannelHandler, YoutubeVideoHandler, YoutubeVideoPoster, isValidAccessToken, fetchNewAccessToken };
package/dist/test.d.ts ADDED
@@ -0,0 +1 @@
1
+ export {};
package/dist/test.js ADDED
@@ -0,0 +1,40 @@
1
+ import { YoutubeChannelHandler } from "./youtube-handlers/youtube-channel-handler";
2
+ import { YoutubeAnalyticsHandler } from "./youtube-handlers/youtube-channel-handler2";
3
+ import { YoutubeVideoHandler } from "./youtube-handlers/youtube-video-handler";
4
+ const access_token = "ya29.a0AQQ_BDSZ2rCrjvxUbkkVtbVtWdstheMCiFoBLDwCLcOkcPVdej3wmFbraxVoVuhTNd875VIOA_hjWj7bPom8AJbRzfDL3roL3OIaLVP2egffiMo0lPScLLK4RuwA16JmdVeJadeNiMofUtfhqdwjz9JRHQ2DBhUYRwzwCAZzPTX9kUU4d4v43TePdZ9Pm1AoCNnGLEQaCgYKAQYSARUSFQHGX2MiEjdmyiMSsAh6MyI_w17C8Q0206";
5
+ const channel_id = "UCfRRVg_MwvlFWqsvBUXrXcw";
6
+ const video_id = "J-Rn69UHm78";
7
+ /*
8
+ "main": "dist/index.js",
9
+ for nextjs:
10
+ in package json: "type": "module", "types": "dist/index.d.ts",
11
+ in tsconfig.json: "module": "ESNext",
12
+ for testing here:
13
+ in package json: remove "type": "module", and "type": "module"
14
+ in tsconfig.json: "module": "commonjs",
15
+ */
16
+ /*
17
+
18
+ npm run build
19
+ npm pack
20
+
21
+ in nextjs go to this package/"my-facebook-api-1.0.0.tgz"
22
+
23
+ */
24
+ const youtubeChannelHandler = new YoutubeChannelHandler(access_token, channel_id);
25
+ /* youtubeChannelHandler.getChannelStats().then((res)=>{
26
+ console.log('================================================');
27
+ console.log(res,'wwwwwwwwwwwwwww');
28
+
29
+ })
30
+ */
31
+ const youtubeAnalyticsHandlers = new YoutubeAnalyticsHandler(access_token, channel_id);
32
+ /* youtubeAnalyticsHandlers.fetchVideosList().then((res)=>{
33
+ console.log(res,'wwwwwwwwwwwwwwwwwwwwwwwwww');
34
+
35
+ }) */
36
+ const youvid = new YoutubeVideoHandler(access_token, video_id);
37
+ /* youvid.getYouTubeComments().then((res)=>{
38
+ console.log(res,res[0].replies,'eeeeeeeeeeeeeeeeeeeeeeeeeeeee');
39
+
40
+ }) */
@@ -0,0 +1,27 @@
1
+ interface AccessTokenType {
2
+ access_token: string;
3
+ refresh_token: string;
4
+ expires_in: number;
5
+ refresh_token_expires_in: number;
6
+ expires_at: number;
7
+ }
8
+ /**
9
+ * Checks whether a Google access token is still valid.
10
+ * @param accessToken - The access token to verify.
11
+ * @returns true if valid, false otherwise.
12
+ */
13
+ export declare function isValidAccessToken(accessToken: string | null): Promise<boolean>;
14
+ /**
15
+ * Refreshes an expired access token using a valid refresh token
16
+ * @param valid_refresh_token - The refresh token obtained during initial OAuth2 authentication
17
+ * @returns Promise resolving to AccessTokenType object containing new tokens and expiration information
18
+ * @throws {AxiosError} If the token refresh request fails (invalid refresh token, client credentials, etc.)
19
+ *
20
+ * @remarks
21
+ * All time-related values are returned in seconds:
22
+ * - expires_in: Lifetime of the access token in seconds (typically 3600)
23
+ * - expires_at: Unix timestamp in seconds when the access token will expire
24
+ * - refresh_token_expires_in: Lifetime of the refresh token in seconds (if provided by Google)
25
+ */
26
+ export declare function fetchNewAccessToken(valid_refresh_token: string, google_client_id: string, google_client_secret: string): Promise<AccessTokenType>;
27
+ export {};
package/dist/utils.js ADDED
@@ -0,0 +1,61 @@
1
+ import axios from "axios";
2
+ /**
3
+ * Checks whether a Google access token is still valid.
4
+ * @param accessToken - The access token to verify.
5
+ * @returns true if valid, false otherwise.
6
+ */
7
+ export async function isValidAccessToken(accessToken) {
8
+ if (!accessToken)
9
+ return false;
10
+ try {
11
+ const response = await axios.get("https://www.googleapis.com/oauth2/v1/tokeninfo", {
12
+ params: { access_token: accessToken },
13
+ });
14
+ // The tokeninfo endpoint returns an error if the token is invalid,
15
+ // so if we get here, it's valid.
16
+ return response.status === 200;
17
+ }
18
+ catch (error) {
19
+ return false; // expired or invalid token
20
+ }
21
+ }
22
+ /**
23
+ * Refreshes an expired access token using a valid refresh token
24
+ * @param valid_refresh_token - The refresh token obtained during initial OAuth2 authentication
25
+ * @returns Promise resolving to AccessTokenType object containing new tokens and expiration information
26
+ * @throws {AxiosError} If the token refresh request fails (invalid refresh token, client credentials, etc.)
27
+ *
28
+ * @remarks
29
+ * All time-related values are returned in seconds:
30
+ * - expires_in: Lifetime of the access token in seconds (typically 3600)
31
+ * - expires_at: Unix timestamp in seconds when the access token will expire
32
+ * - refresh_token_expires_in: Lifetime of the refresh token in seconds (if provided by Google)
33
+ */
34
+ export async function fetchNewAccessToken(valid_refresh_token, google_client_id, google_client_secret) {
35
+ try {
36
+ const params = new URLSearchParams({
37
+ client_id: google_client_id,
38
+ client_secret: google_client_secret,
39
+ grant_type: "refresh_token",
40
+ refresh_token: valid_refresh_token,
41
+ });
42
+ const response = await axios.post("https://oauth2.googleapis.com/token", params.toString(), { headers: { "Content-Type": "application/x-www-form-urlencoded" } });
43
+ const data = response.data;
44
+ const access_token = data.access_token;
45
+ const expires_in = data.expires_in;
46
+ const refresh_token = data.refresh_token ?? valid_refresh_token;
47
+ const refresh_token_expires_in = data.refresh_token_expires_in;
48
+ const expires_at = Math.floor(Date.now() / 1000) + expires_in;
49
+ return {
50
+ access_token,
51
+ expires_at,
52
+ refresh_token_expires_in,
53
+ expires_in,
54
+ refresh_token,
55
+ };
56
+ }
57
+ catch (error) {
58
+ console.error("❌ Failed to refresh access token:", error.response?.data || error.message);
59
+ throw error;
60
+ }
61
+ }
@@ -0,0 +1,21 @@
1
+ interface Channel {
2
+ channelId: string;
3
+ title: string;
4
+ description: string;
5
+ thumbnail: string;
6
+ }
7
+ export declare class YoutubeAccountHandler {
8
+ private account_access_token;
9
+ /**
10
+ * Creates a new YoutubeAccountHandler instance
11
+ * @param account_access_token - The current access token for YouTube API authentication
12
+ */
13
+ constructor(account_access_token: string);
14
+ /**
15
+ * Fetches the list of YouTube channels associated with the authenticated account
16
+ * @returns Promise resolving to an array of Channel objects containing channel details
17
+ * @throws {AxiosError} If the API request fails due to authentication or other errors
18
+ */
19
+ fetchChannels(): Promise<Channel[]>;
20
+ }
21
+ export {};
@@ -0,0 +1,33 @@
1
+ import axios from "axios";
2
+ import { YOUTUBE_BASE_URL } from "../error-utils";
3
+ export class YoutubeAccountHandler {
4
+ /**
5
+ * Creates a new YoutubeAccountHandler instance
6
+ * @param account_access_token - The current access token for YouTube API authentication
7
+ */
8
+ constructor(account_access_token) {
9
+ this.account_access_token = account_access_token;
10
+ }
11
+ /**
12
+ * Fetches the list of YouTube channels associated with the authenticated account
13
+ * @returns Promise resolving to an array of Channel objects containing channel details
14
+ * @throws {AxiosError} If the API request fails due to authentication or other errors
15
+ */
16
+ async fetchChannels() {
17
+ const url = `${YOUTUBE_BASE_URL}/youtube/v3/channels`;
18
+ const params = {
19
+ part: "snippet,contentDetails,statistics",
20
+ mine: true,
21
+ };
22
+ const access_token = this.account_access_token;
23
+ const headers = { Authorization: `Bearer ${access_token}` };
24
+ const res = await axios.get(url, { params, headers });
25
+ const channels = res.data.items.map((ch) => ({
26
+ channelId: ch.id,
27
+ title: ch.snippet.title,
28
+ description: ch.snippet.description,
29
+ thumbnail: ch.snippet.thumbnails?.default?.url,
30
+ }));
31
+ return channels;
32
+ }
33
+ }
@@ -0,0 +1,65 @@
1
+ interface VideoAnalytics {
2
+ videoId: string;
3
+ title: string;
4
+ views: number;
5
+ likes: number;
6
+ comments: number;
7
+ publishedAt: string;
8
+ thumbnail: string;
9
+ }
10
+ interface ChannelAnalytics {
11
+ channelId: string;
12
+ title: string;
13
+ description: string;
14
+ thumbnail: string;
15
+ subscriberCount: number;
16
+ viewCount: number;
17
+ videoCount: number;
18
+ hiddenSubscriberCount: boolean;
19
+ }
20
+ interface AudienceAnalytics {
21
+ views: number;
22
+ estimatedMinutesWatched: number;
23
+ averageViewDuration: number;
24
+ subscribersGained: number;
25
+ subscribersLost: number;
26
+ }
27
+ interface VideoAnalytics {
28
+ videoId: string;
29
+ title: string;
30
+ views: number;
31
+ likes: number;
32
+ comments: number;
33
+ publishedAt: string;
34
+ thumbneil?: string;
35
+ videoType: "short" | "regular";
36
+ }
37
+ interface ChannelRevenue {
38
+ estimatedRevenue: number;
39
+ currency: string;
40
+ startDate: string;
41
+ endDate: string;
42
+ }
43
+ export declare class YoutubeChannelHandler {
44
+ private access_token;
45
+ private channel_id;
46
+ constructor(access_token: string, channel_id: string);
47
+ /**
48
+ * Fetches basic channel statistics and information
49
+ * @returns Channel analytics including subscriber count, view count, and video count
50
+ */
51
+ fetchChannelAnalytics(): Promise<ChannelAnalytics>;
52
+ /**
53
+ * Fetches analytics for all videos in the channel
54
+ * @param maxResults Maximum number of videos to fetch (default: 50, max: 50)
55
+ * @returns Array of video analytics including views, likes, and comments
56
+ */
57
+ fetchVideos(maxResults?: number): Promise<VideoAnalytics[]>;
58
+ /**
59
+ * Fetches audience analytics and engagement metrics for the channel
60
+ * @returns Audience analytics including view duration and subscriber changes
61
+ */
62
+ fetchAudienceAnalytics(): Promise<AudienceAnalytics>;
63
+ fetchChannelRevenue(startDate?: string, endDate?: string): Promise<ChannelRevenue>;
64
+ }
65
+ export {};
@@ -0,0 +1,193 @@
1
+ import axios from "axios";
2
+ /*
3
+ . Enable YouTube Analytics API
4
+
5
+ Go to your Google Cloud Console → APIs & Services → Library → Search for and enable:
6
+
7
+ YouTube Analytics API
8
+
9
+ YouTube Reporting API
10
+
11
+ for report and analytics
12
+ */
13
+ export class YoutubeChannelHandler {
14
+ constructor(access_token, channel_id) {
15
+ this.access_token = access_token;
16
+ this.channel_id = channel_id;
17
+ }
18
+ /**
19
+ * Fetches basic channel statistics and information
20
+ * @returns Channel analytics including subscriber count, view count, and video count
21
+ */
22
+ async fetchChannelAnalytics() {
23
+ const response = await axios.get("https://www.googleapis.com/youtube/v3/channels", {
24
+ params: {
25
+ part: "snippet,statistics,contentDetails",
26
+ mine: true // This gets the authenticated user's channel
27
+ },
28
+ headers: { Authorization: `Bearer ${this.access_token}` },
29
+ });
30
+ const channel = response.data.items[0];
31
+ return {
32
+ channelId: channel.id,
33
+ title: channel.snippet.title,
34
+ description: channel.snippet.description,
35
+ thumbnail: channel.snippet.thumbnails?.high?.url,
36
+ subscriberCount: parseInt(channel.statistics.subscriberCount || '0'),
37
+ viewCount: parseInt(channel.statistics.viewCount || '0'),
38
+ videoCount: parseInt(channel.statistics.videoCount || '0'),
39
+ hiddenSubscriberCount: channel.statistics.hiddenSubscriberCount || false
40
+ };
41
+ }
42
+ /**
43
+ * Fetches analytics for all videos in the channel
44
+ * @param maxResults Maximum number of videos to fetch (default: 50, max: 50)
45
+ * @returns Array of video analytics including views, likes, and comments
46
+ */
47
+ async fetchVideos(maxResults = 50) {
48
+ // 1️⃣ Get uploads playlist ID
49
+ const channelRes = await axios.get("https://www.googleapis.com/youtube/v3/channels", {
50
+ params: { part: "contentDetails", id: this.channel_id },
51
+ headers: { Authorization: `Bearer ${this.access_token}` },
52
+ });
53
+ const uploadsPlaylistId = channelRes.data.items[0]?.contentDetails?.relatedPlaylists?.uploads;
54
+ if (!uploadsPlaylistId)
55
+ return [];
56
+ // 2️⃣ Fetch videos from the uploads playlist
57
+ const videosRes = await axios.get("https://www.googleapis.com/youtube/v3/playlistItems", {
58
+ params: {
59
+ part: "snippet,contentDetails",
60
+ playlistId: uploadsPlaylistId,
61
+ maxResults: Math.min(maxResults, 50),
62
+ },
63
+ headers: { Authorization: `Bearer ${this.access_token}` },
64
+ });
65
+ const videoIds = videosRes.data.items.map((v) => v.contentDetails.videoId);
66
+ if (videoIds.length === 0)
67
+ return [];
68
+ // 3️⃣ Fetch analytics & contentDetails for each video
69
+ const analyticsRes = await axios.get("https://www.googleapis.com/youtube/v3/videos", {
70
+ params: {
71
+ part: "snippet,statistics,contentDetails",
72
+ id: videoIds.join(","),
73
+ maxResults: Math.min(maxResults, 50),
74
+ },
75
+ headers: { Authorization: `Bearer ${this.access_token}` },
76
+ });
77
+ return analyticsRes.data.items.map((video) => {
78
+ // Convert ISO 8601 duration to seconds
79
+ const duration = video.contentDetails?.duration || "PT0S";
80
+ const match = duration.match(/PT(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?/);
81
+ const seconds = (parseInt(match?.[1] || "0") * 3600) +
82
+ (parseInt(match?.[2] || "0") * 60) +
83
+ parseInt(match?.[3] || "0");
84
+ return {
85
+ videoId: video.id,
86
+ title: video.snippet.title,
87
+ views: parseInt(video.statistics.viewCount || 0),
88
+ likes: parseInt(video.statistics.likeCount || 0),
89
+ comments: parseInt(video.statistics.commentCount || 0),
90
+ publishedAt: video.snippet.publishedAt,
91
+ thumbnail: video.snippet.thumbnails?.high?.url,
92
+ videoType: seconds < 60 ? "short" : "regular",
93
+ };
94
+ });
95
+ }
96
+ /**
97
+ * Fetches audience analytics and engagement metrics for the channel
98
+ * @returns Audience analytics including view duration and subscriber changes
99
+ */
100
+ async fetchAudienceAnalytics() {
101
+ try {
102
+ // 1️⃣ Compute proper date range (last 30 days)
103
+ const endDate = new Date();
104
+ const startDate = new Date();
105
+ startDate.setDate(endDate.getDate() - 30);
106
+ const formatDate = (date) => date.toISOString().split("T")[0]; // YYYY-MM-DD
107
+ // 2️⃣ Call YouTube Analytics API
108
+ const response = await axios.get("https://youtubeanalytics.googleapis.com/v2/reports", {
109
+ params: {
110
+ ids: `channel==${this.channel_id}`,
111
+ startDate: formatDate(startDate),
112
+ endDate: formatDate(endDate),
113
+ metrics: "views,estimatedMinutesWatched,averageViewDuration,subscribersGained,subscribersLost",
114
+ dimensions: "day",
115
+ },
116
+ headers: { Authorization: `Bearer ${this.access_token}` },
117
+ });
118
+ const rows = response.data.rows || [];
119
+ if (rows.length === 0) {
120
+ return {
121
+ views: 0,
122
+ estimatedMinutesWatched: 0,
123
+ averageViewDuration: 0,
124
+ subscribersGained: 0,
125
+ subscribersLost: 0,
126
+ };
127
+ }
128
+ // 3️⃣ Sum up all daily metrics
129
+ const totals = rows.reduce((acc, row) => ({
130
+ views: acc.views + Number(row[1] || 0),
131
+ estimatedMinutesWatched: acc.estimatedMinutesWatched + Number(row[2] || 0),
132
+ averageViewDuration: acc.averageViewDuration + Number(row[3] || 0),
133
+ subscribersGained: acc.subscribersGained + Number(row[4] || 0),
134
+ subscribersLost: acc.subscribersLost + Number(row[5] || 0),
135
+ }), {
136
+ views: 0,
137
+ estimatedMinutesWatched: 0,
138
+ averageViewDuration: 0,
139
+ subscribersGained: 0,
140
+ subscribersLost: 0,
141
+ });
142
+ // 4️⃣ Return final analytics
143
+ return {
144
+ views: totals.views,
145
+ estimatedMinutesWatched: totals.estimatedMinutesWatched,
146
+ averageViewDuration: totals.averageViewDuration / rows.length, // Average of averages
147
+ subscribersGained: totals.subscribersGained,
148
+ subscribersLost: totals.subscribersLost,
149
+ };
150
+ }
151
+ catch (err) {
152
+ console.error("Error fetching audience analytics:", err);
153
+ return {
154
+ views: 0,
155
+ estimatedMinutesWatched: 0,
156
+ averageViewDuration: 0,
157
+ subscribersGained: 0,
158
+ subscribersLost: 0,
159
+ };
160
+ }
161
+ }
162
+ async fetchChannelRevenue(startDate = "2023-01-01", endDate = new Date().toISOString().split("T")[0]) {
163
+ try {
164
+ const response = await axios.get("https://youtubeanalytics.googleapis.com/v2/reports", {
165
+ params: {
166
+ ids: `channel==${this.channel_id}`,
167
+ startDate,
168
+ endDate,
169
+ metrics: "estimatedRevenue",
170
+ dimensions: "day", // optional: can remove to get total
171
+ currency: "USD"
172
+ },
173
+ headers: {
174
+ Authorization: `Bearer ${this.access_token}`
175
+ }
176
+ });
177
+ // Sum revenue if using "day" dimension
178
+ const totalRevenue = response.data.rows
179
+ ? response.data.rows.reduce((acc, row) => acc + parseFloat(row[1] || 0), 0)
180
+ : 0;
181
+ return {
182
+ estimatedRevenue: totalRevenue,
183
+ currency: "USD",
184
+ startDate,
185
+ endDate
186
+ };
187
+ }
188
+ catch (err) {
189
+ console.error("Failed to fetch channel revenue:", err.response?.data || err.message);
190
+ return { estimatedRevenue: 0, currency: "USD", startDate, endDate };
191
+ }
192
+ }
193
+ }
@@ -0,0 +1,65 @@
1
+ interface GrowthMetrics {
2
+ subscribers: number;
3
+ totalVideoViews: number;
4
+ estimatedRevenue: number;
5
+ videosCount: number;
6
+ period: string;
7
+ }
8
+ interface VideoPerformance {
9
+ videoId: string;
10
+ title: string;
11
+ publishedAt: string;
12
+ views: number;
13
+ watchTime: number;
14
+ avgViewDuration: number;
15
+ likes: number;
16
+ dislikes: number;
17
+ comments: number;
18
+ shares: number;
19
+ thumbnail: string;
20
+ }
21
+ interface PublishedVideosStats {
22
+ totalViews: number;
23
+ totalLikes: number;
24
+ totalDislikes: number;
25
+ totalComments: number;
26
+ totalShares: number;
27
+ totalVideos: number;
28
+ averageEngagementRate: number;
29
+ period: string;
30
+ }
31
+ export declare class YoutubeAnalyticsHandler {
32
+ private access_token;
33
+ private channel_id;
34
+ constructor(access_token: string, channel_id: string);
35
+ /**
36
+ * Fetches growth metrics for the channel over a specified period
37
+ * @param period Time period for growth analysis (7days, 30days, 90days, 365days)
38
+ * @returns Growth metrics including subscribers, views, revenue, and video count
39
+ * . Enable YouTube Analytics API
40
+
41
+ Go to your Google Cloud Console → APIs & Services → Library → Search for and enable:
42
+
43
+ YouTube Analytics API
44
+
45
+ YouTube Reporting API
46
+ */
47
+ fetchGrowthMetrics(period?: string): Promise<GrowthMetrics>;
48
+ /**
49
+ * Fetches aggregated statistics for all published videos in a period
50
+ * @param period Time period for analysis (7days, 30days, 90days)
51
+ * @returns Combined statistics for all published videos
52
+ */
53
+ fetchPublishedVideosStats(period?: string): Promise<PublishedVideosStats>;
54
+ /**
55
+ * Fetches detailed list of videos with comprehensive performance metrics
56
+ * @param maxResults Maximum number of videos to return (default: 50, max: 50)
57
+ * @returns Array of video performance metrics
58
+ */
59
+ fetchVideosList(maxResults?: number): Promise<VideoPerformance[]>;
60
+ private fetchChannelBasicStats;
61
+ private fetchVideosPublishedInPeriod;
62
+ private fetchVideosDetailedStats;
63
+ private getStartDate;
64
+ }
65
+ export {};