yt-metrics-cli 0.2.0__tar.gz
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.
- yt_metrics_cli-0.2.0/.claude/CLAUDE.md +51 -0
- yt_metrics_cli-0.2.0/.env.example +15 -0
- yt_metrics_cli-0.2.0/.github/ISSUE_TEMPLATE/bug_report.yml +39 -0
- yt_metrics_cli-0.2.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
- yt_metrics_cli-0.2.0/.github/ISSUE_TEMPLATE/feature_request.yml +23 -0
- yt_metrics_cli-0.2.0/.github/pull_request_template.md +21 -0
- yt_metrics_cli-0.2.0/.github/workflows/ci.yml +45 -0
- yt_metrics_cli-0.2.0/.github/workflows/pages.yml +41 -0
- yt_metrics_cli-0.2.0/.github/workflows/release.yml +44 -0
- yt_metrics_cli-0.2.0/.gitignore +41 -0
- yt_metrics_cli-0.2.0/.release-please-manifest.json +3 -0
- yt_metrics_cli-0.2.0/CHANGELOG.md +16 -0
- yt_metrics_cli-0.2.0/CODE_OF_CONDUCT.md +37 -0
- yt_metrics_cli-0.2.0/CONTRIBUTING.md +45 -0
- yt_metrics_cli-0.2.0/LICENSE +21 -0
- yt_metrics_cli-0.2.0/Makefile +37 -0
- yt_metrics_cli-0.2.0/PKG-INFO +144 -0
- yt_metrics_cli-0.2.0/README.md +110 -0
- yt_metrics_cli-0.2.0/SECURITY.md +30 -0
- yt_metrics_cli-0.2.0/Taskfile.yml +61 -0
- yt_metrics_cli-0.2.0/channels.example.yml +7 -0
- yt_metrics_cli-0.2.0/pyproject.toml +72 -0
- yt_metrics_cli-0.2.0/release-please-config.json +11 -0
- yt_metrics_cli-0.2.0/site/astro.config.mjs +45 -0
- yt_metrics_cli-0.2.0/site/package-lock.json +6851 -0
- yt_metrics_cli-0.2.0/site/package.json +17 -0
- yt_metrics_cli-0.2.0/site/public/favicon.svg +6 -0
- yt_metrics_cli-0.2.0/site/src/assets/logo.svg +6 -0
- yt_metrics_cli-0.2.0/site/src/content/docs/getting-started.md +106 -0
- yt_metrics_cli-0.2.0/site/src/content/docs/index.mdx +90 -0
- yt_metrics_cli-0.2.0/site/src/content.config.ts +7 -0
- yt_metrics_cli-0.2.0/site/src/styles/custom.css +52 -0
- yt_metrics_cli-0.2.0/site/tsconfig.json +3 -0
- yt_metrics_cli-0.2.0/src/__init__.py +3 -0
- yt_metrics_cli-0.2.0/src/analyzer.py +314 -0
- yt_metrics_cli-0.2.0/src/config.py +62 -0
- yt_metrics_cli-0.2.0/src/exporters/__init__.py +15 -0
- yt_metrics_cli-0.2.0/src/exporters/csv_exporter.py +55 -0
- yt_metrics_cli-0.2.0/src/exporters/readme_exporter.py +115 -0
- yt_metrics_cli-0.2.0/src/exporters/text_exporter.py +325 -0
- yt_metrics_cli-0.2.0/src/exporters/url_exporter.py +49 -0
- yt_metrics_cli-0.2.0/src/main.py +213 -0
- yt_metrics_cli-0.2.0/src/metrics.py +75 -0
- yt_metrics_cli-0.2.0/src/transcript.py +83 -0
- yt_metrics_cli-0.2.0/tasks/todo.md +29 -0
- yt_metrics_cli-0.2.0/tests/__init__.py +0 -0
- yt_metrics_cli-0.2.0/tests/conftest.py +150 -0
- yt_metrics_cli-0.2.0/tests/test_analyzer.py +248 -0
- yt_metrics_cli-0.2.0/tests/test_cli.py +94 -0
- yt_metrics_cli-0.2.0/tests/test_config.py +72 -0
- yt_metrics_cli-0.2.0/tests/test_exporters.py +147 -0
- yt_metrics_cli-0.2.0/tests/test_metrics.py +145 -0
- yt_metrics_cli-0.2.0/tests/test_transcript.py +125 -0
- yt_metrics_cli-0.2.0/uv.lock +1038 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# yt-metrics-cli
|
|
2
|
+
|
|
3
|
+
> CLI for YouTube channel analysis and transcript downloading.
|
|
4
|
+
|
|
5
|
+
## Architecture
|
|
6
|
+
|
|
7
|
+
- **CLI Layer:** `src/main.py` — Entry point with `channels` and `transcript` commands
|
|
8
|
+
- **Config:** `src/config.py` — Constants and environment variable management
|
|
9
|
+
- **Core:** `src/analyzer.py` — YouTube API wrapper (channel resolution, batch video stats)
|
|
10
|
+
- **Metrics:** `src/metrics.py` — Pure engagement calculations (6 computed fields)
|
|
11
|
+
- **Transcript:** `src/transcript.py` — Transcript download with 3-level fallback
|
|
12
|
+
- **Export:** `src/exporters.py` — Report generators (CSV, TXT, README)
|
|
13
|
+
|
|
14
|
+
## Technical Standards
|
|
15
|
+
|
|
16
|
+
| Requirement | Tool/Pattern |
|
|
17
|
+
|---|---|
|
|
18
|
+
| Python | 3.12+ |
|
|
19
|
+
| Type hints | mypy --strict |
|
|
20
|
+
| Dependencies | uv |
|
|
21
|
+
| Formatting | Ruff |
|
|
22
|
+
| Testing | pytest + pytest-cov |
|
|
23
|
+
| Build | hatchling |
|
|
24
|
+
|
|
25
|
+
## Key Paths
|
|
26
|
+
|
|
27
|
+
| Path | Role |
|
|
28
|
+
|---|---|
|
|
29
|
+
| `src/main.py` | CLI entry point |
|
|
30
|
+
| `src/config.py` | Configuration and constants |
|
|
31
|
+
| `src/analyzer.py` | YouTube API wrapper |
|
|
32
|
+
| `src/metrics.py` | Engagement metric calculations |
|
|
33
|
+
| `src/transcript.py` | Transcript downloader with fallback chain |
|
|
34
|
+
| `src/exporters.py` | Report generators (CSV, text, README) |
|
|
35
|
+
| `tests/` | pytest suite |
|
|
36
|
+
| `site/` | Astro Starlight documentation |
|
|
37
|
+
|
|
38
|
+
## Verification Commands
|
|
39
|
+
|
|
40
|
+
All commands go through the Makefile:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
make install # Create venv + install deps
|
|
44
|
+
make lint # Ruff linter
|
|
45
|
+
make typecheck # mypy --strict
|
|
46
|
+
make test # pytest with coverage
|
|
47
|
+
make check # lint + typecheck + test
|
|
48
|
+
make build # check + uv build
|
|
49
|
+
make run # Run channel analysis
|
|
50
|
+
make clean # Remove build artifacts
|
|
51
|
+
```
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Required: YouTube Data API v3 key
|
|
2
|
+
# Get one at: https://console.cloud.google.com/apis/credentials
|
|
3
|
+
YOUTUBE_API_KEY=your_api_key_here
|
|
4
|
+
|
|
5
|
+
# Optional: Max videos to fetch per channel (default: 50)
|
|
6
|
+
# MAX_RESULTS_PER_CHANNEL=50
|
|
7
|
+
|
|
8
|
+
# Optional: Output directory for reports (default: ./output)
|
|
9
|
+
# OUTPUT_DIR=./output
|
|
10
|
+
|
|
11
|
+
# Optional: Video ID for transcript mode (default: tLkRAqmAEtE)
|
|
12
|
+
# VIDEO_ID=your_video_id_here
|
|
13
|
+
|
|
14
|
+
# Optional: Local transcript fixtures directory
|
|
15
|
+
# YOUTUBE_TRANSCRIPT_FIXTURES_DIR=./fixtures
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
name: Bug Report
|
|
2
|
+
description: Report a bug or unexpected behavior
|
|
3
|
+
labels: ["bug"]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: description
|
|
7
|
+
attributes:
|
|
8
|
+
label: Description
|
|
9
|
+
description: What happened? What did you expect to happen?
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: steps
|
|
14
|
+
attributes:
|
|
15
|
+
label: Steps to Reproduce
|
|
16
|
+
description: Minimal steps to reproduce the issue
|
|
17
|
+
placeholder: |
|
|
18
|
+
1. Set up .env with YOUTUBE_API_KEY
|
|
19
|
+
2. Run `yt-metrics channels`
|
|
20
|
+
3. See error
|
|
21
|
+
validations:
|
|
22
|
+
required: true
|
|
23
|
+
- type: textarea
|
|
24
|
+
id: environment
|
|
25
|
+
attributes:
|
|
26
|
+
label: Environment
|
|
27
|
+
description: Python version, OS, yt-metrics-cli version
|
|
28
|
+
placeholder: |
|
|
29
|
+
- yt-metrics-cli version: 0.1.0
|
|
30
|
+
- Python: 3.12.8
|
|
31
|
+
- OS: macOS 15.2 / Ubuntu 24.04
|
|
32
|
+
validations:
|
|
33
|
+
required: true
|
|
34
|
+
- type: textarea
|
|
35
|
+
id: logs
|
|
36
|
+
attributes:
|
|
37
|
+
label: Logs / Error Output
|
|
38
|
+
description: Paste any relevant error messages or logs
|
|
39
|
+
render: text
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
name: Feature Request
|
|
2
|
+
description: Suggest a new feature or improvement
|
|
3
|
+
labels: ["enhancement"]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: problem
|
|
7
|
+
attributes:
|
|
8
|
+
label: Problem
|
|
9
|
+
description: What problem does this solve? What's the current limitation?
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: solution
|
|
14
|
+
attributes:
|
|
15
|
+
label: Proposed Solution
|
|
16
|
+
description: How should this work? Include examples if possible.
|
|
17
|
+
validations:
|
|
18
|
+
required: true
|
|
19
|
+
- type: textarea
|
|
20
|
+
id: alternatives
|
|
21
|
+
attributes:
|
|
22
|
+
label: Alternatives Considered
|
|
23
|
+
description: What other approaches did you consider?
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
<!-- Brief description of what this PR does and why -->
|
|
4
|
+
|
|
5
|
+
## Changes
|
|
6
|
+
|
|
7
|
+
-
|
|
8
|
+
|
|
9
|
+
## Testing
|
|
10
|
+
|
|
11
|
+
- [ ] `make check` passes (lint + typecheck + tests)
|
|
12
|
+
- [ ] New tests added for new functionality
|
|
13
|
+
- [ ] Manual testing completed
|
|
14
|
+
|
|
15
|
+
## Type
|
|
16
|
+
|
|
17
|
+
- [ ] Bug fix
|
|
18
|
+
- [ ] New feature
|
|
19
|
+
- [ ] Refactor
|
|
20
|
+
- [ ] Documentation
|
|
21
|
+
- [ ] CI/Build
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [master]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
check:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.12", "3.13"]
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- uses: astral-sh/setup-uv@v5
|
|
19
|
+
with:
|
|
20
|
+
enable-cache: true
|
|
21
|
+
|
|
22
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
23
|
+
run: uv python install ${{ matrix.python-version }}
|
|
24
|
+
|
|
25
|
+
- name: Install
|
|
26
|
+
run: uv venv && uv pip install -e ".[dev]"
|
|
27
|
+
|
|
28
|
+
- name: Lint
|
|
29
|
+
run: uv run ruff check src/ tests/
|
|
30
|
+
|
|
31
|
+
- name: Type check
|
|
32
|
+
run: uv run mypy src/
|
|
33
|
+
|
|
34
|
+
- name: Test
|
|
35
|
+
run: uv run pytest tests/ -v --cov=src --cov-report=term-missing --cov-report=xml
|
|
36
|
+
|
|
37
|
+
- name: Upload coverage
|
|
38
|
+
if: matrix.python-version == '3.12'
|
|
39
|
+
uses: codecov/codecov-action@v5
|
|
40
|
+
with:
|
|
41
|
+
files: coverage.xml
|
|
42
|
+
fail_ci_if_error: false
|
|
43
|
+
|
|
44
|
+
- name: Build
|
|
45
|
+
run: uv build
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
name: Deploy to GitHub Pages
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches: [master]
|
|
5
|
+
paths: ['site/**']
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
pages: write
|
|
10
|
+
id-token: write
|
|
11
|
+
concurrency:
|
|
12
|
+
group: pages
|
|
13
|
+
cancel-in-progress: true
|
|
14
|
+
jobs:
|
|
15
|
+
build:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
- uses: actions/setup-node@v4
|
|
20
|
+
with:
|
|
21
|
+
node-version: 22
|
|
22
|
+
cache: npm
|
|
23
|
+
cache-dependency-path: site/package-lock.json
|
|
24
|
+
- name: Install
|
|
25
|
+
working-directory: site
|
|
26
|
+
run: npm ci
|
|
27
|
+
- name: Build
|
|
28
|
+
working-directory: site
|
|
29
|
+
run: npm run build
|
|
30
|
+
- uses: actions/upload-pages-artifact@v3
|
|
31
|
+
with:
|
|
32
|
+
path: site/dist
|
|
33
|
+
deploy:
|
|
34
|
+
needs: build
|
|
35
|
+
runs-on: ubuntu-latest
|
|
36
|
+
environment:
|
|
37
|
+
name: github-pages
|
|
38
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
39
|
+
steps:
|
|
40
|
+
- id: deployment
|
|
41
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: write
|
|
9
|
+
pull-requests: write
|
|
10
|
+
id-token: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
release-please:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
outputs:
|
|
16
|
+
release_created: ${{ steps.release.outputs.release_created }}
|
|
17
|
+
tag_name: ${{ steps.release.outputs.tag_name }}
|
|
18
|
+
steps:
|
|
19
|
+
- uses: googleapis/release-please-action@v4
|
|
20
|
+
id: release
|
|
21
|
+
with:
|
|
22
|
+
release-type: python
|
|
23
|
+
token: ${{ secrets.RELEASE_TOKEN }}
|
|
24
|
+
|
|
25
|
+
publish:
|
|
26
|
+
needs: release-please
|
|
27
|
+
if: needs.release-please.outputs.release_created == 'true'
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
environment: pypi
|
|
30
|
+
permissions:
|
|
31
|
+
id-token: write
|
|
32
|
+
steps:
|
|
33
|
+
- uses: actions/checkout@v4
|
|
34
|
+
|
|
35
|
+
- uses: astral-sh/setup-uv@v5
|
|
36
|
+
|
|
37
|
+
- name: Set up Python
|
|
38
|
+
run: uv python install 3.12
|
|
39
|
+
|
|
40
|
+
- name: Build
|
|
41
|
+
run: uv build
|
|
42
|
+
|
|
43
|
+
- name: Publish to PyPI
|
|
44
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.pyc
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.venv/
|
|
6
|
+
dist/
|
|
7
|
+
|
|
8
|
+
# Tool caches
|
|
9
|
+
.ruff_cache/
|
|
10
|
+
.mypy_cache/
|
|
11
|
+
.pytest_cache/
|
|
12
|
+
.coverage
|
|
13
|
+
coverage.xml
|
|
14
|
+
htmlcov/
|
|
15
|
+
|
|
16
|
+
# Astro / Node
|
|
17
|
+
site/node_modules/
|
|
18
|
+
site/dist/
|
|
19
|
+
site/.astro/
|
|
20
|
+
site/.vscode/
|
|
21
|
+
|
|
22
|
+
# Claude
|
|
23
|
+
.claude/plans/
|
|
24
|
+
|
|
25
|
+
# Project
|
|
26
|
+
output/
|
|
27
|
+
.env
|
|
28
|
+
channels.yml
|
|
29
|
+
*.log
|
|
30
|
+
|
|
31
|
+
# Editor
|
|
32
|
+
*~
|
|
33
|
+
*.swp
|
|
34
|
+
|
|
35
|
+
# Worktrees
|
|
36
|
+
.worktrees/
|
|
37
|
+
|
|
38
|
+
# Legacy
|
|
39
|
+
poetry.lock
|
|
40
|
+
.cache/
|
|
41
|
+
.cache_ggshield
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.2.0](https://github.com/mlorentedev/yt-metrics-cli/compare/v0.1.0...v0.2.0) (2026-03-15)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add API rate limiting and README overhaul ([#8](https://github.com/mlorentedev/yt-metrics-cli/issues/8)) ([d7e474d](https://github.com/mlorentedev/yt-metrics-cli/commit/d7e474d2fce5627b6bca13543193fd85dcb6da6d))
|
|
9
|
+
|
|
10
|
+
## 0.1.0 (2026-03-15)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* add poetry.lock to .gitignore ([a501d2c](https://github.com/mlorentedev/youtube-toolkit/commit/a501d2c126366eb866ec791c9d1901438477a29b))
|
|
16
|
+
* use correct RELEASE_TOKEN secret name ([#6](https://github.com/mlorentedev/youtube-toolkit/issues/6)) ([357c212](https://github.com/mlorentedev/youtube-toolkit/commit/357c212d8ce22bd6cde7ab3a01855b35e9f9aa3a))
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our
|
|
6
|
+
community a harassment-free experience for everyone, regardless of age, body
|
|
7
|
+
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
|
8
|
+
identity and expression, level of experience, education, socio-economic status,
|
|
9
|
+
nationality, personal appearance, race, caste, color, religion, or sexual
|
|
10
|
+
identity and orientation.
|
|
11
|
+
|
|
12
|
+
## Our Standards
|
|
13
|
+
|
|
14
|
+
Examples of behavior that contributes to a positive environment:
|
|
15
|
+
|
|
16
|
+
- Using welcoming and inclusive language
|
|
17
|
+
- Being respectful of differing viewpoints and experiences
|
|
18
|
+
- Gracefully accepting constructive criticism
|
|
19
|
+
- Focusing on what is best for the community
|
|
20
|
+
|
|
21
|
+
Examples of unacceptable behavior:
|
|
22
|
+
|
|
23
|
+
- Trolling, insulting/derogatory comments, and personal or political attacks
|
|
24
|
+
- Public or private harassment
|
|
25
|
+
- Publishing others' private information without explicit permission
|
|
26
|
+
- Other conduct which could reasonably be considered inappropriate
|
|
27
|
+
|
|
28
|
+
## Enforcement
|
|
29
|
+
|
|
30
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
31
|
+
reported to the project maintainer. All complaints will be reviewed and
|
|
32
|
+
investigated and will result in a response that is deemed necessary and
|
|
33
|
+
appropriate to the circumstances.
|
|
34
|
+
|
|
35
|
+
## Attribution
|
|
36
|
+
|
|
37
|
+
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), version 2.1.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
## Setup
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
git clone https://github.com/mlorentedev/yt-metrics-cli.git
|
|
7
|
+
cd yt-metrics-cli
|
|
8
|
+
make install
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Development
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
make check # lint + typecheck + test (run before every PR)
|
|
15
|
+
make lint # ruff only
|
|
16
|
+
make typecheck # mypy --strict only
|
|
17
|
+
make test # pytest only
|
|
18
|
+
make build # full build (runs check first)
|
|
19
|
+
make run # run channel analysis
|
|
20
|
+
make site # build documentation site
|
|
21
|
+
make site-dev # start docs dev server
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Pull Requests
|
|
25
|
+
|
|
26
|
+
1. Create a feature branch from `master`
|
|
27
|
+
2. Follow [Conventional Commits](https://www.conventionalcommits.org/) (`feat:`, `fix:`, `docs:`, etc.)
|
|
28
|
+
3. Run `make check` — all gates must pass
|
|
29
|
+
4. Open a PR against `master`
|
|
30
|
+
5. CI runs automatically (Python 3.12 + 3.13)
|
|
31
|
+
6. Squash merge after CI passes
|
|
32
|
+
|
|
33
|
+
## Code Standards
|
|
34
|
+
|
|
35
|
+
- Python 3.12+, type hints everywhere (`mypy --strict`)
|
|
36
|
+
- Formatting: Ruff
|
|
37
|
+
- Tests: pytest, TDD preferred (write test first)
|
|
38
|
+
- Functions < 40 lines, nesting < 4 levels
|
|
39
|
+
|
|
40
|
+
## Release Process
|
|
41
|
+
|
|
42
|
+
Automated via [release-please](https://github.com/googleapis/release-please). Merging to `master` with conventional commits triggers:
|
|
43
|
+
|
|
44
|
+
1. Release PR with changelog (auto-created)
|
|
45
|
+
2. Merge Release PR → GitHub Release + PyPI publish (trusted publishing)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Manuel Lorente
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
.PHONY: help install lint typecheck test check build clean run site site-dev site-preview
|
|
2
|
+
.DEFAULT_GOAL := help
|
|
3
|
+
|
|
4
|
+
help: ## Show this help
|
|
5
|
+
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-14s\033[0m %s\n", $$1, $$2}'
|
|
6
|
+
|
|
7
|
+
install: ## Create venv and install deps
|
|
8
|
+
uv venv && uv pip install -e ".[dev]"
|
|
9
|
+
|
|
10
|
+
lint: ## Run ruff linter
|
|
11
|
+
uv run ruff check src/ tests/
|
|
12
|
+
|
|
13
|
+
typecheck: ## Run mypy --strict
|
|
14
|
+
uv run mypy src/
|
|
15
|
+
|
|
16
|
+
test: ## Run tests with coverage
|
|
17
|
+
uv run pytest tests/ -v --cov=src --cov-report=term-missing
|
|
18
|
+
|
|
19
|
+
check: lint typecheck test ## Lint + typecheck + test
|
|
20
|
+
|
|
21
|
+
build: check ## Check + build package
|
|
22
|
+
uv build
|
|
23
|
+
|
|
24
|
+
clean: ## Remove build artifacts
|
|
25
|
+
rm -rf dist/ .venv/ *.egg-info/ .ruff_cache/ .mypy_cache/ .pytest_cache/ htmlcov/ .coverage coverage.xml site/dist/ site/node_modules/
|
|
26
|
+
|
|
27
|
+
run: ## Run channel analysis (requires .env)
|
|
28
|
+
uv run yt-metrics channels
|
|
29
|
+
|
|
30
|
+
site: ## Build documentation site (requires Node.js)
|
|
31
|
+
cd site && npm ci && npm run build
|
|
32
|
+
|
|
33
|
+
site-dev: ## Start documentation dev server
|
|
34
|
+
cd site && npm run dev
|
|
35
|
+
|
|
36
|
+
site-preview: ## Preview documentation production build
|
|
37
|
+
cd site && npm run preview
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: yt-metrics-cli
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: CLI for YouTube channel analysis and transcript downloading
|
|
5
|
+
Project-URL: Homepage, https://github.com/mlorentedev/yt-metrics-cli
|
|
6
|
+
Project-URL: Documentation, https://mlorentedev.github.io/yt-metrics-cli/
|
|
7
|
+
Project-URL: Repository, https://github.com/mlorentedev/yt-metrics-cli
|
|
8
|
+
Project-URL: Issues, https://github.com/mlorentedev/yt-metrics-cli/issues
|
|
9
|
+
Author-email: Manuel Lorente <info@mlorente.dev>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: analytics,cli,engagement-metrics,transcripts,youtube
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Multimedia :: Video
|
|
19
|
+
Requires-Python: >=3.12
|
|
20
|
+
Requires-Dist: google-api-python-client>=2.112.0
|
|
21
|
+
Requires-Dist: google-auth-oauthlib>=1.2.0
|
|
22
|
+
Requires-Dist: pydantic-settings>=2.0
|
|
23
|
+
Requires-Dist: pyyaml>=6.0
|
|
24
|
+
Requires-Dist: rich>=13.0
|
|
25
|
+
Requires-Dist: typer>=0.15.0
|
|
26
|
+
Requires-Dist: youtube-transcript-api>=1.2.2
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: mypy>=1.13; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: ruff>=0.8.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: types-pyyaml>=6.0; extra == 'dev'
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
|
|
35
|
+
# yt-metrics-cli
|
|
36
|
+
|
|
37
|
+
[](https://github.com/mlorentedev/yt-metrics-cli/actions/workflows/ci.yml)
|
|
38
|
+
[](https://www.python.org/downloads/)
|
|
39
|
+
[](LICENSE)
|
|
40
|
+
[](https://mlorentedev.github.io/yt-metrics-cli/)
|
|
41
|
+
|
|
42
|
+
CLI tool that analyzes YouTube channels and downloads video transcripts, generating engagement metrics and structured reports.
|
|
43
|
+
|
|
44
|
+
## Problem
|
|
45
|
+
|
|
46
|
+
YouTube Studio gives you analytics for **your own** channels. If you want to compare multiple channels, benchmark engagement rates, or bulk-download transcripts for research, you're stuck with manual work or fragmented browser extensions.
|
|
47
|
+
|
|
48
|
+
**yt-metrics-cli** solves this: point it at a list of channels, get CSV data, engagement reports, and transcript files in one command.
|
|
49
|
+
|
|
50
|
+
## Quick Start
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# Install
|
|
54
|
+
pip install yt-metrics-cli
|
|
55
|
+
# or
|
|
56
|
+
uv tool install yt-metrics-cli
|
|
57
|
+
|
|
58
|
+
# Set your API key
|
|
59
|
+
export YOUTUBE_API_KEY=your_key_here
|
|
60
|
+
# Get one at: https://console.cloud.google.com/apis/credentials
|
|
61
|
+
|
|
62
|
+
# Create channels.yml
|
|
63
|
+
cat > channels.yml << 'EOF'
|
|
64
|
+
- custom_url: "@mkbhd"
|
|
65
|
+
- custom_url: "@veritasium"
|
|
66
|
+
EOF
|
|
67
|
+
|
|
68
|
+
# Analyze
|
|
69
|
+
yt-metrics channels
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Features
|
|
73
|
+
|
|
74
|
+
| Feature | Description |
|
|
75
|
+
|---------|-------------|
|
|
76
|
+
| Multi-channel analysis | Analyze N channels in one run |
|
|
77
|
+
| Engagement metrics | View rate, like rate, comment rate, viral detection |
|
|
78
|
+
| CSV export | Raw data with all computed fields |
|
|
79
|
+
| Text reports | Channel stats, trends, top/latest video URLs |
|
|
80
|
+
| Transcript download | Multi-language with 3-level fallback chain |
|
|
81
|
+
| API resilience | Exponential backoff on rate limits (403/429) |
|
|
82
|
+
|
|
83
|
+
## Usage
|
|
84
|
+
|
|
85
|
+
### Analyze Channels
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
yt-metrics channels # Use defaults from .env
|
|
89
|
+
yt-metrics channels -c my_channels.yml # Custom channel list
|
|
90
|
+
yt-metrics channels -n 100 -o ./reports # 100 videos, custom output
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Generates timestamped reports in `output/<timestamp>/`:
|
|
94
|
+
|
|
95
|
+
- **CSV** — Raw data with all metrics per video
|
|
96
|
+
- **Channel Stats** — Per-channel analysis with top 5 videos
|
|
97
|
+
- **Engagement Trends** — Cross-channel comparisons and rankings
|
|
98
|
+
- **Best/Latest Videos** — URL lists for quick access
|
|
99
|
+
- **README** — Index explaining all generated files
|
|
100
|
+
|
|
101
|
+
### Download Transcripts
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
yt-metrics transcript -v dQw4w9WgXcQ # Specific video
|
|
105
|
+
yt-metrics transcript -v abc123 -l es,en # Language preference
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Engagement Metrics
|
|
109
|
+
|
|
110
|
+
| Metric | Formula | Interpretation |
|
|
111
|
+
|--------|---------|----------------|
|
|
112
|
+
| Engagement Rate | `(likes + comments) / views * 100` | Overall audience interaction |
|
|
113
|
+
| View Rate | `views / subscribers * 100` | Reach beyond subscriber base (>100% = viral) |
|
|
114
|
+
| Like Rate | `likes / views * 100` | Content satisfaction signal |
|
|
115
|
+
| Comment Rate | `comments / views * 100` | Discussion engagement level |
|
|
116
|
+
|
|
117
|
+
## Configuration
|
|
118
|
+
|
|
119
|
+
All settings can be set via environment variables or `.env` file:
|
|
120
|
+
|
|
121
|
+
| Variable | Default | Description |
|
|
122
|
+
|----------|---------|-------------|
|
|
123
|
+
| `YOUTUBE_API_KEY` | *(required)* | YouTube Data API v3 key |
|
|
124
|
+
| `MAX_RESULTS_PER_CHANNEL` | `50` | Videos to fetch per channel |
|
|
125
|
+
| `OUTPUT_DIR` | `./output` | Report output directory |
|
|
126
|
+
| `CHANNELS_FILE` | `channels.yml` | Channel list file path |
|
|
127
|
+
| `VIDEO_ID` | — | Default video for transcript mode |
|
|
128
|
+
| `TRANSCRIPT_LANGUAGES` | `es,en` | Preferred transcript languages |
|
|
129
|
+
|
|
130
|
+
## Development
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
git clone https://github.com/mlorentedev/yt-metrics-cli.git
|
|
134
|
+
cd yt-metrics-cli
|
|
135
|
+
make install # Create venv + install deps
|
|
136
|
+
make check # Lint + typecheck + test
|
|
137
|
+
make build # Full build
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for details.
|
|
141
|
+
|
|
142
|
+
## License
|
|
143
|
+
|
|
144
|
+
[MIT](LICENSE)
|