vink 0.1.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.
- vink-0.1.0/.env.example +24 -0
- vink-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +37 -0
- vink-0.1.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
- vink-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +28 -0
- vink-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +18 -0
- vink-0.1.0/.github/dependabot.yml +14 -0
- vink-0.1.0/.github/workflows/ci.yml +62 -0
- vink-0.1.0/.github/workflows/release.yml +50 -0
- vink-0.1.0/.gitignore +51 -0
- vink-0.1.0/.pre-commit-config.yaml +21 -0
- vink-0.1.0/.python-version +1 -0
- vink-0.1.0/CHANGELOG.md +29 -0
- vink-0.1.0/CODE_OF_CONDUCT.md +22 -0
- vink-0.1.0/CONTRIBUTING.md +111 -0
- vink-0.1.0/LICENSE +21 -0
- vink-0.1.0/PKG-INFO +236 -0
- vink-0.1.0/README.md +202 -0
- vink-0.1.0/SECURITY.md +30 -0
- vink-0.1.0/docs/adr/0001-ports-and-adapters.md +44 -0
- vink-0.1.0/docs/adr/0002-transcripts-without-data-api.md +58 -0
- vink-0.1.0/docs/adr/0003-separate-extraction-from-styling.md +47 -0
- vink-0.1.0/docs/architecture.md +112 -0
- vink-0.1.0/docs/configuration.md +54 -0
- vink-0.1.0/docs/mcp.md +90 -0
- vink-0.1.0/docs/releasing.md +69 -0
- vink-0.1.0/pyproject.toml +147 -0
- vink-0.1.0/src/vink/__init__.py +10 -0
- vink-0.1.0/src/vink/adapters/__init__.py +6 -0
- vink-0.1.0/src/vink/adapters/cache/__init__.py +6 -0
- vink-0.1.0/src/vink/adapters/cache/caching_source.py +74 -0
- vink-0.1.0/src/vink/adapters/cache/filesystem.py +50 -0
- vink-0.1.0/src/vink/adapters/cache/serialization.py +95 -0
- vink-0.1.0/src/vink/adapters/render/__init__.py +5 -0
- vink-0.1.0/src/vink/adapters/render/markdown.py +111 -0
- vink-0.1.0/src/vink/adapters/sinks/__init__.py +5 -0
- vink-0.1.0/src/vink/adapters/sinks/local.py +51 -0
- vink-0.1.0/src/vink/adapters/youtube/__init__.py +6 -0
- vink-0.1.0/src/vink/adapters/youtube/oembed.py +63 -0
- vink-0.1.0/src/vink/adapters/youtube/transcript_source.py +126 -0
- vink-0.1.0/src/vink/bootstrap.py +85 -0
- vink-0.1.0/src/vink/config.py +71 -0
- vink-0.1.0/src/vink/domain/__init__.py +56 -0
- vink-0.1.0/src/vink/domain/errors.py +86 -0
- vink-0.1.0/src/vink/domain/models.py +188 -0
- vink-0.1.0/src/vink/domain/video_ref.py +81 -0
- vink-0.1.0/src/vink/interfaces/__init__.py +6 -0
- vink-0.1.0/src/vink/interfaces/cli/__init__.py +5 -0
- vink-0.1.0/src/vink/interfaces/cli/app.py +187 -0
- vink-0.1.0/src/vink/interfaces/logging_setup.py +16 -0
- vink-0.1.0/src/vink/interfaces/mcp/__init__.py +5 -0
- vink-0.1.0/src/vink/interfaces/mcp/schemas.py +27 -0
- vink-0.1.0/src/vink/interfaces/mcp/server.py +180 -0
- vink-0.1.0/src/vink/ports/__init__.py +14 -0
- vink-0.1.0/src/vink/ports/cache.py +19 -0
- vink-0.1.0/src/vink/ports/metadata_source.py +19 -0
- vink-0.1.0/src/vink/ports/renderer.py +27 -0
- vink-0.1.0/src/vink/ports/sink.py +22 -0
- vink-0.1.0/src/vink/ports/transcript_source.py +22 -0
- vink-0.1.0/src/vink/processing/__init__.py +23 -0
- vink-0.1.0/src/vink/processing/chunking.py +49 -0
- vink-0.1.0/src/vink/processing/cleaning.py +47 -0
- vink-0.1.0/src/vink/processing/filenames.py +40 -0
- vink-0.1.0/src/vink/processing/paragraphs.py +105 -0
- vink-0.1.0/src/vink/processing/timecode.py +20 -0
- vink-0.1.0/src/vink/processing/track_selection.py +114 -0
- vink-0.1.0/src/vink/py.typed +0 -0
- vink-0.1.0/src/vink/services/__init__.py +10 -0
- vink-0.1.0/src/vink/services/export_service.py +69 -0
- vink-0.1.0/src/vink/services/transcript_service.py +102 -0
- vink-0.1.0/src/vink/styles/__init__.py +46 -0
- vink-0.1.0/src/vink/styles/clean-transcript.md +28 -0
- vink-0.1.0/src/vink/styles/detailed-notes.md +38 -0
- vink-0.1.0/tests/__init__.py +0 -0
- vink-0.1.0/tests/conftest.py +68 -0
- vink-0.1.0/tests/fakes.py +77 -0
- vink-0.1.0/tests/fixtures/expected/chunk.md +5 -0
- vink-0.1.0/tests/fixtures/expected/transcript.md +19 -0
- vink-0.1.0/tests/integration/__init__.py +0 -0
- vink-0.1.0/tests/integration/test_youtube_live.py +38 -0
- vink-0.1.0/tests/unit/__init__.py +0 -0
- vink-0.1.0/tests/unit/adapters/__init__.py +0 -0
- vink-0.1.0/tests/unit/adapters/test_cache.py +118 -0
- vink-0.1.0/tests/unit/adapters/test_local_sink.py +39 -0
- vink-0.1.0/tests/unit/adapters/test_markdown_renderer.py +66 -0
- vink-0.1.0/tests/unit/adapters/test_oembed.py +62 -0
- vink-0.1.0/tests/unit/adapters/test_youtube_transcript_source.py +160 -0
- vink-0.1.0/tests/unit/domain/__init__.py +0 -0
- vink-0.1.0/tests/unit/domain/test_models.py +59 -0
- vink-0.1.0/tests/unit/domain/test_video_ref.py +58 -0
- vink-0.1.0/tests/unit/interfaces/__init__.py +0 -0
- vink-0.1.0/tests/unit/interfaces/conftest.py +27 -0
- vink-0.1.0/tests/unit/interfaces/test_cli.py +117 -0
- vink-0.1.0/tests/unit/interfaces/test_mcp_server.py +133 -0
- vink-0.1.0/tests/unit/processing/__init__.py +0 -0
- vink-0.1.0/tests/unit/processing/test_chunking.py +54 -0
- vink-0.1.0/tests/unit/processing/test_cleaning.py +31 -0
- vink-0.1.0/tests/unit/processing/test_paragraphs.py +79 -0
- vink-0.1.0/tests/unit/processing/test_text_helpers.py +36 -0
- vink-0.1.0/tests/unit/processing/test_track_selection.py +87 -0
- vink-0.1.0/tests/unit/services/__init__.py +0 -0
- vink-0.1.0/tests/unit/services/test_export_service.py +55 -0
- vink-0.1.0/tests/unit/services/test_transcript_service.py +78 -0
- vink-0.1.0/tests/unit/test_config.py +49 -0
- vink-0.1.0/tests/unit/test_styles.py +20 -0
- vink-0.1.0/uv.lock +1775 -0
vink-0.1.0/.env.example
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Copy to .env and adjust. Every setting is optional.
|
|
2
|
+
# See docs/configuration.md for details.
|
|
3
|
+
|
|
4
|
+
# Preferred transcript languages, in order (comma-separated language codes).
|
|
5
|
+
VINK_LANGUAGES=en
|
|
6
|
+
|
|
7
|
+
# Fall back to YouTube's machine translation when no track matches.
|
|
8
|
+
VINK_ALLOW_TRANSLATION=true
|
|
9
|
+
|
|
10
|
+
# Where generated Markdown files are written.
|
|
11
|
+
VINK_OUTPUT_DIR=output
|
|
12
|
+
|
|
13
|
+
# Local transcript cache. Leave unset to use the platform's user cache directory.
|
|
14
|
+
# VINK_CACHE_DIR=
|
|
15
|
+
VINK_USE_CACHE=true
|
|
16
|
+
|
|
17
|
+
# Target length of one chunk, in seconds (used by the MCP get_chunk tool).
|
|
18
|
+
VINK_CHUNK_SECONDS=600
|
|
19
|
+
|
|
20
|
+
# Network timeout for metadata requests, in seconds.
|
|
21
|
+
VINK_HTTP_TIMEOUT=10
|
|
22
|
+
|
|
23
|
+
# DEBUG, INFO, WARNING, or ERROR.
|
|
24
|
+
VINK_LOG_LEVEL=WARNING
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Something does not work as expected
|
|
3
|
+
labels: [bug]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: what-happened
|
|
7
|
+
attributes:
|
|
8
|
+
label: What happened?
|
|
9
|
+
description: What did you expect, and what happened instead?
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: reproduce
|
|
14
|
+
attributes:
|
|
15
|
+
label: Steps to reproduce
|
|
16
|
+
description: The exact command or MCP tool call, and the video URL if it is public.
|
|
17
|
+
placeholder: uv run vink transcript https://youtu.be/... --lang hi
|
|
18
|
+
validations:
|
|
19
|
+
required: true
|
|
20
|
+
- type: textarea
|
|
21
|
+
id: output
|
|
22
|
+
attributes:
|
|
23
|
+
label: Error output
|
|
24
|
+
description: Run with `-v` and paste the full output.
|
|
25
|
+
render: text
|
|
26
|
+
- type: input
|
|
27
|
+
id: version
|
|
28
|
+
attributes:
|
|
29
|
+
label: vink version
|
|
30
|
+
placeholder: output of `vink --version`
|
|
31
|
+
validations:
|
|
32
|
+
required: true
|
|
33
|
+
- type: input
|
|
34
|
+
id: environment
|
|
35
|
+
attributes:
|
|
36
|
+
label: OS and Python version
|
|
37
|
+
placeholder: macOS 15, Python 3.12
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
blank_issues_enabled: false
|
|
2
|
+
contact_links:
|
|
3
|
+
- name: Security vulnerability
|
|
4
|
+
url: https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability
|
|
5
|
+
about: Please report security issues privately, not as public issues.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Suggest a new capability, format, destination or note style
|
|
3
|
+
labels: [enhancement]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: problem
|
|
7
|
+
attributes:
|
|
8
|
+
label: Problem
|
|
9
|
+
description: What are you trying to do that vink does not support today?
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: proposal
|
|
14
|
+
attributes:
|
|
15
|
+
label: Proposed solution
|
|
16
|
+
description: How would you like it to work? Example commands or output help.
|
|
17
|
+
- type: dropdown
|
|
18
|
+
id: area
|
|
19
|
+
attributes:
|
|
20
|
+
label: Area
|
|
21
|
+
options:
|
|
22
|
+
- Transcript source / languages
|
|
23
|
+
- Output format
|
|
24
|
+
- Destination (Notion, Obsidian, ...)
|
|
25
|
+
- Note style / prompts
|
|
26
|
+
- CLI
|
|
27
|
+
- MCP server
|
|
28
|
+
- Other
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
## What
|
|
2
|
+
|
|
3
|
+
<!-- What does this change do? -->
|
|
4
|
+
|
|
5
|
+
## Why
|
|
6
|
+
|
|
7
|
+
<!-- What problem does it solve? Link the issue: Closes #123 -->
|
|
8
|
+
|
|
9
|
+
## How to test
|
|
10
|
+
|
|
11
|
+
<!-- Commands or steps a reviewer can run. -->
|
|
12
|
+
|
|
13
|
+
## Checklist
|
|
14
|
+
|
|
15
|
+
- [ ] `ruff format`, `ruff check`, `mypy` and `pytest` pass locally
|
|
16
|
+
- [ ] Tests added or updated for new behavior
|
|
17
|
+
- [ ] `CHANGELOG.md` updated under `[Unreleased]` (if user-visible)
|
|
18
|
+
- [ ] Docs updated (README / `docs/`) for new options or behavior
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
# youtube-transcript-api tracks YouTube internals; stay current.
|
|
4
|
+
- package-ecosystem: uv
|
|
5
|
+
directory: /
|
|
6
|
+
schedule:
|
|
7
|
+
interval: weekly
|
|
8
|
+
groups:
|
|
9
|
+
dev-tools:
|
|
10
|
+
dependency-type: development
|
|
11
|
+
- package-ecosystem: github-actions
|
|
12
|
+
directory: /
|
|
13
|
+
schedule:
|
|
14
|
+
interval: monthly
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
schedule:
|
|
8
|
+
# Weekly run of the live YouTube tests to catch upstream breakage early.
|
|
9
|
+
- cron: "0 6 * * 1"
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
concurrency:
|
|
16
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
17
|
+
cancel-in-progress: true
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
checks:
|
|
21
|
+
name: Lint and type check
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
25
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
26
|
+
- run: uv sync --locked
|
|
27
|
+
- run: uv run ruff format --check .
|
|
28
|
+
- run: uv run ruff check .
|
|
29
|
+
- run: uv run mypy
|
|
30
|
+
|
|
31
|
+
test:
|
|
32
|
+
name: Test (Python ${{ matrix.python-version }}, ${{ matrix.os }})
|
|
33
|
+
runs-on: ${{ matrix.os }}
|
|
34
|
+
strategy:
|
|
35
|
+
fail-fast: false
|
|
36
|
+
matrix:
|
|
37
|
+
os: [ubuntu-latest]
|
|
38
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
39
|
+
include:
|
|
40
|
+
- os: macos-latest
|
|
41
|
+
python-version: "3.12"
|
|
42
|
+
- os: windows-latest
|
|
43
|
+
python-version: "3.12"
|
|
44
|
+
steps:
|
|
45
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
46
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
47
|
+
with:
|
|
48
|
+
python-version: ${{ matrix.python-version }}
|
|
49
|
+
- run: uv sync --locked
|
|
50
|
+
- run: uv run pytest --cov --cov-report=term-missing
|
|
51
|
+
|
|
52
|
+
integration:
|
|
53
|
+
name: Live YouTube tests
|
|
54
|
+
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
|
|
55
|
+
runs-on: ubuntu-latest
|
|
56
|
+
# Cloud runner IPs are sometimes blocked by YouTube; don't fail the workflow for that.
|
|
57
|
+
continue-on-error: true
|
|
58
|
+
steps:
|
|
59
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
60
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
61
|
+
- run: uv sync --locked
|
|
62
|
+
- run: uv run pytest -m integration
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Publishes to PyPI when a version tag (e.g. v0.1.0) is pushed.
|
|
4
|
+
# Uses PyPI trusted publishing (OIDC): no API token is stored in GitHub.
|
|
5
|
+
# One-time setup is described in docs/releasing.md.
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
tags: ["v*"]
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
build:
|
|
16
|
+
name: Build distributions
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
20
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
21
|
+
- name: Check tag matches package version
|
|
22
|
+
run: |
|
|
23
|
+
version=$(uv version --short)
|
|
24
|
+
if [ "v${version}" != "${GITHUB_REF_NAME}" ]; then
|
|
25
|
+
echo "Tag ${GITHUB_REF_NAME} does not match pyproject version ${version}" >&2
|
|
26
|
+
exit 1
|
|
27
|
+
fi
|
|
28
|
+
- run: uv sync --locked
|
|
29
|
+
- run: uv run pytest
|
|
30
|
+
- run: uv build
|
|
31
|
+
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
32
|
+
with:
|
|
33
|
+
name: dist
|
|
34
|
+
path: dist/
|
|
35
|
+
|
|
36
|
+
publish:
|
|
37
|
+
name: Publish to PyPI
|
|
38
|
+
needs: build
|
|
39
|
+
runs-on: ubuntu-latest
|
|
40
|
+
environment:
|
|
41
|
+
name: pypi
|
|
42
|
+
url: https://pypi.org/project/vink/
|
|
43
|
+
permissions:
|
|
44
|
+
id-token: write # required for trusted publishing
|
|
45
|
+
steps:
|
|
46
|
+
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
|
47
|
+
with:
|
|
48
|
+
name: dist
|
|
49
|
+
path: dist/
|
|
50
|
+
- uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3
|
vink-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# ---------------------------------------------------------------------------
|
|
2
|
+
# Internal
|
|
3
|
+
# ---------------------------------------------------------------------------
|
|
4
|
+
# Team engineering standards
|
|
5
|
+
standards/
|
|
6
|
+
|
|
7
|
+
# ---------------------------------------------------------------------------
|
|
8
|
+
# Python
|
|
9
|
+
# ---------------------------------------------------------------------------
|
|
10
|
+
__pycache__/
|
|
11
|
+
*.py[cod]
|
|
12
|
+
*.so
|
|
13
|
+
*.egg-info/
|
|
14
|
+
.eggs/
|
|
15
|
+
build/
|
|
16
|
+
dist/
|
|
17
|
+
wheels/
|
|
18
|
+
|
|
19
|
+
# Virtual environments
|
|
20
|
+
.venv/
|
|
21
|
+
venv/
|
|
22
|
+
env/
|
|
23
|
+
|
|
24
|
+
# Tooling caches
|
|
25
|
+
.mypy_cache/
|
|
26
|
+
.ruff_cache/
|
|
27
|
+
.pytest_cache/
|
|
28
|
+
.coverage
|
|
29
|
+
.coverage.*
|
|
30
|
+
htmlcov/
|
|
31
|
+
coverage.xml
|
|
32
|
+
|
|
33
|
+
# ---------------------------------------------------------------------------
|
|
34
|
+
# Project runtime data
|
|
35
|
+
# ---------------------------------------------------------------------------
|
|
36
|
+
# Local transcript cache and generated output
|
|
37
|
+
.vink-cache/
|
|
38
|
+
output/
|
|
39
|
+
|
|
40
|
+
# Secrets and local config
|
|
41
|
+
.env
|
|
42
|
+
.env.*
|
|
43
|
+
!.env.example
|
|
44
|
+
|
|
45
|
+
# ---------------------------------------------------------------------------
|
|
46
|
+
# Editors / OS
|
|
47
|
+
# ---------------------------------------------------------------------------
|
|
48
|
+
.vscode/
|
|
49
|
+
.idea/
|
|
50
|
+
*.swp
|
|
51
|
+
.DS_Store
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Runs the same checks as CI before each commit.
|
|
2
|
+
# Install once with: uv run pre-commit install
|
|
3
|
+
repos:
|
|
4
|
+
- repo: local
|
|
5
|
+
hooks:
|
|
6
|
+
- id: ruff-format
|
|
7
|
+
name: ruff format
|
|
8
|
+
entry: uv run ruff format
|
|
9
|
+
language: system
|
|
10
|
+
types: [python]
|
|
11
|
+
- id: ruff-check
|
|
12
|
+
name: ruff check
|
|
13
|
+
entry: uv run ruff check --fix
|
|
14
|
+
language: system
|
|
15
|
+
types: [python]
|
|
16
|
+
- id: mypy
|
|
17
|
+
name: mypy
|
|
18
|
+
entry: uv run mypy
|
|
19
|
+
language: system
|
|
20
|
+
types: [python]
|
|
21
|
+
pass_filenames: false
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
vink-0.1.0/CHANGELOG.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.0] - 2026-11-14
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `vink transcript` command: fetch a YouTube transcript and save it as Markdown
|
|
15
|
+
with YAML front matter and clickable timestamps, or print it with `--stdout`.
|
|
16
|
+
- `vink languages` command: list the caption tracks available for a video.
|
|
17
|
+
- Language preferences with fallback (`--lang hi,en`), the special value
|
|
18
|
+
`original` for the spoken language, and optional YouTube machine translation.
|
|
19
|
+
- Cleaning of caption text into readable paragraphs: sound cues removed,
|
|
20
|
+
fragments merged, speaker changes and pauses respected.
|
|
21
|
+
- Local transcript cache.
|
|
22
|
+
- MCP server (`vink mcp`) with tools `list_languages`, `get_video_info`,
|
|
23
|
+
`get_chunk`, `get_transcript`, `save_transcript` and `save_notes`, and a
|
|
24
|
+
`make_notes` prompt with `detailed-notes` and `clean-transcript` styles.
|
|
25
|
+
- Configuration through `VINK_*` environment variables or a `.env` file.
|
|
26
|
+
- Distribution on PyPI (`uv tool install vink`, `uvx vink mcp`).
|
|
27
|
+
|
|
28
|
+
[Unreleased]: https://github.com/navinbhagat322/youtube-vink/compare/v0.1.0...HEAD
|
|
29
|
+
[0.1.0]: https://github.com/navinbhagat322/youtube-vink/releases/tag/v0.1.0
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
This project adopts the
|
|
4
|
+
[Contributor Covenant, version 2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct/)
|
|
5
|
+
as its code of conduct.
|
|
6
|
+
|
|
7
|
+
In short: be respectful, assume good intent, welcome newcomers, and keep
|
|
8
|
+
discussion focused on the work. Harassment, personal attacks and
|
|
9
|
+
discriminatory language are not tolerated in any project space: issues, pull
|
|
10
|
+
requests, discussions or chat.
|
|
11
|
+
|
|
12
|
+
## Reporting
|
|
13
|
+
|
|
14
|
+
If you experience or witness unacceptable behavior, contact the maintainers
|
|
15
|
+
privately through the contact listed on the repository's GitHub profile, or by
|
|
16
|
+
opening a private security advisory if no other channel is available. All
|
|
17
|
+
reports are reviewed promptly and handled confidentially.
|
|
18
|
+
|
|
19
|
+
Maintainers may remove, edit or reject contributions that violate this code of
|
|
20
|
+
conduct, and may temporarily or permanently ban contributors for repeated or
|
|
21
|
+
serious violations, following the enforcement guidelines of the Contributor
|
|
22
|
+
Covenant.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Contributing to vink
|
|
2
|
+
|
|
3
|
+
Thanks for helping. This guide covers setup, the development workflow, and
|
|
4
|
+
the conventions every change follows.
|
|
5
|
+
|
|
6
|
+
## Development setup
|
|
7
|
+
|
|
8
|
+
You need Python 3.11+ and [uv](https://docs.astral.sh/uv/).
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
git clone https://github.com/navinbhagat322/youtube-vink.git
|
|
12
|
+
cd youtube-vink
|
|
13
|
+
uv sync # creates .venv with runtime + dev dependencies
|
|
14
|
+
uv run pre-commit install # runs format, lint and type checks before each commit
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Running checks
|
|
18
|
+
|
|
19
|
+
Run the same checks CI runs:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
uv run ruff format --check .
|
|
23
|
+
uv run ruff check .
|
|
24
|
+
uv run mypy
|
|
25
|
+
uv run pytest --cov
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Tests that call real YouTube are excluded by default. Run them with:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
uv run pytest -m integration
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Project layout
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
src/vink/
|
|
38
|
+
├── domain/ # immutable models and errors (no I/O, no third-party imports)
|
|
39
|
+
├── ports/ # Protocol interfaces the core depends on
|
|
40
|
+
├── processing/ # pure functions: track selection, cleaning, paragraphs, chunks
|
|
41
|
+
├── services/ # use cases that orchestrate ports and processing
|
|
42
|
+
├── adapters/ # implementations: YouTube, cache, Markdown, local files
|
|
43
|
+
├── interfaces/ # entry points: CLI and MCP server
|
|
44
|
+
├── styles/ # note-style prompt templates (Markdown files)
|
|
45
|
+
├── bootstrap.py # wires adapters into services
|
|
46
|
+
└── config.py # typed settings
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Read [docs/architecture.md](docs/architecture.md) before making structural
|
|
50
|
+
changes. The key rule is that dependencies point inward: services depend on
|
|
51
|
+
ports, never on adapters.
|
|
52
|
+
|
|
53
|
+
## Common changes
|
|
54
|
+
|
|
55
|
+
**Add an output format** (e.g. PDF): implement the `Renderer` protocol in
|
|
56
|
+
`src/vink/adapters/render/`, register it in `bootstrap.py`, and add a golden
|
|
57
|
+
file test in `tests/unit/adapters/`.
|
|
58
|
+
|
|
59
|
+
**Add a destination** (e.g. Notion): implement the `Sink` protocol in
|
|
60
|
+
`src/vink/adapters/sinks/` and wire it in `bootstrap.py`. Put heavy
|
|
61
|
+
dependencies in an optional extra (`vink[notion]`) and import them inside the
|
|
62
|
+
adapter.
|
|
63
|
+
|
|
64
|
+
**Add a note style**: add a Markdown file to `src/vink/styles/`. It is
|
|
65
|
+
discovered automatically. Use `{output_language}` where the target language
|
|
66
|
+
belongs.
|
|
67
|
+
|
|
68
|
+
## Conventions
|
|
69
|
+
|
|
70
|
+
- **Style:** PEP 8 via `ruff format`, line length 100, Google-style docstrings
|
|
71
|
+
on all public code, full type hints (`mypy --strict`).
|
|
72
|
+
- **Errors:** raise errors from `vink.domain.errors`. Adapters convert library
|
|
73
|
+
exceptions with `raise ... from exc`. Messages should tell the user what to
|
|
74
|
+
do next.
|
|
75
|
+
- **Logging:** `logging.getLogger(__name__)`, never `print()`. Nothing may
|
|
76
|
+
write to stdout from the MCP server.
|
|
77
|
+
- **Tests:** unit tests never touch the network. Use the fakes in
|
|
78
|
+
`tests/fakes.py`. Every bug fix starts with a failing test.
|
|
79
|
+
|
|
80
|
+
## Commits and pull requests
|
|
81
|
+
|
|
82
|
+
We use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/):
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
feat(youtube): fall back to auto-generated captions
|
|
86
|
+
fix(processing): keep Devanagari punctuation when merging segments
|
|
87
|
+
docs: explain MCP setup on Windows
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Scopes follow the architecture: `domain`, `processing`, `services`, `youtube`,
|
|
91
|
+
`cache`, `render`, `sinks`, `cli`, `mcp`, `config`, `deps`.
|
|
92
|
+
|
|
93
|
+
Before opening a pull request:
|
|
94
|
+
|
|
95
|
+
- [ ] All checks above pass.
|
|
96
|
+
- [ ] New behavior has tests.
|
|
97
|
+
- [ ] User-visible changes are noted under `[Unreleased]` in `CHANGELOG.md`.
|
|
98
|
+
- [ ] Docs are updated for new options or behavior.
|
|
99
|
+
|
|
100
|
+
Keep pull requests small and focused. They are squash-merged, so the PR title
|
|
101
|
+
becomes the commit message.
|
|
102
|
+
|
|
103
|
+
## Reporting bugs
|
|
104
|
+
|
|
105
|
+
Open an issue with the video URL (if public), the command you ran, the full
|
|
106
|
+
error output, and `vink --version`. For security issues, see
|
|
107
|
+
[SECURITY.md](SECURITY.md).
|
|
108
|
+
|
|
109
|
+
## Code of conduct
|
|
110
|
+
|
|
111
|
+
This project follows the [Code of Conduct](CODE_OF_CONDUCT.md).
|
vink-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 vink contributors
|
|
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.
|