@zapier/youtube-connector 0.0.0 → 0.0.1

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.js ADDED
@@ -0,0 +1,1550 @@
1
+ // index.ts
2
+ import { defineConnector, toFunctions } from "@zapier/connectors-sdk";
3
+
4
+ // connections.ts
5
+ import {
6
+ defineEnvTokenResolver,
7
+ zapierConnectionResolver
8
+ } from "@zapier/connectors-sdk";
9
+ var connectionResolvers = {
10
+ youtube: [zapierConnectionResolver, defineEnvTokenResolver()]
11
+ };
12
+
13
+ // scripts/addVideoToPlaylist.ts
14
+ import { defineTool, handleIfScriptMain } from "@zapier/connectors-sdk";
15
+ import { z as z2 } from "zod";
16
+
17
+ // lib/youtube.ts
18
+ import { ConnectorHttpError } from "@zapier/connectors-sdk";
19
+ import { z } from "zod";
20
+ var ThumbnailsSchema = z.record(
21
+ z.string(),
22
+ z.object({
23
+ url: z.string().optional(),
24
+ width: z.number().int().optional(),
25
+ height: z.number().int().optional()
26
+ })
27
+ ).describe("Thumbnail images keyed by size (default, medium, high, ...).");
28
+ var ResourceIdSchema = z.object({
29
+ kind: z.string().describe(
30
+ "The referenced resource type, e.g. youtube#video or youtube#channel."
31
+ ).optional(),
32
+ videoId: z.string().describe("Set when kind is youtube#video.").optional(),
33
+ channelId: z.string().describe("Set when kind is youtube#channel.").optional()
34
+ });
35
+ var NextPageToken = z.string().describe("Cursor for the next page; absent when there are no more results.").nullable().optional();
36
+ var VideoSchema = z.object({
37
+ id: z.string().describe("The 11-char video id."),
38
+ snippet: z.object({
39
+ title: z.string().optional(),
40
+ description: z.string().optional(),
41
+ channelId: z.string().optional(),
42
+ channelTitle: z.string().optional(),
43
+ publishedAt: z.string().optional(),
44
+ tags: z.array(z.string()).optional(),
45
+ categoryId: z.string().optional(),
46
+ defaultLanguage: z.string().optional(),
47
+ defaultAudioLanguage: z.string().optional(),
48
+ liveBroadcastContent: z.string().optional(),
49
+ thumbnails: ThumbnailsSchema.optional()
50
+ }).optional(),
51
+ contentDetails: z.object({
52
+ duration: z.string().describe("ISO 8601 duration, e.g. PT4M13S (4 min 13 s).").optional(),
53
+ definition: z.string().describe("hd or sd.").optional(),
54
+ caption: z.string().describe(
55
+ '"true" or "false" (string) \u2014 whether captions are available.'
56
+ ).optional(),
57
+ licensedContent: z.boolean().optional()
58
+ }).optional(),
59
+ statistics: z.object({
60
+ // Counts are returned as strings; likeCount/commentCount are absent when hidden.
61
+ viewCount: z.string().optional(),
62
+ likeCount: z.string().optional(),
63
+ commentCount: z.string().optional(),
64
+ favoriteCount: z.string().optional()
65
+ }).optional(),
66
+ status: z.object({
67
+ uploadStatus: z.string().describe("uploaded, processed, failed, rejected, or deleted.").optional(),
68
+ privacyStatus: z.string().describe("public, unlisted, or private.").optional(),
69
+ publishAt: z.string().describe("Scheduled publish time, if a private scheduled upload.").optional(),
70
+ madeForKids: z.boolean().optional(),
71
+ license: z.string().optional()
72
+ }).optional()
73
+ }).describe("A YouTube video resource.");
74
+ var PlaylistSchema = z.object({
75
+ id: z.string().describe(
76
+ "The playlist id (PL...). Use with addVideoToPlaylist / listPlaylistItems."
77
+ ),
78
+ snippet: z.object({
79
+ title: z.string().optional(),
80
+ description: z.string().optional(),
81
+ channelId: z.string().optional(),
82
+ channelTitle: z.string().optional(),
83
+ publishedAt: z.string().optional(),
84
+ thumbnails: ThumbnailsSchema.optional()
85
+ }).optional(),
86
+ status: z.object({
87
+ privacyStatus: z.string().optional()
88
+ }).optional(),
89
+ contentDetails: z.object({
90
+ itemCount: z.number().int().describe("Number of videos in the playlist.").optional()
91
+ }).optional()
92
+ }).describe("A YouTube playlist resource.");
93
+ var PlaylistItemSchema = z.object({
94
+ id: z.string().describe(
95
+ "The playlistItem id (use with removeVideoFromPlaylist \u2014 distinct from the video id)."
96
+ ),
97
+ snippet: z.object({
98
+ playlistId: z.string().optional(),
99
+ position: z.number().int().optional(),
100
+ title: z.string().optional(),
101
+ description: z.string().optional(),
102
+ channelId: z.string().optional(),
103
+ channelTitle: z.string().optional(),
104
+ publishedAt: z.string().optional(),
105
+ resourceId: ResourceIdSchema.optional(),
106
+ thumbnails: ThumbnailsSchema.optional()
107
+ }).optional(),
108
+ contentDetails: z.object({
109
+ videoId: z.string().optional(),
110
+ videoPublishedAt: z.string().optional()
111
+ }).optional(),
112
+ status: z.object({
113
+ privacyStatus: z.string().optional()
114
+ }).optional()
115
+ }).describe("A video entry within a playlist.");
116
+ var CommentSchema = z.object({
117
+ id: z.string().describe("The comment id."),
118
+ snippet: z.object({
119
+ textDisplay: z.string().describe("The comment text as HTML (may contain links/formatting).").optional(),
120
+ textOriginal: z.string().describe("The raw comment text as written.").optional(),
121
+ authorDisplayName: z.string().optional(),
122
+ authorChannelId: z.object({ value: z.string().optional() }).optional(),
123
+ likeCount: z.number().int().optional(),
124
+ publishedAt: z.string().optional(),
125
+ updatedAt: z.string().optional(),
126
+ parentId: z.string().describe(
127
+ "For a reply, the id of the top-level comment it replies to."
128
+ ).optional()
129
+ }).optional()
130
+ }).describe("A YouTube comment.");
131
+ var CommentThreadSchema = z.object({
132
+ id: z.string().describe("The comment thread id (use as parentId for replyToComment)."),
133
+ snippet: z.object({
134
+ videoId: z.string().optional(),
135
+ totalReplyCount: z.number().int().optional(),
136
+ isPublic: z.boolean().optional(),
137
+ topLevelComment: CommentSchema.optional()
138
+ }).optional(),
139
+ replies: z.object({
140
+ comments: z.array(CommentSchema).optional()
141
+ }).describe(
142
+ "A sample of replies (not exhaustive \u2014 page more via listComments)."
143
+ ).optional()
144
+ }).describe("A top-level comment thread on a video.");
145
+ var ChannelSchema = z.object({
146
+ id: z.string().describe("The channel id (UC...)."),
147
+ snippet: z.object({
148
+ title: z.string().optional(),
149
+ description: z.string().optional(),
150
+ customUrl: z.string().describe("The channel's @handle / custom URL.").optional(),
151
+ publishedAt: z.string().optional(),
152
+ country: z.string().optional(),
153
+ thumbnails: ThumbnailsSchema.optional()
154
+ }).optional(),
155
+ contentDetails: z.object({
156
+ relatedPlaylists: z.object({
157
+ uploads: z.string().describe(
158
+ "The channel's uploads playlist id \u2014 pass to listPlaylistItems to list the channel's videos."
159
+ ).optional(),
160
+ likes: z.string().optional()
161
+ }).optional()
162
+ }).optional(),
163
+ statistics: z.object({
164
+ // Counts returned as strings; subscriberCount is suppressed when hiddenSubscriberCount is true.
165
+ viewCount: z.string().optional(),
166
+ subscriberCount: z.string().optional(),
167
+ hiddenSubscriberCount: z.boolean().optional(),
168
+ videoCount: z.string().optional()
169
+ }).optional()
170
+ }).describe("A YouTube channel resource.");
171
+ var VideoCategorySchema = z.object({
172
+ id: z.string().describe("The category id to pass as categoryId on a video."),
173
+ snippet: z.object({
174
+ title: z.string().optional(),
175
+ assignable: z.boolean().describe(
176
+ "Whether the category can be assigned to a video. Only assignable categories are usable."
177
+ ).optional()
178
+ }).optional()
179
+ }).describe("An assignable video category.");
180
+ var SubscriptionSchema = z.object({
181
+ id: z.string().describe(
182
+ "The subscription id (use with unsubscribeFromChannel \u2014 distinct from the channel id)."
183
+ ),
184
+ snippet: z.object({
185
+ title: z.string().describe("The subscribed channel's title.").optional(),
186
+ description: z.string().optional(),
187
+ publishedAt: z.string().optional(),
188
+ resourceId: ResourceIdSchema.optional(),
189
+ thumbnails: ThumbnailsSchema.optional()
190
+ }).optional(),
191
+ contentDetails: z.object({
192
+ totalItemCount: z.number().int().optional(),
193
+ newItemCount: z.number().int().optional()
194
+ }).optional()
195
+ }).describe("A channel subscription.");
196
+ var CaptionSchema = z.object({
197
+ id: z.string().describe("The caption track id (use with downloadCaption)."),
198
+ snippet: z.object({
199
+ videoId: z.string().optional(),
200
+ language: z.string().describe("BCP-47 language code of the track, e.g. en.").optional(),
201
+ name: z.string().describe("The track name/label.").optional(),
202
+ trackKind: z.string().describe("standard, ASR (auto-generated), or forced.").optional(),
203
+ status: z.string().describe("serving, syncing, or failed.").optional(),
204
+ isAutoSynced: z.boolean().optional(),
205
+ lastUpdated: z.string().optional()
206
+ }).optional()
207
+ }).describe("A caption track on a video.");
208
+ var SearchResultSchema = z.object({
209
+ id: z.object({
210
+ kind: z.string().optional(),
211
+ videoId: z.string().optional(),
212
+ channelId: z.string().optional(),
213
+ playlistId: z.string().optional()
214
+ }).describe("The matched resource id; id.videoId is the video.").optional(),
215
+ snippet: z.object({
216
+ title: z.string().optional(),
217
+ description: z.string().optional(),
218
+ channelId: z.string().optional(),
219
+ channelTitle: z.string().optional(),
220
+ publishedAt: z.string().optional(),
221
+ liveBroadcastContent: z.string().describe("none, upcoming, or live.").optional(),
222
+ thumbnails: ThumbnailsSchema.optional()
223
+ }).optional()
224
+ }).describe("A lightweight search hit (id + snippet only).");
225
+ var SuccessResultSchema = z.object({ success: z.literal(true) }).describe(
226
+ "Result for an operation with an empty API body (delete/rate/unsubscribe). success is synthesized."
227
+ );
228
+ var QUOTA_REASONS = /* @__PURE__ */ new Set(["quotaExceeded", "dailyLimitExceeded"]);
229
+ var RATE_LIMIT_REASONS = /* @__PURE__ */ new Set([
230
+ "rateLimitExceeded",
231
+ "userRateLimitExceeded",
232
+ "servingLimitExceeded"
233
+ ]);
234
+ async function readBody(res) {
235
+ let text;
236
+ try {
237
+ text = await res.text();
238
+ } catch {
239
+ return void 0;
240
+ }
241
+ if (text === "") return "";
242
+ try {
243
+ return JSON.parse(text);
244
+ } catch {
245
+ return text;
246
+ }
247
+ }
248
+ async function throwForYouTube(res, toolName) {
249
+ if (res.ok) return res;
250
+ const body = await readBody(res);
251
+ const err = body?.error;
252
+ const reason = err?.errors?.[0]?.reason;
253
+ const apiMessage = err?.message;
254
+ const prefix = `YouTube ${toolName} ${res.status}`;
255
+ let message;
256
+ if (res.status === 401) {
257
+ message = `${prefix}: invalid or expired credentials. Reconnect YouTube.`;
258
+ } else if (res.status === 403 && reason && QUOTA_REASONS.has(reason)) {
259
+ message = `${prefix}: ${reason} \u2014 the daily YouTube API quota is exhausted (no Retry-After is sent; the quota resets once per day). Do not retry today; stop and report the quota limit.`;
260
+ } else if (res.status === 429 || res.status === 403 && reason && RATE_LIMIT_REASONS.has(reason)) {
261
+ message = `${prefix}: ${reason ?? "rateLimitExceeded"} \u2014 short-term rate limit. Back off and retry with jitter.`;
262
+ } else if (res.status === 403 && reason === "insufficientPermissions") {
263
+ message = `${prefix}: insufficientPermissions \u2014 the connection's OAuth scope is too narrow. Reconnect YouTube with the access this tool needs (comment and caption operations require the youtube.force-ssl scope).`;
264
+ } else if (res.status === 403) {
265
+ message = `${prefix}: ${reason ?? "forbidden"} \u2014 ${apiMessage ?? "access denied"}. This is either a missing OAuth scope (reconnect YouTube with the needed access \u2014 comment/caption writes need youtube.force-ssl) or you do not own this resource (reconnecting won't help; you can only modify videos, playlists, and subscriptions you own).`;
266
+ } else if (res.status === 404) {
267
+ message = `${prefix}: ${reason ?? "notFound"} \u2014 ${apiMessage ?? "the resource does not exist"}. Verify the id (resolve channels via getChannel, playlists via listPlaylists, videos via searchVideos/getVideo).`;
268
+ } else {
269
+ message = `${prefix}: ${apiMessage ?? reason ?? "request failed"}`;
270
+ }
271
+ throw ConnectorHttpError.fromResponseBody(res, body, { message });
272
+ }
273
+ function hasYouTubeReason(body, reason) {
274
+ const err = body?.error;
275
+ return err?.errors?.some((e) => e.reason === reason) ?? false;
276
+ }
277
+
278
+ // scripts/addVideoToPlaylist.ts
279
+ var inputSchema = z2.object({
280
+ snippet: z2.object({
281
+ playlistId: z2.string().describe(
282
+ "The id of the playlist to add the video to (from listPlaylists; you must own it)."
283
+ ),
284
+ resourceId: z2.object({
285
+ kind: z2.string().describe("Always youtube#video for adding a video.").default("youtube#video"),
286
+ videoId: z2.string().describe("The 11-char id of the video to add.")
287
+ }).strict().describe(
288
+ "The video to add. Set kind to youtube#video and videoId to the 11-char video id."
289
+ ),
290
+ position: z2.number().int().describe("0-based insert position. Omit to append at the end.").optional()
291
+ }).strict(),
292
+ part: z2.string().describe("Resource parts being written. Leave as the default.").default("snippet")
293
+ }).strict();
294
+ var outputSchema = PlaylistItemSchema;
295
+ var definition = defineTool({
296
+ name: "addVideoToPlaylist",
297
+ title: "Add Video To Playlist",
298
+ description: "Add a video to a playlist owned by the authenticated user. Resolve the playlist id via listPlaylists. Returns the new playlistItem id (distinct from the video id \u2014 use it with removeVideoFromPlaylist).",
299
+ inputSchema,
300
+ outputSchema,
301
+ annotations: {
302
+ readOnlyHint: false,
303
+ destructiveHint: false,
304
+ idempotentHint: false,
305
+ openWorldHint: true
306
+ },
307
+ connection: "youtube",
308
+ run: async (input, ctx) => {
309
+ const url = new URL(`https://www.googleapis.com/youtube/v3/playlistItems`);
310
+ url.searchParams.set("part", input.part);
311
+ const res = await ctx.fetch(url.toString(), {
312
+ method: "POST",
313
+ headers: { "Content-Type": "application/json" },
314
+ body: JSON.stringify({ snippet: input.snippet })
315
+ });
316
+ await throwForYouTube(res, "addVideoToPlaylist");
317
+ return res.json();
318
+ }
319
+ });
320
+ var addVideoToPlaylist_default = definition;
321
+ await handleIfScriptMain(import.meta, definition, { connectionResolvers });
322
+
323
+ // scripts/createPlaylist.ts
324
+ import { defineTool as defineTool2, handleIfScriptMain as handleIfScriptMain2 } from "@zapier/connectors-sdk";
325
+ import { z as z3 } from "zod";
326
+ var inputSchema2 = z3.object({
327
+ snippet: z3.object({
328
+ title: z3.string().describe("Playlist title (required)."),
329
+ description: z3.string().describe("Playlist description.").optional(),
330
+ defaultLanguage: z3.string().describe(
331
+ "BCP-47 language code of the title/description text, e.g. en."
332
+ ).optional()
333
+ }).strict(),
334
+ status: z3.object({
335
+ privacyStatus: z3.enum(["public", "unlisted", "private"]).describe("Playlist visibility. Defaults to private if omitted.").optional()
336
+ }).strict().optional(),
337
+ part: z3.string().describe("Resource parts being written. Leave as the default.").default("snippet,status")
338
+ }).strict();
339
+ var outputSchema2 = PlaylistSchema;
340
+ var definition2 = defineTool2({
341
+ name: "createPlaylist",
342
+ title: "Create Playlist",
343
+ description: "Create a new playlist on the authenticated user's channel. Returns the new playlist id for addVideoToPlaylist.",
344
+ inputSchema: inputSchema2,
345
+ outputSchema: outputSchema2,
346
+ annotations: {
347
+ readOnlyHint: false,
348
+ destructiveHint: false,
349
+ idempotentHint: false,
350
+ openWorldHint: true
351
+ },
352
+ connection: "youtube",
353
+ run: async (input, ctx) => {
354
+ const url = new URL(`https://www.googleapis.com/youtube/v3/playlists`);
355
+ if (input.part !== void 0) {
356
+ url.searchParams.set("part", String(input.part));
357
+ }
358
+ const body = {};
359
+ if (input.snippet !== void 0) body["snippet"] = input.snippet;
360
+ if (input.status !== void 0) body["status"] = input.status;
361
+ const res = await ctx.fetch(url.toString(), {
362
+ method: "POST",
363
+ headers: { "Content-Type": "application/json" },
364
+ body: JSON.stringify(body)
365
+ });
366
+ await throwForYouTube(res, "createPlaylist");
367
+ return res.json();
368
+ }
369
+ });
370
+ var createPlaylist_default = definition2;
371
+ await handleIfScriptMain2(import.meta, definition2, { connectionResolvers });
372
+
373
+ // scripts/deletePlaylist.ts
374
+ import { defineTool as defineTool3, handleIfScriptMain as handleIfScriptMain3 } from "@zapier/connectors-sdk";
375
+ import { z as z4 } from "zod";
376
+ var inputSchema3 = z4.object({
377
+ id: z4.string().describe("The id of the playlist to delete (from listPlaylists).")
378
+ }).strict();
379
+ var outputSchema3 = SuccessResultSchema;
380
+ var definition3 = defineTool3({
381
+ name: "deletePlaylist",
382
+ title: "Delete Playlist",
383
+ description: "Permanently delete a playlist owned by the authenticated user. Irreversible.",
384
+ inputSchema: inputSchema3,
385
+ outputSchema: outputSchema3,
386
+ annotations: {
387
+ readOnlyHint: false,
388
+ destructiveHint: true,
389
+ idempotentHint: true,
390
+ openWorldHint: true
391
+ },
392
+ connection: "youtube",
393
+ run: async (input, ctx) => {
394
+ const url = new URL(`https://www.googleapis.com/youtube/v3/playlists`);
395
+ if (input.id !== void 0) {
396
+ url.searchParams.set("id", String(input.id));
397
+ }
398
+ const res = await ctx.fetch(url.toString(), {
399
+ method: "DELETE"
400
+ });
401
+ await throwForYouTube(res, "deletePlaylist");
402
+ return { success: true };
403
+ }
404
+ });
405
+ var deletePlaylist_default = definition3;
406
+ await handleIfScriptMain3(import.meta, definition3, { connectionResolvers });
407
+
408
+ // scripts/deleteVideo.ts
409
+ import { defineTool as defineTool4, handleIfScriptMain as handleIfScriptMain4 } from "@zapier/connectors-sdk";
410
+ import { z as z5 } from "zod";
411
+ var inputSchema4 = z5.object({ id: z5.string().describe("The id of the video to delete.") }).strict();
412
+ var outputSchema4 = SuccessResultSchema;
413
+ var definition4 = defineTool4({
414
+ name: "deleteVideo",
415
+ title: "Delete Video",
416
+ description: "Permanently delete a video from the authenticated user's channel. Irreversible. The caller must own the video.",
417
+ inputSchema: inputSchema4,
418
+ outputSchema: outputSchema4,
419
+ annotations: {
420
+ readOnlyHint: false,
421
+ destructiveHint: true,
422
+ idempotentHint: true,
423
+ openWorldHint: true
424
+ },
425
+ connection: "youtube",
426
+ run: async (input, ctx) => {
427
+ const url = new URL(`https://www.googleapis.com/youtube/v3/videos`);
428
+ if (input.id !== void 0) {
429
+ url.searchParams.set("id", String(input.id));
430
+ }
431
+ const res = await ctx.fetch(url.toString(), {
432
+ method: "DELETE"
433
+ });
434
+ await throwForYouTube(res, "deleteVideo");
435
+ return { success: true };
436
+ }
437
+ });
438
+ var deleteVideo_default = definition4;
439
+ await handleIfScriptMain4(import.meta, definition4, { connectionResolvers });
440
+
441
+ // scripts/downloadCaption.ts
442
+ import { defineTool as defineTool5, handleIfScriptMain as handleIfScriptMain5 } from "@zapier/connectors-sdk";
443
+ import { z as z6 } from "zod";
444
+ var inputSchema5 = z6.object({
445
+ id: z6.string().describe("The caption track id to download (from listCaptions)."),
446
+ tfmt: z6.enum(["srt", "vtt", "sbv", "scc", "ttml"]).describe("Output caption format. Defaults to srt.").default("srt"),
447
+ tlang: z6.string().describe(
448
+ "Optional BCP-47 language code (e.g. es) to request a machine translation of the track."
449
+ ).optional()
450
+ }).strict();
451
+ var outputSchema5 = z6.object({
452
+ caption_text: z6.string().describe("The caption track text in the requested format."),
453
+ format: z6.string().describe("The format the text was returned in.")
454
+ });
455
+ var definition5 = defineTool5({
456
+ name: "downloadCaption",
457
+ title: "Download Caption",
458
+ description: "Download a caption track's text in a chosen format (srt, vtt, sbv, scc, or ttml). Resolve the track id via listCaptions. Requires permission to edit the video (the owner or an editor) and the youtube.force-ssl scope.",
459
+ inputSchema: inputSchema5,
460
+ outputSchema: outputSchema5,
461
+ annotations: {
462
+ readOnlyHint: true,
463
+ destructiveHint: false,
464
+ idempotentHint: true,
465
+ openWorldHint: true
466
+ },
467
+ connection: "youtube",
468
+ run: async (input, ctx) => {
469
+ const url = new URL(
470
+ `https://www.googleapis.com/youtube/v3/captions/${encodeURIComponent(input.id)}`
471
+ );
472
+ url.searchParams.set("tfmt", input.tfmt);
473
+ if (input.tlang !== void 0) url.searchParams.set("tlang", input.tlang);
474
+ const res = await ctx.fetch(url.toString(), { method: "GET" });
475
+ await throwForYouTube(res, "downloadCaption");
476
+ const caption_text = await res.text();
477
+ return { caption_text, format: input.tfmt };
478
+ }
479
+ });
480
+ var downloadCaption_default = definition5;
481
+ await handleIfScriptMain5(import.meta, definition5, { connectionResolvers });
482
+
483
+ // scripts/getChannel.ts
484
+ import { defineTool as defineTool6, handleIfScriptMain as handleIfScriptMain6 } from "@zapier/connectors-sdk";
485
+ import { z as z7 } from "zod";
486
+ var inputSchema6 = z7.object({
487
+ part: z7.string().describe("Resource parts to return. Leave as the default.").default("snippet,contentDetails,statistics,brandingSettings"),
488
+ mine: z7.boolean().describe(
489
+ "Return the authenticated user's own channel(s). Use this to discover the caller's channel id and uploads playlist."
490
+ ).optional(),
491
+ id: z7.string().describe("Look up channel(s) by id (UC..., comma-separated, max 50).").optional(),
492
+ forHandle: z7.string().describe(
493
+ "Look up a channel by its @handle, e.g. @MrBeast (with or without the leading @). Mutually exclusive with mine and id."
494
+ ).optional()
495
+ }).strict().refine(
496
+ (v) => [v.mine, v.id, v.forHandle].filter((x) => x !== void 0).length <= 1,
497
+ {
498
+ message: "Provide only one of mine, id, or forHandle (they are mutually exclusive)."
499
+ }
500
+ );
501
+ var outputSchema6 = z7.object({
502
+ items: z7.array(ChannelSchema).describe("The requested channels.")
503
+ });
504
+ var definition6 = defineTool6({
505
+ name: "getChannel",
506
+ title: "Get Channel",
507
+ description: "Get a channel's profile, statistics, and uploads-playlist id. Pass mine=true for the authenticated user's channel, or a channel id / handle to look up another. The resolver for channelId and for a channel's uploads playlist.",
508
+ inputSchema: inputSchema6,
509
+ outputSchema: outputSchema6,
510
+ annotations: {
511
+ readOnlyHint: true,
512
+ destructiveHint: false,
513
+ idempotentHint: true,
514
+ openWorldHint: true
515
+ },
516
+ connection: "youtube",
517
+ run: async (input, ctx) => {
518
+ const url = new URL(`https://www.googleapis.com/youtube/v3/channels`);
519
+ if (input.part !== void 0) {
520
+ url.searchParams.set("part", String(input.part));
521
+ }
522
+ if (input.mine !== void 0) {
523
+ url.searchParams.set("mine", String(input.mine));
524
+ }
525
+ if (input.id !== void 0) {
526
+ url.searchParams.set("id", String(input.id));
527
+ }
528
+ if (input.forHandle !== void 0) {
529
+ url.searchParams.set("forHandle", String(input.forHandle));
530
+ }
531
+ const res = await ctx.fetch(url.toString(), {
532
+ method: "GET"
533
+ });
534
+ await throwForYouTube(res, "getChannel");
535
+ const payload = await res.json();
536
+ return { items: payload.items ?? [] };
537
+ }
538
+ });
539
+ var getChannel_default = definition6;
540
+ await handleIfScriptMain6(import.meta, definition6, { connectionResolvers });
541
+
542
+ // scripts/getVideo.ts
543
+ import { defineTool as defineTool7, handleIfScriptMain as handleIfScriptMain7 } from "@zapier/connectors-sdk";
544
+ import { z as z8 } from "zod";
545
+ var inputSchema7 = z8.object({
546
+ part: z8.string().describe("Resource parts to return. Leave as the default.").default("snippet,contentDetails,statistics,status"),
547
+ id: z8.string().describe(
548
+ "One video id or a comma-separated list (max 50), e.g. dQw4w9WgXcQ. The 11-char id from a watch URL or searchVideos."
549
+ ),
550
+ maxResults: z8.number().int().gte(1).lte(50).describe(
551
+ "Max results per page when listing many ids. Defaults to 10 when omitted; pass a value when you need a specific number of results."
552
+ ).optional()
553
+ }).strict();
554
+ var outputSchema7 = z8.object({
555
+ items: z8.array(VideoSchema).describe("The requested videos."),
556
+ next_page_token: NextPageToken
557
+ });
558
+ var definition7 = defineTool7({
559
+ name: "getVideo",
560
+ title: "Get Video",
561
+ description: "Get full details of one or more videos by id \u2014 snippet (title, description, tags, category), statistics (view/like/comment counts), contentDetails (ISO-8601 duration), and status (privacy, upload state). Counts come back as strings; like/comment counts are absent when the owner hides them. Resolve ids via searchVideos or a watch URL.",
562
+ inputSchema: inputSchema7,
563
+ outputSchema: outputSchema7,
564
+ annotations: {
565
+ readOnlyHint: true,
566
+ destructiveHint: false,
567
+ idempotentHint: true,
568
+ openWorldHint: true
569
+ },
570
+ connection: "youtube",
571
+ run: async (input, ctx) => {
572
+ const url = new URL(`https://www.googleapis.com/youtube/v3/videos`);
573
+ url.searchParams.set("part", input.part);
574
+ url.searchParams.set("id", input.id);
575
+ url.searchParams.set("maxResults", String(input.maxResults ?? 10));
576
+ const res = await ctx.fetch(url.toString(), { method: "GET" });
577
+ await throwForYouTube(res, "getVideo");
578
+ const payload = await res.json();
579
+ return {
580
+ items: payload.items ?? [],
581
+ next_page_token: payload.nextPageToken
582
+ };
583
+ }
584
+ });
585
+ var getVideo_default = definition7;
586
+ await handleIfScriptMain7(import.meta, definition7, { connectionResolvers });
587
+
588
+ // scripts/listCaptions.ts
589
+ import { defineTool as defineTool8, handleIfScriptMain as handleIfScriptMain8 } from "@zapier/connectors-sdk";
590
+ import { z as z9 } from "zod";
591
+ var inputSchema8 = z9.object({
592
+ part: z9.string().describe("Resource parts to return. Leave as the default.").default("snippet"),
593
+ videoId: z9.string().describe("The video id whose caption tracks to list.")
594
+ }).strict();
595
+ var outputSchema8 = z9.object({
596
+ items: z9.array(CaptionSchema).describe("The caption tracks for the video.")
597
+ });
598
+ var definition8 = defineTool8({
599
+ name: "listCaptions",
600
+ title: "List Captions",
601
+ description: "List the caption tracks available for a video (id, language, name, type, status). Use the track id with downloadCaption to fetch the text. Requires the youtube.force-ssl scope.",
602
+ inputSchema: inputSchema8,
603
+ outputSchema: outputSchema8,
604
+ annotations: {
605
+ readOnlyHint: true,
606
+ destructiveHint: false,
607
+ idempotentHint: true,
608
+ openWorldHint: true
609
+ },
610
+ connection: "youtube",
611
+ run: async (input, ctx) => {
612
+ const url = new URL(`https://www.googleapis.com/youtube/v3/captions`);
613
+ if (input.part !== void 0) {
614
+ url.searchParams.set("part", String(input.part));
615
+ }
616
+ if (input.videoId !== void 0) {
617
+ url.searchParams.set("videoId", String(input.videoId));
618
+ }
619
+ const res = await ctx.fetch(url.toString(), {
620
+ method: "GET"
621
+ });
622
+ await throwForYouTube(res, "listCaptions");
623
+ const payload = await res.json();
624
+ return { items: payload.items ?? [] };
625
+ }
626
+ });
627
+ var listCaptions_default = definition8;
628
+ await handleIfScriptMain8(import.meta, definition8, { connectionResolvers });
629
+
630
+ // scripts/listComments.ts
631
+ import { defineTool as defineTool9, handleIfScriptMain as handleIfScriptMain9 } from "@zapier/connectors-sdk";
632
+ import { z as z10 } from "zod";
633
+ var inputSchema9 = z10.object({
634
+ part: z10.string().describe("Resource parts to return. Leave as the default.").default("snippet,replies"),
635
+ videoId: z10.string().describe("The video id whose comment threads to list."),
636
+ order: z10.enum(["time", "relevance"]).describe("time = newest first; relevance = YouTube's relevance ranking.").default("time"),
637
+ searchTerms: z10.string().describe("Only return comment threads matching this text.").optional(),
638
+ maxResults: z10.number().int().gte(1).lte(100).describe(
639
+ "Max threads per page (1-100). Defaults to 20 when omitted; pass a value when you need a specific number of results."
640
+ ).optional(),
641
+ pageToken: z10.string().describe(
642
+ "Page cursor from a previous response's next_page_token. Omit for the first page."
643
+ ).optional()
644
+ }).strict();
645
+ var outputSchema9 = z10.object({
646
+ items: z10.array(CommentThreadSchema).describe("The comment threads."),
647
+ next_page_token: NextPageToken
648
+ });
649
+ var definition9 = defineTool9({
650
+ name: "listComments",
651
+ title: "List Comments",
652
+ description: "List top-level comment threads on a video (each with its first replies). Use to read what viewers commented. Resolve videoId via searchVideos/getVideo.",
653
+ inputSchema: inputSchema9,
654
+ outputSchema: outputSchema9,
655
+ annotations: {
656
+ readOnlyHint: true,
657
+ destructiveHint: false,
658
+ idempotentHint: true,
659
+ openWorldHint: true
660
+ },
661
+ connection: "youtube",
662
+ run: async (input, ctx) => {
663
+ const url = new URL(`https://www.googleapis.com/youtube/v3/commentThreads`);
664
+ if (input.part !== void 0) {
665
+ url.searchParams.set("part", String(input.part));
666
+ }
667
+ if (input.videoId !== void 0) {
668
+ url.searchParams.set("videoId", String(input.videoId));
669
+ }
670
+ if (input.order !== void 0) {
671
+ url.searchParams.set("order", String(input.order));
672
+ }
673
+ if (input.searchTerms !== void 0) {
674
+ url.searchParams.set("searchTerms", String(input.searchTerms));
675
+ }
676
+ url.searchParams.set("maxResults", String(input.maxResults ?? 20));
677
+ if (input.pageToken !== void 0) {
678
+ url.searchParams.set("pageToken", String(input.pageToken));
679
+ }
680
+ const res = await ctx.fetch(url.toString(), {
681
+ method: "GET"
682
+ });
683
+ await throwForYouTube(res, "listComments");
684
+ const payload = await res.json();
685
+ return {
686
+ items: payload.items ?? [],
687
+ next_page_token: payload.nextPageToken
688
+ };
689
+ }
690
+ });
691
+ var listComments_default = definition9;
692
+ await handleIfScriptMain9(import.meta, definition9, { connectionResolvers });
693
+
694
+ // scripts/listPlaylistItems.ts
695
+ import { defineTool as defineTool10, handleIfScriptMain as handleIfScriptMain10 } from "@zapier/connectors-sdk";
696
+ import { z as z11 } from "zod";
697
+ var inputSchema10 = z11.object({
698
+ part: z11.string().describe("Resource parts to return. Leave as the default.").default("snippet,contentDetails,status"),
699
+ playlistId: z11.string().describe(
700
+ "The playlist id whose items to list (from listPlaylists). For a channel's uploads, use the uploads playlist id from getChannel."
701
+ ),
702
+ maxResults: z11.number().int().gte(1).lte(50).describe(
703
+ "Max items per page (1-50). Defaults to 20 when omitted; pass a value when you need a specific number of results."
704
+ ).optional(),
705
+ pageToken: z11.string().describe(
706
+ "Page cursor from a previous response's next_page_token. Omit for the first page."
707
+ ).optional()
708
+ }).strict();
709
+ var outputSchema10 = z11.object({
710
+ items: z11.array(PlaylistItemSchema).describe("The videos in the playlist, in order."),
711
+ next_page_token: NextPageToken
712
+ });
713
+ var definition10 = defineTool10({
714
+ name: "listPlaylistItems",
715
+ title: "List Playlist Items",
716
+ description: "List the videos in a playlist, in playlist order. Each item carries its own playlistItem id (needed by removeVideoFromPlaylist) plus the video id and snippet.",
717
+ inputSchema: inputSchema10,
718
+ outputSchema: outputSchema10,
719
+ annotations: {
720
+ readOnlyHint: true,
721
+ destructiveHint: false,
722
+ idempotentHint: true,
723
+ openWorldHint: true
724
+ },
725
+ connection: "youtube",
726
+ run: async (input, ctx) => {
727
+ const url = new URL(`https://www.googleapis.com/youtube/v3/playlistItems`);
728
+ if (input.part !== void 0) {
729
+ url.searchParams.set("part", String(input.part));
730
+ }
731
+ if (input.playlistId !== void 0) {
732
+ url.searchParams.set("playlistId", String(input.playlistId));
733
+ }
734
+ url.searchParams.set("maxResults", String(input.maxResults ?? 20));
735
+ if (input.pageToken !== void 0) {
736
+ url.searchParams.set("pageToken", String(input.pageToken));
737
+ }
738
+ const res = await ctx.fetch(url.toString(), {
739
+ method: "GET"
740
+ });
741
+ await throwForYouTube(res, "listPlaylistItems");
742
+ const payload = await res.json();
743
+ return {
744
+ items: payload.items ?? [],
745
+ next_page_token: payload.nextPageToken
746
+ };
747
+ }
748
+ });
749
+ var listPlaylistItems_default = definition10;
750
+ await handleIfScriptMain10(import.meta, definition10, { connectionResolvers });
751
+
752
+ // scripts/listPlaylists.ts
753
+ import { defineTool as defineTool11, handleIfScriptMain as handleIfScriptMain11 } from "@zapier/connectors-sdk";
754
+ import { z as z12 } from "zod";
755
+ var inputSchema11 = z12.object({
756
+ part: z12.string().describe("Resource parts to return. Leave as the default.").default("snippet,contentDetails,status"),
757
+ mine: z12.boolean().describe(
758
+ "List the authenticated user's own playlists. The default when no channelId or id is given."
759
+ ).optional(),
760
+ channelId: z12.string().describe(
761
+ "List playlists owned by this channel id (UC...). Mutually exclusive with mine and id."
762
+ ).optional(),
763
+ id: z12.string().describe(
764
+ "Fetch specific playlists by id (comma-separated, max 50). Mutually exclusive with mine and channelId."
765
+ ).optional(),
766
+ maxResults: z12.number().int().gte(1).lte(50).describe(
767
+ "Max playlists per page (1-50). Defaults to 20 when omitted; pass a value when you need a specific number of results."
768
+ ).optional(),
769
+ pageToken: z12.string().describe(
770
+ "Page cursor from a previous response's next_page_token. Omit for the first page."
771
+ ).optional()
772
+ }).strict();
773
+ var outputSchema11 = z12.object({
774
+ items: z12.array(PlaylistSchema).describe("The playlists."),
775
+ next_page_token: NextPageToken
776
+ });
777
+ var definition11 = defineTool11({
778
+ name: "listPlaylists",
779
+ title: "List Playlists",
780
+ description: "List playlists owned by the authenticated user (default) or by a channel, or fetch specific playlists by id. The resolver for any playlistId input.",
781
+ inputSchema: inputSchema11,
782
+ outputSchema: outputSchema11,
783
+ annotations: {
784
+ readOnlyHint: true,
785
+ destructiveHint: false,
786
+ idempotentHint: true,
787
+ openWorldHint: true
788
+ },
789
+ connection: "youtube",
790
+ run: async (input, ctx) => {
791
+ const url = new URL(`https://www.googleapis.com/youtube/v3/playlists`);
792
+ if (input.part !== void 0) {
793
+ url.searchParams.set("part", String(input.part));
794
+ }
795
+ if (input.mine !== void 0) {
796
+ url.searchParams.set("mine", String(input.mine));
797
+ }
798
+ if (input.channelId !== void 0) {
799
+ url.searchParams.set("channelId", String(input.channelId));
800
+ }
801
+ if (input.id !== void 0) {
802
+ url.searchParams.set("id", String(input.id));
803
+ }
804
+ url.searchParams.set("maxResults", String(input.maxResults ?? 20));
805
+ if (input.pageToken !== void 0) {
806
+ url.searchParams.set("pageToken", String(input.pageToken));
807
+ }
808
+ const res = await ctx.fetch(url.toString(), {
809
+ method: "GET"
810
+ });
811
+ await throwForYouTube(res, "listPlaylists");
812
+ const payload = await res.json();
813
+ return {
814
+ items: payload.items ?? [],
815
+ next_page_token: payload.nextPageToken
816
+ };
817
+ }
818
+ });
819
+ var listPlaylists_default = definition11;
820
+ await handleIfScriptMain11(import.meta, definition11, { connectionResolvers });
821
+
822
+ // scripts/listSubscriptions.ts
823
+ import { defineTool as defineTool12, handleIfScriptMain as handleIfScriptMain12 } from "@zapier/connectors-sdk";
824
+ import { z as z13 } from "zod";
825
+ var inputSchema12 = z13.object({
826
+ part: z13.string().describe("Resource parts to return. Leave as the default.").default("snippet,contentDetails"),
827
+ mine: z13.boolean().describe("List the authenticated user's subscriptions. The default.").default(true),
828
+ forChannelId: z13.string().describe(
829
+ "Restrict to a subscription to this specific channel id \u2014 returns one item if subscribed, none otherwise. Use to check subscription state."
830
+ ).optional(),
831
+ order: z13.enum(["alphabetical", "relevance", "unread"]).describe("Sort order.").default("relevance"),
832
+ maxResults: z13.number().int().gte(1).lte(50).describe(
833
+ "Max subscriptions per page (1-50). Defaults to 20 when omitted; pass a value when you need a specific number of results."
834
+ ).optional(),
835
+ pageToken: z13.string().describe(
836
+ "Page cursor from a previous response's next_page_token. Omit for the first page."
837
+ ).optional()
838
+ }).strict();
839
+ var outputSchema12 = z13.object({
840
+ items: z13.array(SubscriptionSchema).describe("The subscriptions."),
841
+ next_page_token: NextPageToken
842
+ });
843
+ var definition12 = defineTool12({
844
+ name: "listSubscriptions",
845
+ title: "List Subscriptions",
846
+ description: "List the channels the authenticated user is subscribed to (default), or check whether the user subscribes to a specific channel via forChannelId.",
847
+ inputSchema: inputSchema12,
848
+ outputSchema: outputSchema12,
849
+ annotations: {
850
+ readOnlyHint: true,
851
+ destructiveHint: false,
852
+ idempotentHint: true,
853
+ openWorldHint: true
854
+ },
855
+ connection: "youtube",
856
+ run: async (input, ctx) => {
857
+ const url = new URL(`https://www.googleapis.com/youtube/v3/subscriptions`);
858
+ if (input.part !== void 0) {
859
+ url.searchParams.set("part", String(input.part));
860
+ }
861
+ if (input.mine !== void 0) {
862
+ url.searchParams.set("mine", String(input.mine));
863
+ }
864
+ if (input.forChannelId !== void 0) {
865
+ url.searchParams.set("forChannelId", String(input.forChannelId));
866
+ }
867
+ if (input.order !== void 0) {
868
+ url.searchParams.set("order", String(input.order));
869
+ }
870
+ url.searchParams.set("maxResults", String(input.maxResults ?? 20));
871
+ if (input.pageToken !== void 0) {
872
+ url.searchParams.set("pageToken", String(input.pageToken));
873
+ }
874
+ const res = await ctx.fetch(url.toString(), {
875
+ method: "GET"
876
+ });
877
+ await throwForYouTube(res, "listSubscriptions");
878
+ const payload = await res.json();
879
+ return {
880
+ items: payload.items ?? [],
881
+ next_page_token: payload.nextPageToken
882
+ };
883
+ }
884
+ });
885
+ var listSubscriptions_default = definition12;
886
+ await handleIfScriptMain12(import.meta, definition12, { connectionResolvers });
887
+
888
+ // scripts/listVideoCategories.ts
889
+ import { defineTool as defineTool13, handleIfScriptMain as handleIfScriptMain13 } from "@zapier/connectors-sdk";
890
+ import { z as z14 } from "zod";
891
+ var inputSchema13 = z14.object({
892
+ part: z14.string().describe("Resource parts to return. Leave as the default.").default("snippet"),
893
+ regionCode: z14.string().describe(
894
+ "ISO 3166-1 alpha-2 country code whose category set to return (e.g. US, GB). Categories vary by region."
895
+ ).default("US")
896
+ }).strict();
897
+ var outputSchema13 = z14.object({
898
+ items: z14.array(VideoCategorySchema).describe("The categories for the region.")
899
+ });
900
+ var definition13 = defineTool13({
901
+ name: "listVideoCategories",
902
+ title: "List Video Categories",
903
+ description: "List the assignable video categories for a region (the id/title pairs that categoryId accepts on a video). Resolver for the category an upload or update should use.",
904
+ inputSchema: inputSchema13,
905
+ outputSchema: outputSchema13,
906
+ annotations: {
907
+ readOnlyHint: true,
908
+ destructiveHint: false,
909
+ idempotentHint: true,
910
+ openWorldHint: true
911
+ },
912
+ connection: "youtube",
913
+ run: async (input, ctx) => {
914
+ const url = new URL(
915
+ `https://www.googleapis.com/youtube/v3/videoCategories`
916
+ );
917
+ if (input.part !== void 0) {
918
+ url.searchParams.set("part", String(input.part));
919
+ }
920
+ if (input.regionCode !== void 0) {
921
+ url.searchParams.set("regionCode", String(input.regionCode));
922
+ }
923
+ const res = await ctx.fetch(url.toString(), {
924
+ method: "GET"
925
+ });
926
+ await throwForYouTube(res, "listVideoCategories");
927
+ const payload = await res.json();
928
+ return { items: payload.items ?? [] };
929
+ }
930
+ });
931
+ var listVideoCategories_default = definition13;
932
+ await handleIfScriptMain13(import.meta, definition13, { connectionResolvers });
933
+
934
+ // scripts/postComment.ts
935
+ import { defineTool as defineTool14, handleIfScriptMain as handleIfScriptMain14 } from "@zapier/connectors-sdk";
936
+ import { z as z15 } from "zod";
937
+ var inputSchema14 = z15.object({
938
+ snippet: z15.object({
939
+ videoId: z15.string().describe("The video to comment on."),
940
+ topLevelComment: z15.object({
941
+ snippet: z15.object({
942
+ textOriginal: z15.string().describe("The comment text to post.")
943
+ }).strict()
944
+ }).strict()
945
+ }).strict(),
946
+ part: z15.string().describe("Resource parts being written. Leave as the default.").default("snippet")
947
+ }).strict();
948
+ var outputSchema14 = CommentThreadSchema;
949
+ var definition14 = defineTool14({
950
+ name: "postComment",
951
+ title: "Post Comment",
952
+ description: "Post a new top-level comment on a video. For a reply to an existing comment, use replyToComment instead. Requires the youtube.force-ssl scope.",
953
+ inputSchema: inputSchema14,
954
+ outputSchema: outputSchema14,
955
+ annotations: {
956
+ readOnlyHint: false,
957
+ destructiveHint: false,
958
+ idempotentHint: false,
959
+ openWorldHint: true
960
+ },
961
+ connection: "youtube",
962
+ run: async (input, ctx) => {
963
+ const url = new URL(`https://www.googleapis.com/youtube/v3/commentThreads`);
964
+ if (input.part !== void 0) {
965
+ url.searchParams.set("part", String(input.part));
966
+ }
967
+ const body = {};
968
+ if (input.snippet !== void 0) body["snippet"] = input.snippet;
969
+ const res = await ctx.fetch(url.toString(), {
970
+ method: "POST",
971
+ headers: { "Content-Type": "application/json" },
972
+ body: JSON.stringify(body)
973
+ });
974
+ await throwForYouTube(res, "postComment");
975
+ return res.json();
976
+ }
977
+ });
978
+ var postComment_default = definition14;
979
+ await handleIfScriptMain14(import.meta, definition14, { connectionResolvers });
980
+
981
+ // scripts/rateVideo.ts
982
+ import { defineTool as defineTool15, handleIfScriptMain as handleIfScriptMain15 } from "@zapier/connectors-sdk";
983
+ import { z as z16 } from "zod";
984
+ var inputSchema15 = z16.object({
985
+ id: z16.string().describe("The id of the video to rate."),
986
+ rating: z16.enum(["like", "dislike", "none"]).describe(
987
+ "like or dislike to set the rating; none to remove an existing rating."
988
+ )
989
+ }).strict();
990
+ var outputSchema15 = SuccessResultSchema;
991
+ var definition15 = defineTool15({
992
+ name: "rateVideo",
993
+ title: "Rate Video",
994
+ description: "Like, dislike, or clear the authenticated user's rating on a video (the thumbs up/down action). Use rating=none to remove an existing rating. The API returns no body; the connector synthesizes a success flag.",
995
+ inputSchema: inputSchema15,
996
+ outputSchema: outputSchema15,
997
+ annotations: {
998
+ readOnlyHint: false,
999
+ destructiveHint: false,
1000
+ // Setting the same rating twice leaves the same state.
1001
+ idempotentHint: true,
1002
+ openWorldHint: true
1003
+ },
1004
+ connection: "youtube",
1005
+ run: async (input, ctx) => {
1006
+ const url = new URL(`https://www.googleapis.com/youtube/v3/videos/rate`);
1007
+ url.searchParams.set("id", input.id);
1008
+ url.searchParams.set("rating", input.rating);
1009
+ const res = await ctx.fetch(url.toString(), { method: "POST" });
1010
+ await throwForYouTube(res, "rateVideo");
1011
+ return { success: true };
1012
+ }
1013
+ });
1014
+ var rateVideo_default = definition15;
1015
+ await handleIfScriptMain15(import.meta, definition15, { connectionResolvers });
1016
+
1017
+ // scripts/removeVideoFromPlaylist.ts
1018
+ import { defineTool as defineTool16, handleIfScriptMain as handleIfScriptMain16 } from "@zapier/connectors-sdk";
1019
+ import { z as z17 } from "zod";
1020
+ var inputSchema16 = z17.object({
1021
+ id: z17.string().describe(
1022
+ "The playlistItem id to remove (the item's own id from listPlaylistItems, not the video id)."
1023
+ )
1024
+ }).strict();
1025
+ var outputSchema16 = SuccessResultSchema;
1026
+ var definition16 = defineTool16({
1027
+ name: "removeVideoFromPlaylist",
1028
+ title: "Remove Video From Playlist",
1029
+ description: "Remove an item from a playlist. The id is the playlistItem id (NOT the video id) \u2014 get it from listPlaylistItems.",
1030
+ inputSchema: inputSchema16,
1031
+ outputSchema: outputSchema16,
1032
+ annotations: {
1033
+ readOnlyHint: false,
1034
+ // Reversible — the video can be re-added with addVideoToPlaylist.
1035
+ destructiveHint: false,
1036
+ idempotentHint: true,
1037
+ openWorldHint: true
1038
+ },
1039
+ connection: "youtube",
1040
+ run: async (input, ctx) => {
1041
+ const url = new URL(`https://www.googleapis.com/youtube/v3/playlistItems`);
1042
+ if (input.id !== void 0) {
1043
+ url.searchParams.set("id", String(input.id));
1044
+ }
1045
+ const res = await ctx.fetch(url.toString(), {
1046
+ method: "DELETE"
1047
+ });
1048
+ await throwForYouTube(res, "removeVideoFromPlaylist");
1049
+ return { success: true };
1050
+ }
1051
+ });
1052
+ var removeVideoFromPlaylist_default = definition16;
1053
+ await handleIfScriptMain16(import.meta, definition16, { connectionResolvers });
1054
+
1055
+ // scripts/replyToComment.ts
1056
+ import {
1057
+ ConnectorHttpError as ConnectorHttpError2,
1058
+ defineTool as defineTool17,
1059
+ handleIfScriptMain as handleIfScriptMain17
1060
+ } from "@zapier/connectors-sdk";
1061
+ import { z as z18 } from "zod";
1062
+ var inputSchema17 = z18.object({
1063
+ snippet: z18.object({
1064
+ parentId: z18.string().describe(
1065
+ "The TOP-LEVEL comment thread id to reply to (from listComments) \u2014 not a reply id. Replies are single-level: you cannot reply to a reply."
1066
+ ),
1067
+ textOriginal: z18.string().describe("The reply text to post.")
1068
+ }).strict(),
1069
+ part: z18.string().describe("Resource parts being written. Leave as the default.").default("snippet")
1070
+ }).strict();
1071
+ var outputSchema17 = CommentSchema;
1072
+ var definition17 = defineTool17({
1073
+ name: "replyToComment",
1074
+ title: "Reply To Comment",
1075
+ description: "Reply to an existing top-level comment thread. The parentId must be a top-level comment thread id from listComments \u2014 replies are single-level, so you cannot reply to a reply (YouTube rejects it with operationNotSupported). Requires the youtube.force-ssl scope.",
1076
+ inputSchema: inputSchema17,
1077
+ outputSchema: outputSchema17,
1078
+ annotations: {
1079
+ readOnlyHint: false,
1080
+ destructiveHint: false,
1081
+ idempotentHint: false,
1082
+ openWorldHint: true
1083
+ },
1084
+ connection: "youtube",
1085
+ run: async (input, ctx) => {
1086
+ const url = new URL(`https://www.googleapis.com/youtube/v3/comments`);
1087
+ if (input.part !== void 0) {
1088
+ url.searchParams.set("part", String(input.part));
1089
+ }
1090
+ const body = {};
1091
+ if (input.snippet !== void 0) body["snippet"] = input.snippet;
1092
+ const res = await ctx.fetch(url.toString(), {
1093
+ method: "POST",
1094
+ headers: { "Content-Type": "application/json" },
1095
+ body: JSON.stringify(body)
1096
+ });
1097
+ if (res.ok) return res.json();
1098
+ if (res.status === 400) {
1099
+ const errBody = await res.json().catch(() => null);
1100
+ if (hasYouTubeReason(errBody, "operationNotSupported")) {
1101
+ throw ConnectorHttpError2.fromResponseBody(res, errBody, {
1102
+ message: "YouTube replyToComment 400: operationNotSupported \u2014 parentId must be a top-level comment thread id (from listComments), not a reply. YouTube does not support nested replies."
1103
+ });
1104
+ }
1105
+ throw ConnectorHttpError2.fromResponseBody(res, errBody, {
1106
+ message: `YouTube replyToComment 400: ${errBody?.error?.message ?? "bad request"}`
1107
+ });
1108
+ }
1109
+ await throwForYouTube(res, "replyToComment");
1110
+ return res.json();
1111
+ }
1112
+ });
1113
+ var replyToComment_default = definition17;
1114
+ await handleIfScriptMain17(import.meta, definition17, { connectionResolvers });
1115
+
1116
+ // scripts/searchVideos.ts
1117
+ import { defineTool as defineTool18, handleIfScriptMain as handleIfScriptMain18 } from "@zapier/connectors-sdk";
1118
+ import { z as z19 } from "zod";
1119
+ var inputSchema18 = z19.object({
1120
+ part: z19.string().describe("Resource parts to return. Leave as the default.").default("snippet"),
1121
+ type: z19.string().describe(
1122
+ "Resource type to search. Leave as the default to search videos."
1123
+ ).default("video"),
1124
+ q: z19.string().describe(
1125
+ 'Free-text search query. Supports the NOT (-) and OR (|) operators, e.g. "boating|sailing -fishing".'
1126
+ ).optional(),
1127
+ channelId: z19.string().describe(
1128
+ "Restrict results to videos uploaded by this channel id (UC...). Resolve via getChannel."
1129
+ ).optional(),
1130
+ forMine: z19.boolean().describe(
1131
+ "Restrict results to the authenticated user's own videos. Requires type=video. Cannot be combined with channelId."
1132
+ ).optional(),
1133
+ order: z19.enum(["date", "rating", "relevance", "title", "videoCount", "viewCount"]).describe("Sort order for results.").default("relevance"),
1134
+ publishedAfter: z19.string().datetime({ offset: true }).describe(
1135
+ "Only return videos published at or after this RFC3339 datetime, e.g. 2026-01-01T00:00:00Z."
1136
+ ).optional(),
1137
+ publishedBefore: z19.string().datetime({ offset: true }).describe("Only return videos published before this RFC3339 datetime.").optional(),
1138
+ videoDuration: z19.enum(["any", "long", "medium", "short"]).describe(
1139
+ "Filter by length. short = <4 min, medium = 4-20 min, long = >20 min."
1140
+ ).optional(),
1141
+ regionCode: z19.string().describe(
1142
+ "ISO 3166-1 alpha-2 country code (e.g. US, GB) to return results for."
1143
+ ).optional(),
1144
+ relevanceLanguage: z19.string().describe("ISO 639-1 language code (e.g. en, es) to bias results toward.").optional(),
1145
+ maxResults: z19.number().int().gte(1).lte(50).describe(
1146
+ "Max results per page (1-50). Defaults to 10 when omitted; pass a value when you need a specific number of results."
1147
+ ).optional(),
1148
+ pageToken: z19.string().describe(
1149
+ "Page cursor from a previous response's next_page_token. Omit for the first page."
1150
+ ).optional()
1151
+ }).strict();
1152
+ var outputSchema18 = z19.object({
1153
+ items: z19.array(SearchResultSchema).describe("The search hits."),
1154
+ next_page_token: NextPageToken
1155
+ });
1156
+ var definition18 = defineTool18({
1157
+ name: "searchVideos",
1158
+ title: "Search Videos",
1159
+ description: "Search YouTube for videos by keyword, channel, date, or duration. Returns lightweight results (id + snippet); call getVideo for statistics and contentDetails. Metered against a separate Search Queries quota bucket, independent of the main 10,000-unit pool.",
1160
+ inputSchema: inputSchema18,
1161
+ outputSchema: outputSchema18,
1162
+ annotations: {
1163
+ readOnlyHint: true,
1164
+ destructiveHint: false,
1165
+ idempotentHint: true,
1166
+ openWorldHint: true
1167
+ },
1168
+ connection: "youtube",
1169
+ run: async (input, ctx) => {
1170
+ const url = new URL(`https://www.googleapis.com/youtube/v3/search`);
1171
+ if (input.part !== void 0) {
1172
+ url.searchParams.set("part", String(input.part));
1173
+ }
1174
+ if (input.type !== void 0) {
1175
+ url.searchParams.set("type", String(input.type));
1176
+ }
1177
+ if (input.q !== void 0) {
1178
+ url.searchParams.set("q", String(input.q));
1179
+ }
1180
+ if (input.channelId !== void 0) {
1181
+ url.searchParams.set("channelId", String(input.channelId));
1182
+ }
1183
+ if (input.forMine !== void 0) {
1184
+ url.searchParams.set("forMine", String(input.forMine));
1185
+ }
1186
+ if (input.order !== void 0) {
1187
+ url.searchParams.set("order", String(input.order));
1188
+ }
1189
+ if (input.publishedAfter !== void 0) {
1190
+ url.searchParams.set("publishedAfter", String(input.publishedAfter));
1191
+ }
1192
+ if (input.publishedBefore !== void 0) {
1193
+ url.searchParams.set("publishedBefore", String(input.publishedBefore));
1194
+ }
1195
+ if (input.videoDuration !== void 0) {
1196
+ url.searchParams.set("videoDuration", String(input.videoDuration));
1197
+ }
1198
+ if (input.regionCode !== void 0) {
1199
+ url.searchParams.set("regionCode", String(input.regionCode));
1200
+ }
1201
+ if (input.relevanceLanguage !== void 0) {
1202
+ url.searchParams.set(
1203
+ "relevanceLanguage",
1204
+ String(input.relevanceLanguage)
1205
+ );
1206
+ }
1207
+ url.searchParams.set("maxResults", String(input.maxResults ?? 10));
1208
+ if (input.pageToken !== void 0) {
1209
+ url.searchParams.set("pageToken", String(input.pageToken));
1210
+ }
1211
+ const res = await ctx.fetch(url.toString(), {
1212
+ method: "GET"
1213
+ });
1214
+ await throwForYouTube(res, "searchVideos");
1215
+ const payload = await res.json();
1216
+ return {
1217
+ items: payload.items ?? [],
1218
+ next_page_token: payload.nextPageToken
1219
+ };
1220
+ }
1221
+ });
1222
+ var searchVideos_default = definition18;
1223
+ await handleIfScriptMain18(import.meta, definition18, { connectionResolvers });
1224
+
1225
+ // scripts/subscribeToChannel.ts
1226
+ import {
1227
+ ConnectorHttpError as ConnectorHttpError3,
1228
+ defineTool as defineTool19,
1229
+ handleIfScriptMain as handleIfScriptMain19
1230
+ } from "@zapier/connectors-sdk";
1231
+ import { z as z20 } from "zod";
1232
+ var inputSchema19 = z20.object({
1233
+ snippet: z20.object({
1234
+ resourceId: z20.object({
1235
+ kind: z20.string().default("youtube#channel"),
1236
+ channelId: z20.string().describe("The id (UC...) of the channel to subscribe to.")
1237
+ }).strict().describe(
1238
+ "The channel to subscribe to. Set kind to youtube#channel and channelId to the target channel id."
1239
+ )
1240
+ }).strict(),
1241
+ part: z20.string().describe("Resource parts being written. Leave as the default.").default("snippet")
1242
+ }).strict();
1243
+ var outputSchema19 = SubscriptionSchema.extend({
1244
+ alreadySatisfied: z20.literal(true).describe("Present and true when the user was already subscribed.").optional(),
1245
+ alreadySatisfiedReason: z20.string().describe('The upstream code, e.g. "subscriptionDuplicate".').optional()
1246
+ });
1247
+ var definition19 = defineTool19({
1248
+ name: "subscribeToChannel",
1249
+ title: "Subscribe To Channel",
1250
+ description: "Subscribe the authenticated user to a channel. Returns the subscription id (used by unsubscribeFromChannel \u2014 distinct from the channel id). If the user is already subscribed, returns the existing subscription with alreadySatisfied: true rather than failing.",
1251
+ inputSchema: inputSchema19,
1252
+ outputSchema: outputSchema19,
1253
+ annotations: {
1254
+ readOnlyHint: false,
1255
+ destructiveHint: false,
1256
+ idempotentHint: true,
1257
+ openWorldHint: true
1258
+ },
1259
+ connection: "youtube",
1260
+ run: async (input, ctx) => {
1261
+ const url = new URL(`https://www.googleapis.com/youtube/v3/subscriptions`);
1262
+ url.searchParams.set("part", input.part);
1263
+ const res = await ctx.fetch(url.toString(), {
1264
+ method: "POST",
1265
+ headers: { "Content-Type": "application/json" },
1266
+ body: JSON.stringify({ snippet: input.snippet })
1267
+ });
1268
+ if (res.ok) return res.json();
1269
+ if (res.status === 400) {
1270
+ const body = await res.json().catch(() => null);
1271
+ if (hasYouTubeReason(body, "subscriptionDuplicate")) {
1272
+ const channelId = input.snippet.resourceId.channelId;
1273
+ const lookup = new URL(
1274
+ `https://www.googleapis.com/youtube/v3/subscriptions`
1275
+ );
1276
+ lookup.searchParams.set("part", "snippet,contentDetails");
1277
+ lookup.searchParams.set("mine", "true");
1278
+ lookup.searchParams.set("forChannelId", channelId);
1279
+ const lres = await ctx.fetch(lookup.toString(), { method: "GET" });
1280
+ await throwForYouTube(lres, "subscribeToChannel");
1281
+ const lpayload = await lres.json();
1282
+ const existing = lpayload.items?.[0];
1283
+ if (existing) {
1284
+ return {
1285
+ ...existing,
1286
+ alreadySatisfied: true,
1287
+ alreadySatisfiedReason: "subscriptionDuplicate"
1288
+ };
1289
+ }
1290
+ }
1291
+ throw ConnectorHttpError3.fromResponseBody(res, body, {
1292
+ message: `YouTube subscribeToChannel 400: ${body?.error?.message ?? "bad request"}`
1293
+ });
1294
+ }
1295
+ await throwForYouTube(res, "subscribeToChannel");
1296
+ return res.json();
1297
+ }
1298
+ });
1299
+ var subscribeToChannel_default = definition19;
1300
+ await handleIfScriptMain19(import.meta, definition19, { connectionResolvers });
1301
+
1302
+ // scripts/unsubscribeFromChannel.ts
1303
+ import { defineTool as defineTool20, handleIfScriptMain as handleIfScriptMain20 } from "@zapier/connectors-sdk";
1304
+ import { z as z21 } from "zod";
1305
+ var inputSchema20 = z21.object({
1306
+ id: z21.string().describe(
1307
+ "The subscription id to delete (from listSubscriptions, not the channel id)."
1308
+ )
1309
+ }).strict();
1310
+ var outputSchema20 = SuccessResultSchema;
1311
+ var definition20 = defineTool20({
1312
+ name: "unsubscribeFromChannel",
1313
+ title: "Unsubscribe From Channel",
1314
+ description: "Unsubscribe the authenticated user from a channel. The id is the subscription id from listSubscriptions (NOT the channel id).",
1315
+ inputSchema: inputSchema20,
1316
+ outputSchema: outputSchema20,
1317
+ annotations: {
1318
+ readOnlyHint: false,
1319
+ // Reversible — the user can re-subscribe with subscribeToChannel.
1320
+ destructiveHint: false,
1321
+ idempotentHint: true,
1322
+ openWorldHint: true
1323
+ },
1324
+ connection: "youtube",
1325
+ run: async (input, ctx) => {
1326
+ const url = new URL(`https://www.googleapis.com/youtube/v3/subscriptions`);
1327
+ if (input.id !== void 0) {
1328
+ url.searchParams.set("id", String(input.id));
1329
+ }
1330
+ const res = await ctx.fetch(url.toString(), {
1331
+ method: "DELETE"
1332
+ });
1333
+ await throwForYouTube(res, "unsubscribeFromChannel");
1334
+ return { success: true };
1335
+ }
1336
+ });
1337
+ var unsubscribeFromChannel_default = definition20;
1338
+ await handleIfScriptMain20(import.meta, definition20, { connectionResolvers });
1339
+
1340
+ // scripts/updatePlaylist.ts
1341
+ import { defineTool as defineTool21, handleIfScriptMain as handleIfScriptMain21 } from "@zapier/connectors-sdk";
1342
+ import { z as z22 } from "zod";
1343
+ var inputSchema21 = z22.object({
1344
+ id: z22.string().describe("The id of the playlist to update."),
1345
+ snippet: z22.object({
1346
+ title: z22.string().describe("Playlist title (required)."),
1347
+ description: z22.string().describe("Playlist description.").optional(),
1348
+ defaultLanguage: z22.string().describe(
1349
+ "BCP-47 language code of the title/description text, e.g. en."
1350
+ ).optional()
1351
+ }).strict(),
1352
+ status: z22.object({
1353
+ privacyStatus: z22.enum(["public", "unlisted", "private"]).describe("Playlist visibility. Defaults to private if omitted.").optional()
1354
+ }).strict().optional(),
1355
+ part: z22.string().describe("Resource parts being written. Leave as the default.").default("snippet,status")
1356
+ }).strict();
1357
+ var outputSchema21 = PlaylistSchema;
1358
+ var definition21 = defineTool21({
1359
+ name: "updatePlaylist",
1360
+ title: "Update Playlist",
1361
+ description: "Update a playlist's title, description, or privacy. Send the complete desired snippet \u2014 omitted fields within a written part are reset (the API replaces, not merges). Resolve id via listPlaylists.",
1362
+ inputSchema: inputSchema21,
1363
+ outputSchema: outputSchema21,
1364
+ annotations: {
1365
+ readOnlyHint: false,
1366
+ destructiveHint: false,
1367
+ idempotentHint: true,
1368
+ openWorldHint: true
1369
+ },
1370
+ connection: "youtube",
1371
+ run: async (input, ctx) => {
1372
+ const url = new URL(`https://www.googleapis.com/youtube/v3/playlists`);
1373
+ if (input.part !== void 0) {
1374
+ url.searchParams.set("part", String(input.part));
1375
+ }
1376
+ const body = {};
1377
+ if (input.id !== void 0) body["id"] = input.id;
1378
+ if (input.snippet !== void 0) body["snippet"] = input.snippet;
1379
+ if (input.status !== void 0) body["status"] = input.status;
1380
+ const res = await ctx.fetch(url.toString(), {
1381
+ method: "PUT",
1382
+ headers: { "Content-Type": "application/json" },
1383
+ body: JSON.stringify(body)
1384
+ });
1385
+ await throwForYouTube(res, "updatePlaylist");
1386
+ return res.json();
1387
+ }
1388
+ });
1389
+ var updatePlaylist_default = definition21;
1390
+ await handleIfScriptMain21(import.meta, definition21, { connectionResolvers });
1391
+
1392
+ // scripts/updateVideo.ts
1393
+ import { defineTool as defineTool22, handleIfScriptMain as handleIfScriptMain22 } from "@zapier/connectors-sdk";
1394
+ import { z as z23 } from "zod";
1395
+ var inputSchema22 = z23.object({
1396
+ video_id: z23.string().describe("The id of the video to update (you must own it)."),
1397
+ title: z23.string().describe("New title. Max 100 characters.").optional(),
1398
+ description: z23.string().describe("New description.").optional(),
1399
+ tags: z23.array(z23.string()).describe("New tag list (replaces the existing tags).").optional(),
1400
+ category_id: z23.string().describe("New category id (from listVideoCategories).").optional(),
1401
+ privacy_status: z23.enum(["private", "public", "unlisted"]).describe("New privacy status.").optional(),
1402
+ publish_at: z23.string().describe(
1403
+ "Reschedule publication (RFC3339). Requires privacy_status=private."
1404
+ ).optional(),
1405
+ made_for_kids: z23.boolean().describe("COPPA self-declaration (status.selfDeclaredMadeForKids).").optional()
1406
+ }).strict();
1407
+ var outputSchema22 = VideoSchema;
1408
+ var definition22 = defineTool22({
1409
+ name: "updateVideo",
1410
+ title: "Update Video",
1411
+ description: "Update an existing video's metadata (title, description, tags, category, privacy) without disturbing the fields you don't change. Reads the current video first, merges your changes, then writes \u2014 so omitting a field leaves it as-is. You must own the video.",
1412
+ inputSchema: inputSchema22,
1413
+ outputSchema: outputSchema22,
1414
+ annotations: {
1415
+ readOnlyHint: false,
1416
+ destructiveHint: false,
1417
+ idempotentHint: true,
1418
+ openWorldHint: true
1419
+ },
1420
+ connection: "youtube",
1421
+ run: async (input, ctx) => {
1422
+ const getUrl = new URL(`https://www.googleapis.com/youtube/v3/videos`);
1423
+ getUrl.searchParams.set("part", "snippet,status");
1424
+ getUrl.searchParams.set("id", input.video_id);
1425
+ const getRes = await ctx.fetch(getUrl.toString(), { method: "GET" });
1426
+ await throwForYouTube(getRes, "updateVideo");
1427
+ const current = await getRes.json();
1428
+ const video = current.items?.[0];
1429
+ if (!video) {
1430
+ throw new Error(
1431
+ `YouTube updateVideo 404: no video found with id '${input.video_id}'. Verify the id (resolve via searchVideos/getVideo); you can only update videos you own.`
1432
+ );
1433
+ }
1434
+ const cur = video.snippet ?? {};
1435
+ const snippet = {
1436
+ title: input.title ?? cur.title,
1437
+ categoryId: input.category_id ?? cur.categoryId
1438
+ };
1439
+ if (input.description !== void 0)
1440
+ snippet.description = input.description;
1441
+ else if (cur.description !== void 0)
1442
+ snippet.description = cur.description;
1443
+ if (input.tags !== void 0) snippet.tags = input.tags;
1444
+ else if (cur.tags !== void 0) snippet.tags = cur.tags;
1445
+ if (cur.defaultLanguage !== void 0)
1446
+ snippet.defaultLanguage = cur.defaultLanguage;
1447
+ const curStatus = video.status ?? {};
1448
+ const status = {
1449
+ privacyStatus: input.privacy_status ?? curStatus.privacyStatus
1450
+ };
1451
+ if (input.publish_at !== void 0) status.publishAt = input.publish_at;
1452
+ else if (curStatus.publishAt !== void 0)
1453
+ status.publishAt = curStatus.publishAt;
1454
+ if (input.made_for_kids !== void 0)
1455
+ status.selfDeclaredMadeForKids = input.made_for_kids;
1456
+ else if (curStatus.selfDeclaredMadeForKids !== void 0)
1457
+ status.selfDeclaredMadeForKids = curStatus.selfDeclaredMadeForKids;
1458
+ if (curStatus.license !== void 0) status.license = curStatus.license;
1459
+ const putUrl = new URL(`https://www.googleapis.com/youtube/v3/videos`);
1460
+ putUrl.searchParams.set("part", "snippet,status");
1461
+ const putRes = await ctx.fetch(putUrl.toString(), {
1462
+ method: "PUT",
1463
+ headers: { "Content-Type": "application/json" },
1464
+ body: JSON.stringify({ id: input.video_id, snippet, status })
1465
+ });
1466
+ await throwForYouTube(putRes, "updateVideo");
1467
+ return putRes.json();
1468
+ }
1469
+ });
1470
+ var updateVideo_default = definition22;
1471
+ await handleIfScriptMain22(import.meta, definition22, { connectionResolvers });
1472
+
1473
+ // index.ts
1474
+ var connector = defineConnector({
1475
+ scripts: {
1476
+ addVideoToPlaylist: addVideoToPlaylist_default,
1477
+ createPlaylist: createPlaylist_default,
1478
+ deletePlaylist: deletePlaylist_default,
1479
+ deleteVideo: deleteVideo_default,
1480
+ downloadCaption: downloadCaption_default,
1481
+ getChannel: getChannel_default,
1482
+ getVideo: getVideo_default,
1483
+ listCaptions: listCaptions_default,
1484
+ listComments: listComments_default,
1485
+ listPlaylistItems: listPlaylistItems_default,
1486
+ listPlaylists: listPlaylists_default,
1487
+ listSubscriptions: listSubscriptions_default,
1488
+ listVideoCategories: listVideoCategories_default,
1489
+ postComment: postComment_default,
1490
+ rateVideo: rateVideo_default,
1491
+ removeVideoFromPlaylist: removeVideoFromPlaylist_default,
1492
+ replyToComment: replyToComment_default,
1493
+ searchVideos: searchVideos_default,
1494
+ subscribeToChannel: subscribeToChannel_default,
1495
+ unsubscribeFromChannel: unsubscribeFromChannel_default,
1496
+ updatePlaylist: updatePlaylist_default,
1497
+ updateVideo: updateVideo_default
1498
+ },
1499
+ connectionResolvers
1500
+ });
1501
+ var index_default = connector;
1502
+ var {
1503
+ addVideoToPlaylist,
1504
+ createPlaylist,
1505
+ deletePlaylist,
1506
+ deleteVideo,
1507
+ downloadCaption,
1508
+ getChannel,
1509
+ getVideo,
1510
+ listCaptions,
1511
+ listComments,
1512
+ listPlaylistItems,
1513
+ listPlaylists,
1514
+ listSubscriptions,
1515
+ listVideoCategories,
1516
+ postComment,
1517
+ rateVideo,
1518
+ removeVideoFromPlaylist,
1519
+ replyToComment,
1520
+ searchVideos,
1521
+ subscribeToChannel,
1522
+ unsubscribeFromChannel,
1523
+ updatePlaylist,
1524
+ updateVideo
1525
+ } = toFunctions(connector);
1526
+ export {
1527
+ addVideoToPlaylist,
1528
+ createPlaylist,
1529
+ index_default as default,
1530
+ deletePlaylist,
1531
+ deleteVideo,
1532
+ downloadCaption,
1533
+ getChannel,
1534
+ getVideo,
1535
+ listCaptions,
1536
+ listComments,
1537
+ listPlaylistItems,
1538
+ listPlaylists,
1539
+ listSubscriptions,
1540
+ listVideoCategories,
1541
+ postComment,
1542
+ rateVideo,
1543
+ removeVideoFromPlaylist,
1544
+ replyToComment,
1545
+ searchVideos,
1546
+ subscribeToChannel,
1547
+ unsubscribeFromChannel,
1548
+ updatePlaylist,
1549
+ updateVideo
1550
+ };