Skip to content

Conversation

@gianpaj
Copy link
Owner

@gianpaj gianpaj commented Jan 12, 2026

Add a YouTube channel ID extraction script

  • Created scripts/extract-youtube-channel-id.js
  • Supports extracting channel IDs from video URLs, usernames, or direct channel IDs
  • Uses YouTube Data API v3 with YOUTUBE_API_KEY environment variable

Fixes #294

🤖 Generated with Claude Code

Summary by Sourcery

Add a CLI script to extract and validate YouTube channel IDs using the YouTube Data API v3 from various input formats.

New Features:

  • Introduce a Node.js script to resolve a YouTube channel ID from a video URL, channel URL, username, handle, or direct channel ID.
  • Support a verbose mode that prints human-readable channel or video details while always emitting the raw channel ID for scripting.

Enhancements:

  • Validate existing channel IDs and provide informative error and usage output, including colored terminal messages, when API calls fail or inputs are invalid.

claude bot and others added 2 commits December 10, 2025 20:55
- Created scripts/extract-youtube-channel-id.js
- Supports extracting channel IDs from video URLs, usernames, or direct channel IDs
- Uses YouTube Data API v3 with YOUTUBE_API_KEY environment variable
- Includes comprehensive error handling and colored terminal output
- Follows existing project patterns and conventions

Fixes #294

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: Gianfranco P <gianpaj@users.noreply.github.com>
@gianpaj gianpaj requested a review from Copilot January 12, 2026 12:45
@bolt-new-by-stackblitz
Copy link

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@sourcery-ai
Copy link

sourcery-ai bot commented Jan 12, 2026

Reviewer's Guide

Adds a standalone Node.js CLI script to extract and validate YouTube channel IDs from various inputs (video URLs, usernames/handles, or direct channel IDs) using the YouTube Data API v3 and a YOUTUBE_API_KEY environment variable, with optional verbose output and colored logging.

Sequence diagram for YouTube channel ID extraction CLI flow

sequenceDiagram
  actor User
  participant CLI_Script as CLI_Script
  participant YouTube_API as YouTube_Data_API_v3

  User->>CLI_Script: Run extract-youtube-channel-id input [--verbose]
  CLI_Script->>CLI_Script: Parse args, set verbose, read input
  CLI_Script->>CLI_Script: Check YOUTUBE_API_KEY presence on API calls

  alt Input is channel ID
    CLI_Script->>CLI_Script: isChannelId(input)
    CLI_Script->>YouTube_API: GET /channels?part=snippet&id=channelId&key=API_KEY
    YouTube_API-->>CLI_Script: Channel data JSON
    CLI_Script->>CLI_Script: Validate and format channel info
    CLI_Script-->>User: Print channelId (and details if verbose)
  else Input is video URL
    CLI_Script->>CLI_Script: isVideoUrl(input)
    CLI_Script->>CLI_Script: extractVideoId(url)
    CLI_Script->>YouTube_API: GET /videos?part=snippet&id=videoId&key=API_KEY
    YouTube_API-->>CLI_Script: Video data JSON
    CLI_Script->>CLI_Script: Extract channelId, channelTitle, videoTitle
    CLI_Script-->>User: Print channelId (and details if verbose)
  else Input is username or handle
    CLI_Script->>CLI_Script: Normalize username (remove leading @)
    CLI_Script->>YouTube_API: GET /search?part=id,snippet&q=username&type=channel&key=API_KEY
    YouTube_API-->>CLI_Script: Search results JSON
    CLI_Script->>CLI_Script: Map results to channel list
    alt Single match
      CLI_Script-->>User: Print channelId (and details if verbose)
    else Multiple matches
      CLI_Script-->>User: Print channels list (verbose)
      CLI_Script-->>User: Print first channelId (non-verbose)
    end
  end

  alt Error (missing key, HTTP error, no results)
    CLI_Script-->>User: Print error (verbose only)
    CLI_Script->>CLI_Script: Exit with code 1
  end
Loading

File-Level Changes

Change Details Files
Introduce a Node.js CLI script that resolves a YouTube channel ID from different types of user input using YouTube Data API v3 endpoints.
  • Define a CLI entrypoint that parses arguments, supports a --verbose flag, and prints usage/help when no input is provided.
  • Implement helpers to detect input type (channel ID vs YouTube URL vs username/handle) and to extract a video ID from multiple YouTube URL formats via regex.
  • Add API wrapper functions that call YouTube Data API v3 videos, search, and channels endpoints to fetch channel metadata, including error handling for HTTP and API-level errors and missing YOUTUBE_API_KEY.
  • Implement the main resolution flow: validate direct channel IDs, derive channel from video URLs, or search by username/handle, then print the resolved channel ID (and additional metadata when verbose), using ANSI-colored logs for human-readable output and plain channel ID output for scripting.
scripts/extract-youtube-channel-id.js

Assessment against linked issues

Issue Objective Addressed Explanation
#294 Create a Node.js script that uses the YouTube Data API to extract a YouTube channel ID from a YouTube video link.
#294 Support extracting a YouTube channel ID from a YouTube username/handle via the YouTube Data API.
#294 Use an environment variable to provide the YouTube API key in the script.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@gemini-code-assist
Copy link

Summary of Changes

Hello @gianpaj, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a new utility script designed to simplify the process of obtaining YouTube channel IDs. This script provides a flexible way to retrieve channel identifiers, whether starting from a video link, a channel's public handle, or by validating an existing channel ID, thereby streamlining operations that depend on these unique identifiers.

Highlights

  • New Script Added: A new Node.js script, scripts/extract-youtube-channel-id.js, has been introduced to facilitate the extraction of YouTube channel IDs.
  • Flexible Input Options: The script supports extracting channel IDs from various inputs, including YouTube video URLs, channel usernames/handles (e.g., 'lexfridman' or '@lexfridman'), and direct YouTube channel IDs for validation.
  • YouTube Data API Integration: It leverages the YouTube Data API v3 to fetch channel information, requiring a YOUTUBE_API_KEY environment variable for authentication.
  • Verbose Output Option: Users can utilize a --verbose flag to receive detailed output, including video titles, channel titles, and descriptions, instead of just the channel ID.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@netlify
Copy link

netlify bot commented Jan 12, 2026

Deploy Preview for walnut failed.

Name Link
🔨 Latest commit fcd4340
🔍 Latest deploy log https://app.netlify.com/projects/walnut/deploys/6964ee0e60a2a70008e13061

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a utility script for extracting YouTube channel IDs from various input formats including video URLs, usernames/handles, and direct channel IDs using the YouTube Data API v3.

Changes:

  • Added a new Node.js script that accepts video URLs, usernames, or channel IDs as input
  • Implemented API integration with YouTube Data API v3 requiring YOUTUBE_API_KEY environment variable
  • Included verbose mode flag for detailed output versus simple channel ID output

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

log('\n✅ Channel found:', 'green');
log(` Channel ID: ${channelInfo.channelId}`, 'reset');
log(` Channel Title: ${channelInfo.channelTitle}`, 'reset');
log(` Description: ${channelInfo.description.substring(0, 100)}...`, 'reset');
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential error if channelInfo.description is null, undefined, or has fewer than 100 characters. The substring method will fail on null/undefined values. Consider adding a check or using optional chaining with a fallback.

Suggested change
log(` Description: ${channelInfo.description.substring(0, 100)}...`, 'reset');
log(` Description: ${(channelInfo.description ?? '').substring(0, 100)}...`, 'reset');

Copilot uses AI. Check for mistakes.
log('\n✅ Channel found:', 'green');
log(` Channel ID: ${channel.channelId}`, 'reset');
log(` Channel Title: ${channel.channelTitle}`, 'reset');
log(` Description: ${channel.description.substring(0, 100)}...`, 'reset');
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential error if channel.description is null, undefined, or has fewer than 100 characters. The substring method will fail on null/undefined values. Consider adding a check or using optional chaining with a fallback.

Copilot uses AI. Check for mistakes.
results.forEach((channel, index) => {
log(`\n${index + 1}. ${channel.channelTitle}`, 'blue');
log(` Channel ID: ${channel.channelId}`, 'reset');
log(` Description: ${channel.description.substring(0, 100)}...`, 'reset');
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential error if channel.description is null, undefined, or has fewer than 100 characters. The substring method will fail on null/undefined values. Consider adding a check or using optional chaining with a fallback.

Copilot uses AI. Check for mistakes.
Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 4 issues, and left some high level feedback:

  • The usage/help output in main() is wrapped in log() calls, so with verbose defaulting to false nothing is printed when no args are provided—consider using console.error/console.log directly for help text so users actually see it.
  • The script relies on a global fetch, which is only available in newer Node.js versions; to make this more robust across environments, either import a fetch implementation (e.g. node-fetch/undici) or explicitly document and/or assert the required Node.js version.
  • Several places assume snippet.description is a string and call .substring(0, 100) on it; to avoid runtime errors on channels without descriptions, add a null/undefined guard or a default string before truncating.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The usage/help output in `main()` is wrapped in `log()` calls, so with `verbose` defaulting to `false` nothing is printed when no args are provided—consider using `console.error`/`console.log` directly for help text so users actually see it.
- The script relies on a global `fetch`, which is only available in newer Node.js versions; to make this more robust across environments, either import a fetch implementation (e.g. `node-fetch`/`undici`) or explicitly document and/or assert the required Node.js version.
- Several places assume `snippet.description` is a string and call `.substring(0, 100)` on it; to avoid runtime errors on channels without descriptions, add a null/undefined guard or a default string before truncating.

## Individual Comments

### Comment 1
<location> `scripts/extract-youtube-channel-id.js:208-217` </location>
<code_context>
+async function main() {
+  const args = process.argv.slice(2);
+
+  if (args.length === 0) {
+    log('Usage: node scripts/extract-youtube-channel-id.js <input> [--verbose]', 'yellow');
+    log('', 'reset');
+    log('Where <input> can be:', 'blue');
+    log('  - YouTube video URL: https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'blue');
+    log('  - YouTube short URL: https://youtu.be/dQw4w9WgXcQ', 'blue');
+    log('  - Channel username: lexfridman or @lexfridman', 'blue');
+    log('  - Channel ID: UC2D6eRvCeMtcF5OGHf1-trw', 'blue');
+    log('', 'reset');
+    log('Options:', 'blue');
+    log('  --verbose - Output detailed information instead of just the channel ID', 'blue');
+    log('', 'reset');
+    log('Environment variable required: YOUTUBE_API_KEY', 'yellow');
+    process.exit(1);
+  }
+
</code_context>

<issue_to_address>
**issue (bug_risk):** Help/usage output is suppressed when no arguments are passed.

Because `verbose` remains `false` here, all `log(...)` calls are skipped and the script exits with code 1 without showing any help, which looks like a silent failure. Either write help text with `console.log`/`console.error` in this branch, or set `verbose = true` before calling `log(...)` so the usage information is always displayed.
</issue_to_address>

### Comment 2
<location> `scripts/extract-youtube-channel-id.js:113-122` </location>
<code_context>
+        }
+      }
+    }
+  } catch (error) {
+    log(`❌ Error: ${error.message}`, 'red');
+    process.exit(1);
+  }
+}
</code_context>

<issue_to_address>
**issue (bug_risk):** Errors are hidden unless `--verbose` is enabled.

Because `log` only prints when `--verbose` is enabled, this catch block exits with code 1 but shows no error to non-verbose users, making failures hard to debug. Consider always printing the error (e.g., with `console.error`) and reserving `log`/`verbose` for additional details.
</issue_to_address>

### Comment 3
<location> `scripts/extract-youtube-channel-id.js:236-245` </location>
<code_context>
+      log(`   Description: ${channelInfo.description.substring(0, 100)}...`, 'reset');
</code_context>

<issue_to_address>
**issue:** Potential crash if `description` is missing or not a string.

Several calls assume `description` is a non-empty string and use `.substring(0, 100)` directly. If the API returns `null`, `undefined`, or a non-string, this will throw and stop the script. Consider safely coercing (e.g. `const desc = channelInfo.description || ''`) before substring, or conditionally logging the description only when it’s a valid string.
</issue_to_address>

### Comment 4
<location> `scripts/extract-youtube-channel-id.js:91` </location>
<code_context>
+  const url = `https://www.googleapis.com/youtube/v3/videos?part=snippet&id=${videoId}&key=${YOUTUBE_API_KEY}`;
+
+  try {
+    const response = await fetch(url);
+
+    if (!response.ok) {
</code_context>

<issue_to_address>
**question (bug_risk):** Reliance on global `fetch` may break in older Node versions.

This relies on `fetch` being globally available, which is only true in Node 18+. In earlier Node versions it will throw a `ReferenceError`. If this needs to run across different runtimes, either import a fetch polyfill (e.g. `node-fetch`) or explicitly require Node 18+ via the `engines` field so consumers know a global `fetch` is expected.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +208 to +217
if (args.length === 0) {
log('Usage: node scripts/extract-youtube-channel-id.js <input> [--verbose]', 'yellow');
log('', 'reset');
log('Where <input> can be:', 'blue');
log(' - YouTube video URL: https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'blue');
log(' - YouTube short URL: https://youtu.be/dQw4w9WgXcQ', 'blue');
log(' - Channel username: lexfridman or @lexfridman', 'blue');
log(' - Channel ID: UC2D6eRvCeMtcF5OGHf1-trw', 'blue');
log('', 'reset');
log('Options:', 'blue');
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Help/usage output is suppressed when no arguments are passed.

Because verbose remains false here, all log(...) calls are skipped and the script exits with code 1 without showing any help, which looks like a silent failure. Either write help text with console.log/console.error in this branch, or set verbose = true before calling log(...) so the usage information is always displayed.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new script to extract YouTube channel IDs, which is a great addition. The code is well-organized, but I've identified a few issues. There's a critical problem with how command-line arguments are parsed, which can cause the script to fail or behave unexpectedly. Additionally, important output like usage instructions and error messages are suppressed unless the --verbose flag is used. My review includes suggestions to fix these issues and also to improve code clarity and maintainability by removing redundant checks.

@gianpaj gianpaj merged commit fac7dce into master Jan 12, 2026
4 of 10 checks passed
@gianpaj gianpaj deleted the claude/issue-294-20251210-2053 branch January 12, 2026 12:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

YouTube channel script

1 participant