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
51 changes: 51 additions & 0 deletions docs/adapters/browser/facebook.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Facebook

**Mode**: 🔐 Browser · **Domain**: `facebook.com`

## Commands

| Command | Description |
|---------|-------------|
| `opencli facebook profile` | Get user/page profile info |
| `opencli facebook notifications` | Get recent notifications |
| `opencli facebook feed` | Get news feed posts |
| `opencli facebook search` | Search people, pages, posts |
| `opencli facebook friends` | Friend suggestions |
| `opencli facebook groups` | List your joined groups |
| `opencli facebook memories` | On This Day memories |
| `opencli facebook events` | Browse event categories |
| `opencli facebook add-friend` | Send a friend request |
| `opencli facebook join-group` | Join a group |

## Usage Examples

```bash
# View a profile
opencli facebook profile --username zuck

# Get notifications
opencli facebook notifications --limit 10

# News feed
opencli facebook feed --limit 5

# Search
opencli facebook search --query "OpenAI" --limit 5

# List your groups
opencli facebook groups

# Send friend request
opencli facebook add-friend --username someone

# Join a group
opencli facebook join-group --group 123456789

# JSON output
opencli facebook profile --username zuck -f json
```

## Prerequisites

- Chrome running and **logged into** facebook.com
- [Browser Bridge extension](/guide/browser-bridge) installed
53 changes: 53 additions & 0 deletions docs/adapters/browser/instagram.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Instagram

**Mode**: 🔐 Browser · **Domain**: `instagram.com`

## Commands

| Command | Description |
|---------|-------------|
| `opencli instagram profile` | Get user profile info |
| `opencli instagram search` | Search users |
| `opencli instagram user` | Get recent posts from a user |
| `opencli instagram explore` | Discover trending posts |
| `opencli instagram followers` | List user's followers |
| `opencli instagram following` | List user's following |
| `opencli instagram saved` | Get your saved posts |
| `opencli instagram like` | Like a post |
| `opencli instagram unlike` | Unlike a post |
| `opencli instagram comment` | Comment on a post |
| `opencli instagram save` | Bookmark a post |
| `opencli instagram unsave` | Remove bookmark |
| `opencli instagram follow` | Follow a user |
| `opencli instagram unfollow` | Unfollow a user |

## Usage Examples

```bash
# View a user's profile
opencli instagram profile --username nasa

# Search users
opencli instagram search --query nasa --limit 5

# View a user's recent posts
opencli instagram user --username nasa --limit 10

# Like a user's most recent post
opencli instagram like --username nasa --index 1

# Comment on a post
opencli instagram comment --username nasa --text "Amazing!" --index 1

# Follow/unfollow
opencli instagram follow --username nasa
opencli instagram unfollow --username nasa

# JSON output
opencli instagram profile --username nasa -f json
```

## Prerequisites

- Chrome running and **logged into** instagram.com
- [Browser Bridge extension](/guide/browser-bridge) installed
32 changes: 32 additions & 0 deletions docs/adapters/browser/lobsters.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Lobsters

**Mode**: 🌐 Public · **Domain**: `lobste.rs`

## Commands

| Command | Description |
|---------|-------------|
| `opencli lobsters hot` | Hottest stories |
| `opencli lobsters newest` | Latest stories |
| `opencli lobsters active` | Most active discussions |
| `opencli lobsters tag` | Stories by tag |

## Usage Examples

```bash
# Quick start
opencli lobsters hot --limit 10

# Filter by tag
opencli lobsters tag --tag rust --limit 5

# JSON output
opencli lobsters hot -f json

# Verbose mode
opencli lobsters hot -v
```

## Prerequisites

None — all commands use the public JSON API, no browser or login required.
31 changes: 31 additions & 0 deletions docs/adapters/browser/medium.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Medium

**Mode**: 🌐 Public · **Domain**: `medium.com`

## Commands

| Command | Description |
|---------|-------------|
| `opencli medium publication` | Get recent articles from a publication |
| `opencli medium tag` | Get top articles for a tag |
| `opencli medium user` | Get recent articles by a user |

## Usage Examples

```bash
# Get articles from a publication
opencli medium publication --name towards-data-science

# Get top articles for a tag
opencli medium tag --name programming

# Get articles by a user
opencli medium user --name @username

# JSON output
opencli medium tag --name ai -f json
```

## Prerequisites

None — all commands use public endpoints, no browser or login required.
68 changes: 68 additions & 0 deletions docs/adapters/browser/tiktok.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# TikTok

**Mode**: 🔐 Browser · **Domain**: `tiktok.com`

## Commands

| Command | Description |
|---------|-------------|
| `opencli tiktok profile` | Get user profile info |
| `opencli tiktok search` | Search videos |
| `opencli tiktok explore` | Trending videos from explore page |
| `opencli tiktok user` | Get recent videos from a user |
| `opencli tiktok following` | List accounts you follow |
| `opencli tiktok friends` | Friend suggestions |
| `opencli tiktok live` | Browse live streams |
| `opencli tiktok notifications` | Get notifications |
| `opencli tiktok like` | Like a video |
| `opencli tiktok unlike` | Unlike a video |
| `opencli tiktok save` | Add to Favorites |
| `opencli tiktok unsave` | Remove from Favorites |
| `opencli tiktok follow` | Follow a user |
| `opencli tiktok unfollow` | Unfollow a user |
| `opencli tiktok comment` | Comment on a video |

## Usage Examples

```bash
# View a user's profile
opencli tiktok profile --username tiktok

# Search videos
opencli tiktok search --query "cooking" --limit 10

# Trending explore videos
opencli tiktok explore --limit 20

# Browse live streams
opencli tiktok live --limit 10

# List who you follow
opencli tiktok following

# Friend suggestions
opencli tiktok friends --limit 10

# Like/unlike a video
opencli tiktok like --url "https://www.tiktok.com/@user/video/123"
opencli tiktok unlike --url "https://www.tiktok.com/@user/video/123"

# Save/unsave (Favorites)
opencli tiktok save --url "https://www.tiktok.com/@user/video/123"
opencli tiktok unsave --url "https://www.tiktok.com/@user/video/123"

# Follow/unfollow
opencli tiktok follow --username nasa
opencli tiktok unfollow --username nasa

# Comment on a video
opencli tiktok comment --url "https://www.tiktok.com/@user/video/123" --text "Great!"

# JSON output
opencli tiktok profile --username tiktok -f json
```

## Prerequisites

- Chrome running and **logged into** tiktok.com
- [Browser Bridge extension](/guide/browser-bridge) installed
58 changes: 58 additions & 0 deletions src/clis/tiktok/comment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
site: tiktok
name: comment
description: Comment on a TikTok video
domain: www.tiktok.com

args:
url:
type: str
required: true
positional: true
description: TikTok video URL
text:
type: str
required: true
description: Comment text

pipeline:
- navigate:
url: ${{ args.url }}
settleMs: 6000

- evaluate: |
(async () => {
const url = ${{ args.url | json }};
const commentText = ${{ args.text | json }};

// Click comment icon to expand comment section
const commentIcon = document.querySelector('[data-e2e="comment-icon"]');
if (commentIcon) {
const cBtn = commentIcon.closest('button') || commentIcon.closest('[role="button"]') || commentIcon;
cBtn.click();
await new Promise(r => setTimeout(r, 3000));
}

// Find comment input
const input = document.querySelector('[data-e2e="comment-input"] [contenteditable="true"]') ||
document.querySelector('[contenteditable="true"]');
if (!input) throw new Error('Comment input not found - make sure you are logged in');

input.focus();
document.execCommand('insertText', false, commentText);
await new Promise(r => setTimeout(r, 1000));

// Click post button
const btns = Array.from(document.querySelectorAll('[data-e2e="comment-post"], button'));
const postBtn = btns.find(function(b) {
var t = b.textContent.trim();
return t === 'Post' || t === '发布' || t === '发送';
});
if (postBtn) {
postBtn.click();
await new Promise(r => setTimeout(r, 2000));
}

return [{ status: 'Commented', url: url, text: commentText }];
})()

columns: [status, url, text]
39 changes: 39 additions & 0 deletions src/clis/tiktok/explore.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
site: tiktok
name: explore
description: Get trending TikTok videos from explore page
domain: www.tiktok.com

args:
limit:
type: int
default: 20
description: Number of videos

pipeline:
- navigate:
url: https://www.tiktok.com/explore
settleMs: 5000

- evaluate: |
(() => {
const limit = ${{ args.limit }};
const links = Array.from(document.querySelectorAll('a[href*="/video/"]'));
const seen = new Set();
const results = [];
for (const a of links) {
const href = a.href;
if (seen.has(href)) continue;
seen.add(href);
const match = href.match(/@([^/]+)\/video\/(\d+)/);
results.push({
rank: results.length + 1,
author: match ? match[1] : '',
views: a.textContent.trim() || '-',
url: href,
});
if (results.length >= limit) break;
}
return results;
})()

columns: [rank, author, views, url]
39 changes: 39 additions & 0 deletions src/clis/tiktok/follow.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
site: tiktok
name: follow
description: Follow a TikTok user
domain: www.tiktok.com

args:
username:
type: str
required: true
positional: true
description: TikTok username (without @)

pipeline:
- navigate:
url: https://www.tiktok.com/@${{ args.username }}
settleMs: 6000

- evaluate: |
(async () => {
const username = ${{ args.username | json }};
const buttons = Array.from(document.querySelectorAll('button, [role="button"]'));
const followBtn = buttons.find(function(b) {
var text = b.textContent.trim();
return text === 'Follow' || text === '关注';
});
if (!followBtn) {
var isFollowing = buttons.some(function(b) {
var t = b.textContent.trim();
return t === 'Following' || t === '已关注' || t === 'Friends' || t === '互关';
});
if (isFollowing) return [{ status: 'Already following', username: username }];
return [{ status: 'Follow button not found', username: username }];
}
followBtn.click();
await new Promise(r => setTimeout(r, 2000));
return [{ status: 'Followed', username: username }];
})()

columns: [status, username]
Loading
Loading