Metadata-Version: 2.4
Name: ranktube
Version: 0.1.0
Summary: YouTube search CLI and UI that ranks results by relevance using YouTube Data API v3
Author: Manjunath Shetty
License-Expression: MIT
Project-URL: Homepage, https://github.com/mjshetty/ranktube
Project-URL: Repository, https://github.com/mjshetty/ranktube
Project-URL: Bug Tracker, https://github.com/mjshetty/ranktube/issues
Keywords: youtube,search,ranking,cli,relevance,api
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: End Users/Desktop
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet
Classifier: Topic :: Multimedia :: Video
Classifier: Topic :: Utilities
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: google-api-python-client>=2.0.0
Requires-Dist: google-auth>=2.0.0
Requires-Dist: python-dotenv>=1.0.0
Provides-Extra: ui
Requires-Dist: streamlit>=1.32.0; extra == "ui"
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Provides-Extra: all
Requires-Dist: ranktube[dev,ui]; extra == "all"

# RankTube

A Python CLI tool that searches YouTube using the YouTube Data API v3, scores results by relevance, and outputs filtered video URLs. Designed for bulk discovery of videos matching keyword themes with intelligent ranking.

---

## What is this tool?

`RankTube` takes one or more keyword phrases, queries YouTube, and returns the most relevant video URLs — ranked by how well each video's title, description, tags, and channel name match your search terms. It supports filtering by channel, limiting result count, setting a minimum relevance threshold, and choosing between plain URL, JSON, or detailed output formats.

---

## How it works

```
Keywords → YouTube Search API → Raw Videos → Relevance Scorer → Formatted Output
                                                    ↑
                              Channel Filter (optional, resolved by name or ID)
```

1. **Search** — Keywords are joined into a single query and sent to `search.list` (YouTube Data API v3). Results are paginated until the requested count is reached.
2. **Enrich** — Video IDs are passed to `videos.list` in batches of 50 to fetch tags not returned by the search endpoint.
3. **Score** — Each video is scored against the original keywords using a weighted algorithm (see below).
4. **Filter** — Videos below `--min-score` are dropped. Results are sorted by score descending.
5. **Output** — Results are printed in the chosen format: plain URLs, JSON, or a verbose block per video.

### Relevance Scoring

| Signal | Weight | Method |
|---|---|---|
| Title token overlap | 40% | Fraction of keyword tokens found in title |
| Description overlap | 25% | First 500 characters only |
| Tags overlap | 20% | Video tags vs keyword tokens |
| Exact phrase bonus | 10% | Multi-word phrase appears literally in title or description |
| Channel name overlap | 5% | Channel title tokens vs keyword tokens |

Scores range from 0.0 to 1.0. Default minimum threshold is 0.3.

---

## Python Utilities Used

| Library | Purpose |
|---|---|
| `google-api-python-client` | YouTube Data API v3 client (`search.list`, `videos.list`) |
| `google-auth` | API key authentication |
| `python-dotenv` | Auto-loads `YOUTUBE_API_KEY` from `.env` file |
| `argparse` | CLI argument parsing (stdlib) |
| `dataclasses` | `ScoredVideo` result dataclass (stdlib) |
| `re` | Token extraction for scoring (stdlib) |
| `json` | JSON output formatting (stdlib) |
| `pytest` | Unit and mocked integration tests |

---

## Project Structure

```
ranktube/
├── pyproject.toml           # Package config and entry point
├── requirements.txt
├── .env                     # Your API key (never commit this)
├── .env.example             # Template for .env
├── .gitignore
├── src/ranktube/
│   ├── cli.py               # Argument parsing and orchestration
│   ├── api.py               # YouTube API client and pagination
│   ├── resolver.py          # Channel name → channel ID resolution
│   ├── scorer.py            # Relevance scoring engine
│   └── formatter.py         # Output formatting (urls / json / verbose)
└── tests/
    ├── test_scorer.py        # 27 unit tests (no API calls)
    ├── test_resolver.py      # 6 mocked tests
    └── test_api.py           # 12 mocked tests
```

---

## Features

- **Multi-keyword search** — Pass multiple phrases; they are combined into one query and scored together
- **Relevance scoring** — Weighted algorithm ranks results by how well they match your keywords
- **Minimum score filter** — `--min-score` drops low-relevance noise from results
- **Top-N limiting** — `--top` caps the number of results returned
- **Channel filtering** — Restrict results to a specific channel by name or ID
- **Channel name resolution** — `--channel "Khan Academy"` automatically resolves to the channel ID
- **Multiple output formats** — Plain URLs, JSON array, or verbose blocks with score and snippet
- **API key from `.env`** — No need to export environment variables manually
- **Quota-efficient pagination** — Stops fetching early once `--top` results are collected
- **Tag enrichment** — Fetches video tags (not returned by search) in batches of 50 for more accurate scoring

---

## Setup

```bash
# 1. Clone / navigate to the project
cd ranktube

# 2. Create and activate a virtual environment
python3 -m venv venv && source venv/bin/activate

# 3. Install the package
pip install -e .

# 4. Add your YouTube Data API v3 key to .env
echo 'YOUTUBE_API_KEY=AIza...' > .env
```

Get a YouTube Data API v3 key from [Google Cloud Console](https://console.cloud.google.com/):
- Enable **YouTube Data API v3** under APIs & Services → Library
- Create an API key under APIs & Services → Credentials

---

## CLI Reference

```
rt [-h] [--channel NAME | --channel-id ID]
   [--top N] [--min-score THRESHOLD]
   [--output {urls,json,verbose,details}]
   [--api-key KEY]
   keywords [keywords ...]
```

### Arguments

| Argument | Type | Default | Description |
|---|---|---|---|
| `keywords` | positional (1+) | required | One or more keyword phrases to search |
| `--channel NAME` | optional | — | Channel display name (auto-resolved to ID) |
| `--channel-id ID` | optional | — | Direct YouTube channel ID (skips resolution) |
| `--top N` | optional | all | Return at most N results |
| `--min-score THRESHOLD` | optional | `0.3` | Minimum relevance score (0.0–1.0) |
| `--output` | optional | `urls` | Output format: `urls`, `details`, `json`, or `verbose` |
| `--api-key KEY` | optional | env var | API key (falls back to `YOUTUBE_API_KEY`) |

`--channel` and `--channel-id` are mutually exclusive.

The tool can also be invoked as `ranktube` (alias for `rt`).

---

## Example Commands

### Basic search — plain URL output
```bash
rt "kids brainstorming"
```

### Multiple keywords
```bash
rt "kids brainstorming" "kids learning"
```

### Limit to top 10 results
```bash
rt "kids brainstorming" --top 10
```

### JSON output
```bash
rt "kids brainstorming" --top 10 --output json
```

### Verbose output with score and snippet
```bash
rt "kids brainstorming" --top 5 --output verbose
```

### Links with details (title, channel, snippet, matched keywords)
```bash
rt "kids brainstorming" --top 5 --output details
```

### Filter by channel name
```bash
rt "kids brainstorming" --channel "Khan Academy" --output verbose
```

### Filter by direct channel ID
```bash
rt "kids learning" --channel-id UC4a-Gbdigs3jaI_mG1Um6Hg --output json
```

### High-relevance results only
```bash
rt "kids motivational" --min-score 0.5
```

### Pass API key directly (overrides .env)
```bash
rt "kids brainstorming" --api-key AIza...
```

---

## Sample Verbose Output

```
------------------------------------------------------------
#1  Score: 0.7250
Title:   Kids Brainstorming Activity | Creative Thinking
Channel: Learning Tree
URL:     https://www.youtube.com/watch?v=abc123
Snippet: In this video, kids engage in a fun brainstorming session...
Matched: kids brainstorming
------------------------------------------------------------
#2  Score: 0.5100
Title:   Brainstorming Ideas with Children
Channel: Education World
URL:     https://www.youtube.com/watch?v=def456
Snippet: A classroom activity where students brainstorm...
Matched: kids brainstorming
------------------------------------------------------------
```

---

## Running Tests

```bash
source venv/bin/activate
pytest tests/ -v
```

All 43 tests run without a live API key — API calls are fully mocked.

---

## API Quota

| Operation | Cost |
|---|---|
| `search.list` (per page of 50) | 100 units |
| `videos.list` (per batch of 50) | 1 unit |
| Free daily quota | 10,000 units |

Fetching 100 results costs ~102 units. Fetching 500 results costs ~1,010 units — well within the free tier.
