mirror of
https://github.com/jackwener/OpenCLI.git
synced 2026-09-14 18:25:42 +08:00
67ed9e9c81
* feat(linkedin-learning): add search / trending / course read commands (#1021) Closes #1021. Adds a new linkedin-learning site adapter with three read-only commands against LinkedIn Learning's public learning-api REST surface. Shares cookie session with linkedin.com; Learning queries are not subject to the people-search CUL. Commands: - linkedin-learning search <keywords> searchV2?q=keywords - linkedin-learning trending feedRecommendationGroups?q=learner - linkedin-learning course <slug> courses?q=slug Endpoints were discovered via browser network capture on /learning/search and /learning/<slug> pages: searchV2 returns a flat list of courses/videos/paths keyed by entityType, headline.title.text holds the canonical title, length is a TimeSpan in seconds, and rating is averaged from ratingSum/ratingCount when averageRating is missing. trending walks the carousels array on each recommendation group, flattens cards across them, dedups by slug, and respects --limit. Group is labeled with the carousel title (e.g. "Top picks for you") or the upstream annotation tag (TOP_PICKS). course accepts either a bare slug or a full /learning/<slug> URL, then hits /learning-api/courses?q=slug. The detail endpoint omits rating fields even when search reports them; this is documented in the adapter doc rather than fixed via a second /reviews fetch to keep the PR scoped to one endpoint per command. CUL caveat: Learning's API has no per-month limit, so dev iterations can be much more aggressive than the people-search adapter (#1649). Three commands were live-verified against a logged-in account with 60s sleeps between calls (conservative for first-pass safety). Tests: 28 unit tests across search.test.js (12), trending.test.js (6), course.test.js (10) cover URL construction, limit validation, author join, duration / rating coercion, row mapping, carousel flattening and dedup, slug parsing from URL forms, and the standard auth / empty / fetch-failure error paths. Live verified: - search "AI agent" --limit 3: 3 rows with title/instructor/rating - trending --limit 3: 3 personalized course picks - course agentic-ai-build-your-first-agentic-ai-system: title, 3932s duration, 18 videos, release date 2026-03-27 * fix(linkedin-learning): harden read result boundaries * fix(linkedin-learning): require course title evidence --------- Co-authored-by: jackwener <jakevingoo@gmail.com>
4.0 KiB
4.0 KiB
LinkedIn Learning
Mode: 🔐 Browser + Cookie · Domain: linkedin.com
Read-only adapter for LinkedIn Learning courses, videos, and learning paths. Shares cookie session with linkedin.com, no Commercial Use Limit (Learning queries are separate from people-search CUL).
Commands
| Command | Description |
|---|---|
opencli linkedin-learning search |
Search courses, videos, and paths by keyword via learning-api/searchV2 |
opencli linkedin-learning trending |
Browse personalized recommendation carousels via learning-api/feedRecommendationGroups |
opencli linkedin-learning course |
Course detail by slug or full /learning/<slug> URL via learning-api/courses?q=slug |
Usage Examples
# Search
opencli linkedin-learning search "AI agent"
opencli linkedin-learning search "rust programming" --limit 20
# Personalized recommendations
opencli linkedin-learning trending --limit 10
# Course detail (slug or full URL)
opencli linkedin-learning course agentic-ai-build-your-first-agentic-ai-system
opencli linkedin-learning course https://www.linkedin.com/learning/agentic-ai-build-your-first-agentic-ai-system
# JSON output
opencli linkedin-learning search "data science" -f json
Columns
search
| Column | Notes |
|---|---|
rank |
1-based position in upstream order |
type |
COURSE / VIDEO / LEARNING_PATH / etc |
title |
From headline.title.text |
instructor |
Joined firstName lastName of all authors |
difficulty |
BEGINNER / INTERMEDIATE / etc (uppercase from searchV2) |
duration_sec |
Length in seconds (empty if non-SECOND unit) |
rating |
Average rating to 2 decimals, computed from ratingSum/ratingCount if no averageRating |
rating_count |
Number of ratings |
viewers |
Cumulative viewer count |
url |
https://www.linkedin.com/learning/<slug> |
trending
| Column | Notes |
|---|---|
rank |
1-based across all carousels in document order |
group |
Carousel title (e.g. "Top picks for you") or annotation (TOP_PICKS) |
type |
Same as search |
title |
Course / video title |
difficulty |
Same as search |
viewers |
Cumulative viewer count |
url |
Course URL |
Cards are deduplicated by slug across carousels (first-seen wins).
course
| Column | Notes |
|---|---|
title |
Course title |
slug |
Stable slug used in URL |
description |
Full course description returned by /learning-api/courses?q=slug |
difficulty |
Beginner / Intermediate / etc (mixed case from detail endpoint) |
duration_sec |
Total length in seconds |
videos_count |
Number of videos in the course |
rating |
Average rating to 2 decimals (empty when /courses?q=slug omits ratings; see Caveats) |
rating_count |
Number of ratings (empty when omitted) |
released |
Activation date (YYYY-MM-DD) |
url |
https://www.linkedin.com/learning/<slug> |
Prerequisites
- Chrome running with Browser Bridge extension installed
- Logged in to linkedin.com; Learning shares the cookie session
Caveats
- The course-detail endpoint (
/learning-api/courses?q=slug) does not always includerating/rating_counteven when thesearchendpoint reports them for the same slug. Usesearch "<slug words>"to get ratings if needed; a future revision may make a second call to/learning-api/reviews?contentUrn=...&q=findByContentto fill these in. trendingreturns personalized recommendations (carouselannotation: TOP_PICKSand similar), not a globally-ranked popularity list. The output reflects the logged-in user's recent activity and skills.- Voyager search-cluster endpoints (used by the standard
linkedin/searchjobs adapter andlinkedin/people-search) do not serve Learning data;learning-api/*is the dedicated REST surface.
Limit Validation
searchandtrendingcap--limitat 50 with strict-integer validation (no silent clamp).coursereturns exactly one row by definition.