tangled
alpha
login
or
join now
anil.recoil.org
/
ocaml-peertube
0
fork
atom
OCaml bindings to the Peertube ActivityPub video sharing API
0
fork
atom
overview
issues
pulls
pipelines
trim
anil.recoil.org
1 month ago
5bc73e47
9d090378
-511
2 changed files
expand all
collapse all
unified
split
PLAN.md
TODO.md
-310
PLAN.md
···
1
-
# PeerTube OCaml API Coverage Plan
2
-
3
-
## Current Implementation
4
-
5
-
**Implemented (5 endpoints):**
6
-
- `GET /api/v1/video-channels/{channel}/videos` - List channel videos with pagination
7
-
- `GET /api/v1/videos/{uuid}` - Get video details
8
-
- Thumbnail download (static files)
9
-
10
-
**Types:**
11
-
- `video` - Basic video metadata
12
-
- `video_response` - Paginated response wrapper
13
-
14
-
## Proposed Expansion
15
-
16
-
### Phase 1: Enhanced Video Discovery (Priority: High)
17
-
18
-
Add types and functions for browsing and searching videos.
19
-
20
-
#### New Types
21
-
```ocaml
22
-
type sort_order =
23
-
| Newest | Oldest | Views | Likes | Trending | Hot | Random
24
-
25
-
type video_filter = {
26
-
category_id : int option;
27
-
licence_id : int option;
28
-
language : string option;
29
-
nsfw : bool option;
30
-
is_local : bool option;
31
-
has_hls : bool option;
32
-
has_webtorrent : bool option;
33
-
skip_count : bool option; (* skip total count for performance *)
34
-
}
35
-
36
-
type search_params = {
37
-
search : string;
38
-
start : int;
39
-
count : int;
40
-
sort : sort_order;
41
-
search_target : [`Local | `Everywhere] option;
42
-
duration_min : int option;
43
-
duration_max : int option;
44
-
published_after : Ptime.t option;
45
-
published_before : Ptime.t option;
46
-
}
47
-
```
48
-
49
-
#### New Endpoints
50
-
| Function | Endpoint | Description |
51
-
|----------|----------|-------------|
52
-
| `list_videos` | `GET /api/v1/videos` | Browse all videos with filters |
53
-
| `search_videos` | `GET /api/v1/search/videos` | Full-text search |
54
-
| `search_channels` | `GET /api/v1/search/video-channels` | Search channels |
55
-
| `get_categories` | `GET /api/v1/videos/categories` | Video category list |
56
-
| `get_languages` | `GET /api/v1/videos/languages` | Available languages |
57
-
| `get_licences` | `GET /api/v1/videos/licences` | License types |
58
-
59
-
### Phase 2: Channels & Accounts (Priority: High)
60
-
61
-
#### New Types
62
-
```ocaml
63
-
type channel = {
64
-
id : int;
65
-
name : string;
66
-
display_name : string;
67
-
description : string option;
68
-
url : string;
69
-
host : string;
70
-
followers_count : int;
71
-
following_count : int;
72
-
created_at : Ptime.t;
73
-
banner_path : string option;
74
-
avatar_path : string option;
75
-
owner_account : account_summary option;
76
-
}
77
-
78
-
type account_summary = {
79
-
id : int;
80
-
name : string;
81
-
display_name : string;
82
-
url : string;
83
-
host : string;
84
-
}
85
-
86
-
type account = {
87
-
id : int;
88
-
name : string;
89
-
display_name : string;
90
-
description : string option;
91
-
url : string;
92
-
host : string;
93
-
followers_count : int;
94
-
following_count : int;
95
-
created_at : Ptime.t;
96
-
avatar_path : string option;
97
-
}
98
-
```
99
-
100
-
#### New Endpoints
101
-
| Function | Endpoint | Description |
102
-
|----------|----------|-------------|
103
-
| `list_channels` | `GET /api/v1/video-channels` | Browse all channels |
104
-
| `get_channel` | `GET /api/v1/video-channels/{handle}` | Channel details |
105
-
| `list_accounts` | `GET /api/v1/accounts` | Browse accounts |
106
-
| `get_account` | `GET /api/v1/accounts/{handle}` | Account details |
107
-
| `get_account_videos` | `GET /api/v1/accounts/{handle}/videos` | Videos by account |
108
-
| `get_account_channels` | `GET /api/v1/accounts/{handle}/video-channels` | Account's channels |
109
-
110
-
### Phase 3: Playlists (Priority: Medium)
111
-
112
-
#### New Types
113
-
```ocaml
114
-
type playlist_privacy = Public | Unlisted | Private
115
-
116
-
type playlist = {
117
-
id : int;
118
-
uuid : string;
119
-
display_name : string;
120
-
description : string option;
121
-
privacy : playlist_privacy;
122
-
url : string;
123
-
videos_length : int;
124
-
thumbnail_path : string option;
125
-
created_at : Ptime.t;
126
-
updated_at : Ptime.t;
127
-
owner_account : account_summary;
128
-
video_channel : channel option;
129
-
}
130
-
131
-
type playlist_element = {
132
-
id : int;
133
-
position : int;
134
-
start_timestamp : int option;
135
-
stop_timestamp : int option;
136
-
video : video;
137
-
}
138
-
```
139
-
140
-
#### New Endpoints
141
-
| Function | Endpoint | Description |
142
-
|----------|----------|-------------|
143
-
| `list_playlists` | `GET /api/v1/video-playlists` | Browse playlists |
144
-
| `get_playlist` | `GET /api/v1/video-playlists/{id}` | Playlist details |
145
-
| `get_playlist_videos` | `GET /api/v1/video-playlists/{id}/videos` | Videos in playlist |
146
-
| `get_account_playlists` | `GET /api/v1/accounts/{handle}/video-playlists` | Account's playlists |
147
-
148
-
### Phase 4: Server Information (Priority: Medium)
149
-
150
-
#### New Types
151
-
```ocaml
152
-
type server_config = {
153
-
instance_name : string;
154
-
instance_short_description : string;
155
-
instance_description : string;
156
-
instance_terms : string;
157
-
instance_default_nsfw_policy : string;
158
-
signup_allowed : bool;
159
-
signup_allowed_for_current_ip : bool;
160
-
signup_requires_email_verification : bool;
161
-
transcoding_enabled : bool;
162
-
contact_form_enabled : bool;
163
-
}
164
-
165
-
type server_stats = {
166
-
total_users : int;
167
-
total_daily_active_users : int;
168
-
total_weekly_active_users : int;
169
-
total_monthly_active_users : int;
170
-
total_local_videos : int;
171
-
total_local_video_views : int;
172
-
total_local_video_comments : int;
173
-
total_local_video_files_size : int64;
174
-
total_videos : int;
175
-
total_video_comments : int;
176
-
total_local_video_channels : int;
177
-
total_local_playlists : int;
178
-
total_instance_followers : int;
179
-
total_instance_following : int;
180
-
}
181
-
```
182
-
183
-
#### New Endpoints
184
-
| Function | Endpoint | Description |
185
-
|----------|----------|-------------|
186
-
| `get_config` | `GET /api/v1/config` | Server configuration |
187
-
| `get_about` | `GET /api/v1/config/about` | Instance about page |
188
-
| `get_stats` | `GET /api/v1/server/stats` | Server statistics |
189
-
190
-
### Phase 5: Authentication (Priority: Low for read-only clients)
191
-
192
-
#### New Types
193
-
```ocaml
194
-
type oauth_client = {
195
-
client_id : string;
196
-
client_secret : string;
197
-
}
198
-
199
-
type auth_token = {
200
-
access_token : string;
201
-
token_type : string;
202
-
expires_in : int;
203
-
refresh_token : string;
204
-
}
205
-
206
-
type authenticated_session = {
207
-
session : Requests.t;
208
-
token : auth_token;
209
-
expires_at : Ptime.t;
210
-
}
211
-
```
212
-
213
-
#### New Functions
214
-
| Function | Endpoint | Description |
215
-
|----------|----------|-------------|
216
-
| `get_oauth_client` | `GET /api/v1/oauth-clients/local` | Get OAuth credentials |
217
-
| `login` | `POST /api/v1/users/token` | Authenticate user |
218
-
| `refresh_token` | `POST /api/v1/users/token` | Refresh access token |
219
-
| `logout` | `POST /api/v1/users/revoke-token` | Revoke token |
220
-
221
-
### Phase 6: User Interactions (Priority: Low, requires auth)
222
-
223
-
#### New Endpoints (require authentication)
224
-
| Function | Endpoint | Description |
225
-
|----------|----------|-------------|
226
-
| `rate_video` | `POST /api/v1/videos/{id}/rate` | Like/dislike video |
227
-
| `get_my_rating` | `GET /api/v1/videos/{id}/rating` | Get my rating |
228
-
| `get_comments` | `GET /api/v1/videos/{id}/comments` | Video comments |
229
-
| `post_comment` | `POST /api/v1/videos/{id}/comment-threads` | Add comment |
230
-
| `subscribe` | `POST /api/v1/users/me/subscriptions` | Subscribe to channel |
231
-
| `unsubscribe` | `DELETE /api/v1/users/me/subscriptions/{uri}` | Unsubscribe |
232
-
| `get_subscriptions` | `GET /api/v1/users/me/subscriptions` | My subscriptions |
233
-
| `get_subscription_videos` | `GET /api/v1/users/me/subscriptions/videos` | Subscription feed |
234
-
| `get_notifications` | `GET /api/v1/users/me/notifications` | My notifications |
235
-
| `get_watch_history` | `GET /api/v1/users/me/history/videos` | Watch history |
236
-
237
-
## Implementation Strategy
238
-
239
-
### Step 1: Extend Video Type
240
-
Add missing fields to the existing `video` type that are commonly returned:
241
-
- `duration` (int, seconds)
242
-
- `views` (int)
243
-
- `likes` (int)
244
-
- `dislikes` (int)
245
-
- `category` (category record)
246
-
- `licence` (licence record)
247
-
- `language` (language record)
248
-
- `privacy` (privacy record)
249
-
- `is_local` (bool)
250
-
- `channel` (channel_summary)
251
-
- `account` (account_summary)
252
-
253
-
### Step 2: Create Common Pagination Module
254
-
```ocaml
255
-
module Pagination : sig
256
-
type 'a response = {
257
-
total : int;
258
-
data : 'a list;
259
-
}
260
-
261
-
val fetch_all :
262
-
?page_size:int ->
263
-
?max_pages:int ->
264
-
(start:int -> count:int -> 'a response) ->
265
-
'a list
266
-
end
267
-
```
268
-
269
-
### Step 3: Create Module Structure
270
-
```
271
-
lib/
272
-
peertube.ml - Main entry, re-exports submodules
273
-
peertube.mli - Public interface
274
-
video.ml - Video types and operations
275
-
channel.ml - Channel types and operations
276
-
account.ml - Account types and operations
277
-
playlist.ml - Playlist types and operations
278
-
search.ml - Search functionality
279
-
server.ml - Server config/stats
280
-
auth.ml - Authentication (optional)
281
-
```
282
-
283
-
### Step 4: Add CLI Commands
284
-
Extend `opeertube` with new subcommands:
285
-
- `opeertube search <query>` - Search videos
286
-
- `opeertube channels` - List/search channels
287
-
- `opeertube channel <name>` - Channel details
288
-
- `opeertube playlists` - List playlists
289
-
- `opeertube playlist <id>` - Playlist videos
290
-
- `opeertube server info` - Server configuration
291
-
- `opeertube server stats` - Server statistics
292
-
293
-
## File Changes Summary
294
-
295
-
| File | Changes |
296
-
|------|---------|
297
-
| `lib/dune` | No changes needed |
298
-
| `lib/peertube.mli` | Add new types and functions |
299
-
| `lib/peertube.ml` | Add implementations |
300
-
| `bin/opeertube.ml` | Add new CLI commands |
301
-
| `dune-project` | No changes needed |
302
-
303
-
## Testing Plan
304
-
305
-
1. Unit tests for JSON codec round-trips
306
-
2. Integration tests against public PeerTube instances:
307
-
- https://framatube.org
308
-
- https://peertube.social
309
-
- https://video.ploud.fr
310
-
3. CLI smoke tests for each command
···
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
-201
TODO.md
···
1
-
# PeerTube OCaml Client - Remaining Features
2
-
3
-
## Completed
4
-
5
-
- [x] Phase 1: Video Discovery (list, search, categories, languages, licences)
6
-
- [x] Phase 2: Channels & Accounts (list, search, get details)
7
-
- [x] Phase 3: Playlists (list, search, get details, videos)
8
-
- [x] Phase 4: Server Information (config, stats)
9
-
- [x] CLI with all read-only operations
10
-
11
-
## Phase 5: Authentication
12
-
13
-
The Requests library will have OAuth support, which should simplify this phase.
14
-
15
-
### Types
16
-
17
-
```ocaml
18
-
type oauth_client = {
19
-
client_id : string;
20
-
client_secret : string;
21
-
}
22
-
23
-
type auth_token = {
24
-
access_token : string;
25
-
token_type : string;
26
-
expires_in : int;
27
-
refresh_token : string;
28
-
}
29
-
```
30
-
31
-
### Endpoints
32
-
33
-
- [ ] `get_oauth_client` - `GET /api/v1/oauth-clients/local`
34
-
- Fetches the instance's OAuth client credentials
35
-
- Required before user authentication
36
-
37
-
- [ ] `login` - `POST /api/v1/users/token`
38
-
- OAuth2 password grant flow
39
-
- Parameters: username, password, client_id, client_secret
40
-
- Returns access_token and refresh_token
41
-
- Use Requests OAuth support for token management
42
-
43
-
- [ ] `refresh_token` - `POST /api/v1/users/token`
44
-
- OAuth2 refresh token grant
45
-
- Automatically refresh expired tokens
46
-
- Requests OAuth support should handle this
47
-
48
-
- [ ] `logout` - `POST /api/v1/users/revoke-token`
49
-
- Revoke the current access token
50
-
51
-
### Implementation Notes
52
-
53
-
- Requests OAuth support will handle token storage and automatic refresh
54
-
- Consider storing tokens in `~/.config/opeertube/` for CLI persistence
55
-
- Add `--login` flag to CLI for interactive authentication
56
-
57
-
## Phase 6: User Interactions (requires auth)
58
-
59
-
### Video Interactions
60
-
61
-
- [ ] `rate_video` - `POST /api/v1/videos/{id}/rate`
62
-
- Body: `{ "rating": "like" | "dislike" | "none" }`
63
-
64
-
- [ ] `get_my_rating` - `GET /api/v1/videos/{id}/rating`
65
-
- Returns user's rating for a video
66
-
67
-
### Comments
68
-
69
-
- [ ] `get_comments` - `GET /api/v1/videos/{id}/comment-threads`
70
-
- Paginated list of top-level comments
71
-
- Each comment has nested replies
72
-
73
-
- [ ] `get_comment_thread` - `GET /api/v1/videos/{id}/comment-threads/{threadId}`
74
-
- Full thread with all replies
75
-
76
-
- [ ] `post_comment` - `POST /api/v1/videos/{id}/comment-threads`
77
-
- Body: `{ "text": "comment content" }`
78
-
79
-
- [ ] `reply_to_comment` - `POST /api/v1/videos/{id}/comments/{commentId}`
80
-
- Body: `{ "text": "reply content" }`
81
-
82
-
- [ ] `delete_comment` - `DELETE /api/v1/videos/{id}/comments/{commentId}`
83
-
84
-
### Subscriptions
85
-
86
-
- [ ] `subscribe` - `POST /api/v1/users/me/subscriptions`
87
-
- Body: `{ "uri": "channel@host" }`
88
-
89
-
- [ ] `unsubscribe` - `DELETE /api/v1/users/me/subscriptions/{subscriptionHandle}`
90
-
91
-
- [ ] `get_subscriptions` - `GET /api/v1/users/me/subscriptions`
92
-
- Paginated list of subscribed channels
93
-
94
-
- [ ] `get_subscription_videos` - `GET /api/v1/users/me/subscriptions/videos`
95
-
- Subscription feed (videos from subscribed channels)
96
-
97
-
- [ ] `subscription_exists` - `GET /api/v1/users/me/subscriptions/exist`
98
-
- Check if subscribed to specific channels
99
-
100
-
### User Profile
101
-
102
-
- [ ] `get_my_info` - `GET /api/v1/users/me`
103
-
- Current user's account info
104
-
105
-
- [ ] `update_my_info` - `PUT /api/v1/users/me`
106
-
- Update display name, description, etc.
107
-
108
-
- [ ] `get_my_videos` - `GET /api/v1/users/me/videos`
109
-
- Videos uploaded by current user
110
-
111
-
### Watch History & Notifications
112
-
113
-
- [ ] `get_watch_history` - `GET /api/v1/users/me/history/videos`
114
-
- Paginated watch history
115
-
116
-
- [ ] `delete_watch_history` - `POST /api/v1/users/me/history/videos/remove`
117
-
- Clear watch history
118
-
119
-
- [ ] `get_notifications` - `GET /api/v1/users/me/notifications`
120
-
- User notifications
121
-
122
-
- [ ] `mark_notifications_read` - `POST /api/v1/users/me/notifications/read`
123
-
- Mark notifications as read
124
-
125
-
- [ ] `mark_all_notifications_read` - `POST /api/v1/users/me/notifications/read-all`
126
-
127
-
## Phase 7: Content Upload (requires auth)
128
-
129
-
### Video Upload
130
-
131
-
- [ ] `upload_video` - `POST /api/v1/videos/upload`
132
-
- Multipart form upload
133
-
- Required fields: channelId, name, videofile
134
-
- Optional: description, tags, privacy, etc.
135
-
136
-
- [ ] `upload_video_resumable_init` - `POST /api/v1/videos/upload-resumable`
137
-
- Initialize resumable upload for large files
138
-
139
-
- [ ] `upload_video_resumable` - `PUT /api/v1/videos/upload-resumable`
140
-
- Continue resumable upload
141
-
142
-
- [ ] `update_video` - `PUT /api/v1/videos/{id}`
143
-
- Update video metadata
144
-
145
-
- [ ] `delete_video` - `DELETE /api/v1/videos/{id}`
146
-
147
-
### Playlist Management
148
-
149
-
- [ ] `create_playlist` - `POST /api/v1/video-playlists`
150
-
- Create a new playlist
151
-
152
-
- [ ] `update_playlist` - `PUT /api/v1/video-playlists/{playlistId}`
153
-
154
-
- [ ] `delete_playlist` - `DELETE /api/v1/video-playlists/{playlistId}`
155
-
156
-
- [ ] `add_video_to_playlist` - `POST /api/v1/video-playlists/{playlistId}/videos`
157
-
- Body: `{ "videoId": id }`
158
-
159
-
- [ ] `remove_video_from_playlist` - `DELETE /api/v1/video-playlists/{playlistId}/videos/{playlistElementId}`
160
-
161
-
- [ ] `reorder_playlist` - `POST /api/v1/video-playlists/{playlistId}/videos/reorder`
162
-
163
-
## CLI Enhancements
164
-
165
-
### Authentication Commands
166
-
167
-
- [ ] `opeertube login` - Interactive login, store token
168
-
- [ ] `opeertube logout` - Revoke and delete stored token
169
-
- [ ] `opeertube whoami` - Show current user info
170
-
171
-
### Authenticated Operations
172
-
173
-
- [ ] `opeertube like VIDEO_UUID` - Like a video
174
-
- [ ] `opeertube dislike VIDEO_UUID` - Dislike a video
175
-
- [ ] `opeertube subscribe CHANNEL` - Subscribe to channel
176
-
- [ ] `opeertube unsubscribe CHANNEL` - Unsubscribe
177
-
- [ ] `opeertube subscriptions` - List subscriptions
178
-
- [ ] `opeertube feed` - Show subscription feed
179
-
- [ ] `opeertube history` - Show watch history
180
-
- [ ] `opeertube notifications` - Show notifications
181
-
182
-
### Upload Commands
183
-
184
-
- [ ] `opeertube upload FILE --channel CHANNEL --name NAME [options]`
185
-
- [ ] `opeertube update VIDEO_UUID [options]`
186
-
- [ ] `opeertube delete VIDEO_UUID`
187
-
188
-
## Code Quality
189
-
190
-
- [ ] Add unit tests for JSON codec round-trips
191
-
- [ ] Add integration tests against public instances
192
-
- [ ] Add CI configuration (GitHub Actions)
193
-
- [ ] Generate opam file for release
194
-
- [ ] Add rate limiting / retry logic for API calls
195
-
- [ ] Consider caching for frequently accessed data
196
-
197
-
## Documentation
198
-
199
-
- [ ] Add examples to mli documentation
200
-
- [ ] Create tutorial for common use cases
201
-
- [ ] Document error handling patterns
···
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0