Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions .claude/commands/ai-news-digest-yt.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,15 @@ For each video with a successful transcript, YOU (Claude) will:
- **English summary**: 2-3 sentences covering the key points
- **繁體中文摘要**: 2-3 sentences in Traditional Chinese covering the same points

3. Save each summary as markdown to `digest-yt/{{date}}/VIDEO_ID.md` with this format. Convert `upload_date` from YYYYMMDD → YYYY-MM-DD for display. Only include the **Last Modified** line if `modified_date` is present and different from `upload_date`:
3. Save each summary as markdown to `digest-yt/{{date}}/VIDEO_ID.md` with this format. Convert `upload_date` from YYYYMMDD → YYYY-MM-DD for display. Use `uploader` from fetch output for the **Publisher** field (fall back to "AI Daily Brief" if null). Only include the **Last Modified** line if `modified_date` is present and different from `upload_date`:

```markdown
# Video Title

![Video Title](VIDEO_ID_thumb.jpg)

**Source**: [AI Daily Brief](https://youtube.com/watch?v=VIDEO_ID)
**Publisher**: Uploader Name
**Source**: [Watch on YouTube](https://youtube.com/watch?v=VIDEO_ID)
**Published**: 2026-03-12
**Last Modified**: 2026-03-13

Expand All @@ -92,36 +93,36 @@ For each video with a successful transcript, YOU (Claude) will:

4. Also create two combined digest files. **Each video section MUST include its thumbnail image** (use relative path). If the thumbnail file doesn't exist, omit the image line for that video.

**`digest-yt/{{date}}/summary_en.md`** — All English summaries combined. Include `*Published: YYYY-MM-DD*` (and `| Modified: YYYY-MM-DD` only when `modified_date` is present) below each video heading:
**`digest-yt/{{date}}/summary_en.md`** — All English summaries combined. Include publisher and date metadata below each video heading:
```markdown
# AI Daily Brief - YouTube Digest {{date}}

## Video Title 1
![Video Title 1](VIDEO_ID_thumb.jpg)
*Published: 2026-03-12 | Modified: 2026-03-13*
*Uploader Name — Published: 2026-03-12 | Modified: 2026-03-13*

2-3 sentence English summary...

## Video Title 2
![Video Title 2](VIDEO_ID_thumb.jpg)
*Published: 2026-03-12*
*Uploader Name — Published: 2026-03-12*

2-3 sentence English summary...
```

**`digest-yt/{{date}}/summary_zh-tw.md`** — All zh-TW summaries combined, same date format:
**`digest-yt/{{date}}/summary_zh-tw.md`** — All zh-TW summaries combined, same format:
```markdown
# AI Daily Brief - YouTube 摘要 {{date}}

## Video Title 1
![Video Title 1](VIDEO_ID_thumb.jpg)
*Published: 2026-03-12 | Modified: 2026-03-13*
*Uploader Name — Published: 2026-03-12 | Modified: 2026-03-13*

繁體中文摘要...

## Video Title 2
![Video Title 2](VIDEO_ID_thumb.jpg)
*Published: 2026-03-12*
*Uploader Name — Published: 2026-03-12*

繁體中文摘要...
```
Expand Down Expand Up @@ -174,6 +175,7 @@ Build a Slack mrkdwn message and post it. Use this exact format:

*:movie_camera: Video Title Here*
> :link: <https://youtube.com/watch?v=VIDEO_ID|Watch on YouTube>
> :studio_microphone: Uploader Name · :calendar: 2026-03-15
>
> :us: 2-3 sentence English summary...
>
Expand Down Expand Up @@ -224,6 +226,8 @@ Write `.state/last-digest-yt.json` with the full schema. Only add a video to `po
"video_status": {
"id1": {
"title": "Video Title Here",
"uploader": "AI Daily Brief",
"published_date": "2026-03-15",
"steps": {
"transcript": true,
"thumbnail": true,
Expand Down
8 changes: 5 additions & 3 deletions scripts/yt/fetch_recent_videos.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
python scripts/yt/fetch_recent_videos.py [--channel URL] [--hours 24] [--state PATH]

Outputs JSON array to stdout:
[{"id": "abc123", "title": "Video Title", "upload_date": "20260311", "modified_date": "20260312"}, ...]
[{"id": "abc123", "title": "Video Title", "upload_date": "20260311", "modified_date": "20260312", "uploader": "AI Daily Brief"}, ...]
"""

import argparse
Expand All @@ -29,7 +29,7 @@ def fetch_channel_videos(channel_url: str, max_items: int = 10) -> list[dict]:
"--playlist-items",
f"1:{max_items}",
"--print",
"%(id)s\t%(title)s\t%(upload_date)s\t%(modified_date)s\t%(thumbnail)s",
"%(id)s\t%(title)s\t%(upload_date)s\t%(modified_date)s\t%(thumbnail)s\t%(uploader)s",
"--skip-download",
f"{channel_url}/videos",
]
Expand All @@ -40,14 +40,15 @@ def fetch_channel_videos(channel_url: str, max_items: int = 10) -> list[dict]:

videos = []
for line in result.stdout.strip().splitlines():
parts = line.split("\t", 4)
parts = line.split("\t", 5)
if len(parts) >= 2:
vid_id = parts[0]
upload = parts[2] if len(parts) >= 3 else "NA"
modified = parts[3] if len(parts) >= 4 else "NA"
# Treat modified_date as null if same as upload_date or unavailable
if modified in ("NA", "", upload):
modified = None
uploader = parts[5] if len(parts) >= 6 and parts[5] != "NA" else None
vid = {
"id": vid_id,
"title": parts[1],
Expand All @@ -56,6 +57,7 @@ def fetch_channel_videos(channel_url: str, max_items: int = 10) -> list[dict]:
"thumbnail": parts[4]
if len(parts) >= 5 and parts[4] != "NA"
else f"https://i.ytimg.com/vi/{vid_id}/hqdefault.jpg",
"uploader": uploader,
}
videos.append(vid)
return videos
Expand Down
Loading