diff --git a/mkdocs/docs/api/additional.md b/mkdocs/docs/api/additional.md new file mode 100644 index 0000000..95e1720 --- /dev/null +++ b/mkdocs/docs/api/additional.md @@ -0,0 +1,141 @@ +# Additional API endpoints + +## Login +Return token and user ID for username and password: +**POST** `/api/login/` +```json +{ + "username": "tubearchivist", + "password": "verysecret" +} +``` + +after successful login returns +```json +{ + "token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "user_id": 1 +} +``` + +## Refresh +**GET** `/api/refresh/` + +Parameters: + +- **type**: one of *video*, *channel*, *playlist*, optional +- **id**: item id, optional + +without specifying type: return total for all queued items: +```json +{ + "total_queued": 2, + "type": "all", + "state": "running" +} +``` + +specify type: return total items queue of this type: +```json +{ + "total_queued": 2, + "type": "video", + "state": "running" +} +``` + +specify type *and* id to get state of item in queue: +```json +{ + "total_queued": 2, + "type": "video", + "state": "in_queue", + "id": "video-id" +} +``` + +**POST** `/api/refresh/` + +Parameter: + +- extract_videos: to refresh all videos for channels/playlists, default False + +Manually start a refresh task: post list of *video*, *channel*, *playlist* IDs: +```json +{ + "video": ["video1", "video2", "video3"], + "channel": ["channel1", "channel2", "channel3"], + "playlist": ["playlist1", "playlist2"] +} +``` + +## Cookie +Check your youtube cookie settings, *status* turns to `true` if cookie has been validated. +**GET** `/api/cookie/` +```json +{ + "cookie_enabled": true, + "status": true, + "validated": 1680953715, + "validated_str": "timestamp" +} +``` + +**POST** `/api/cookie/` +Send empty post request to validate cookie. +```json +{ + "cookie_validated": true +} +``` + +**PUT** `/api/cookie/` +Send put request containing the cookie as a string: +```json +{ + "cookie": "your-cookie-as-string" +} +``` +Imports and validates cookie, returns on success: +```json +{ + "cookie_import": "done", + "cookie_validated": true +} +``` +Or returns status code 400 on failure: +```json +{ + "cookie_import": "fail", + "cookie_validated": false +} +``` + +## Search +**GET** `/api/search/?query=` + +Returns search results from your query. + +## Watched +**POST** `/api/watched/` + +Change watched state, where the `id` can be a single video, or channel/playlist to change all videos belonging to that channel/playlist. + +```json +{ + "id": "xxxxxxx", + "is_watched": true +} +``` + +## Ping +Validate your connection with the API +**GET** `/api/ping/` + +When valid returns message with user id: +```json +{ + "response": "pong", + "user": 1 +} +``` diff --git a/mkdocs/docs/api/channel.md b/mkdocs/docs/api/channel.md new file mode 100644 index 0000000..89623bc --- /dev/null +++ b/mkdocs/docs/api/channel.md @@ -0,0 +1,27 @@ +# Channel + +## Channel List +`/api/channel/` + +Parameter: + +- filter: subscribed + +Subscribe to a list of channels: +**POST** `/api/channel/` +```json +{ + "data": [ + {"channel_id": "UC9-y-6csu5WGm29I7JiwpnA", "channel_subscribed": true} + ] +} +``` + +## Channel Item +**GET** `/api/channel//` +**DELETE** `/api/channel/\/` + +- Will delete channel with all it's videos + +## Channel Videos +**GET** /api/channel/\/video/ diff --git a/mkdocs/docs/api/download.md b/mkdocs/docs/api/download.md new file mode 100644 index 0000000..887db08 --- /dev/null +++ b/mkdocs/docs/api/download.md @@ -0,0 +1,51 @@ +# Download + +## Download Queue List +**GET** `/api/download/` + +Parameter: + +- filter: pending, ignore +- channel: channel-id + +Add list of videos to download queue: +**POST** `/api/download/` +```json +{ + "data": [ + {"youtube_id": "NYj3DnI81AQ", "status": "pending"} + ] +} +``` + +Delete download queue items by filter: +**DELETE** `/api/download/?filter=ignore` +**DELETE** `/api/download/?filter=pending` + +## Download Queue Item +**GET** `/api/download//` +**POST** `/api/download//` + +Ignore video in download queue: +```json +{ + "status": "ignore" +} +``` + +Add to queue previously ignored video: +```json +{ + "status": "pending" +} +``` + +Download existing video now: +```json +{ + "status": "priority" +} +``` + +**DELETE** `/api/download//` +Forget or delete from download queue diff --git a/mkdocs/docs/api/introduction.md b/mkdocs/docs/api/introduction.md new file mode 100644 index 0000000..cd659ba --- /dev/null +++ b/mkdocs/docs/api/introduction.md @@ -0,0 +1,43 @@ +# Introduction + +This page has a generic overview with how the Tube Archivist API functions. This is the place to start. + +!!! note + These API endpoints *have* changed in the past and *will* change again while building out additional integrations and functionality. For the time being, don't expect backwards compatibility for third party integrations using these endpoints. + +## Context +- All changes to the API are marked with a `[API]` keyword for easy searching, for example search for [commits](https://github.com/tubearchivist/tubearchivist/search?o=desc&q=%5Bapi%5D&s=committer-date&type=commits). You'll find the same in the [release notes](https://github.com/tubearchivist/tubearchivist/releases). +- Check the commit history and release notes to see if a documented feature is already in your release. The documentation might be ahead of the regular release schedule. + +## Authentication +API token will get automatically created, accessible on the settings page. Token needs to be passed as an authorization header with every request. Additionally session based authentication is enabled too: When you are logged into your TubeArchivist instance, you'll have access to the api in the browser for testing. + +Curl example: +```shell +curl -v /api/video// \ + -H "Authorization: Token xxxxxxxxxx" +``` + +Python requests example: +```python +import requests + +url = "/api/video//" +headers = {"Authorization": "Token xxxxxxxxxx"} +response = requests.get(url, headers=headers) +``` + +## Pagination +The list views return a paginate object with the following keys: + + - page_size: *int* current page size set in config + - page_from: *int* first result idx + - prev_pages: *array of ints* of previous pages, if available + - current_page: *int* current page from query + - max_hits: *bool* if max of 10k results is reached + - params: *str* additional url encoded query parameters + - last_page: *int* of last page link + - next_pages: *array of ints* of next pages + - total_hits: *int* total results + +Pass page number as a query parameter: `page=2`. Defaults to *0*, `page=1` is redundant and falls back to *0*. If a page query doesn't return any results, you'll get `HTTP 404 Not Found`. diff --git a/mkdocs/docs/api/playlist.md b/mkdocs/docs/api/playlist.md new file mode 100644 index 0000000..c07ab74 --- /dev/null +++ b/mkdocs/docs/api/playlist.md @@ -0,0 +1,10 @@ +# Playlist + +## Playlist List +**GET** `/api/playlist/` + +## Playlist Item +**GET** `/api/playlist//` + +## Playlist Videos +**GET** `/api/playlist//video/` diff --git a/mkdocs/docs/api/snapshot.md b/mkdocs/docs/api/snapshot.md new file mode 100644 index 0000000..e46bfd8 --- /dev/null +++ b/mkdocs/docs/api/snapshot.md @@ -0,0 +1,43 @@ +# Snapshot + +## Snapshot List +**GET** `/api/snapshot/` +Return snapshot config and a list of available snapshots. + +```json +{ + "next_exec": epoch, + "next_exec_str": "date_str", + "expire_after": "30d", + "snapshots": [] +} +``` + +**POST** `/api/snapshot/` +Create new snapshot now, will return immediately, task will run async in the background, returns snapshot name: +```json +{ + "snapshot_name": "ta_daily_" +} +``` + +## Snapshot Item View +**GET** `/api/snapshot//` +Return metadata of a single snapshot +```json +{ + "id": "ta_daily_", + "state": "SUCCESS", + "es_version": "0.0.0", + "start_date": "date_str", + "end_date": "date_str", + "end_stamp": epoch, + "duration_s": 0 +} +``` + +**POST** `/api/snapshot//` +Restore this snapshot + +**DELETE** `/api/snapshot//` +Remove this snapshot from index diff --git a/mkdocs/docs/api/task.md b/mkdocs/docs/api/task.md new file mode 100644 index 0000000..8c53c30 --- /dev/null +++ b/mkdocs/docs/api/task.md @@ -0,0 +1,24 @@ +# Task Name and Task ID + +## Task Name List View +**GET** `/api/task-name/` +Return all task results. + +## Task Name Item View +**GET** `/api/task-name//` +Return all ask results by task name + +**POST** `/api/task-name//` +Start a new task by task name, only tasks without arguments can be started like that, see `home.tasks.BaseTask.TASK_CONFIG` for more info. + +## Task ID view +**GET** `/api/task-id//` +Return task status by task ID + +**POST** `/api/task-id//` +```json +{ + "command": "stop|kill" +} +``` +Send command to a task, valid commands: `stop` and `kill`. Not all tasks implement these commands `home.tasks.BaseTask.TASK_CONFIG` for details. diff --git a/mkdocs/docs/api/video.md b/mkdocs/docs/api/video.md new file mode 100644 index 0000000..0d5e73f --- /dev/null +++ b/mkdocs/docs/api/video.md @@ -0,0 +1,78 @@ +# Video + + +## Video List +**GET** `/api/video/` + +## Video Item +**GET** `/api/video//` +**DELETE** `/api/video//` + +## Video Comment +**GET** `/api/video//comment/` + +## Video Similar +**GET** `/api/video//similar/` + +## Video Progress +`/api/video//progress/` + +Progress is stored for each user. + +Get last player position of a video: +**GET** `/api/video//progress/` +```json +{ + "youtube_id": "", + "user_id": 1, + "position": 100 +} +``` + +Update player position of video: +**POST** `/api/video//progress/` +```json +{ + "position": 100 +} +``` + +Delete player position: +**DELETE** `/api/video//progress/` + + +## Sponsor Block +`/api/video//sponsor/` + +Integrate with sponsorblock + +Get list of segments: +**GET** `/api/video//sponsor/` + + +!!! note + Writing to Sponsorblock enpoints is only simulated for now and won't forward any requests. This needs some clever UI/UX implementation first. + +Vote on existing segment: +**POST** `/api/video//sponsor/` +```json +{ + "vote": { + "uuid": "", + "yourVote": 1 + } +} +``` +yourVote needs to be *int*: 0 for downvote, 1 for upvote, 20 to undo vote + +Create new segment +**POST** `/api/video//sponsor/` +```json +{ + "segment": { + "startTime": 5, + "endTime": 10 + } +} +``` +Timestamps either *int* or *float*, end time can't be before start time. diff --git a/mkdocs/docs/stylesheets/style.css b/mkdocs/docs/stylesheets/style.css index 51b466b..00d1ed1 100644 --- a/mkdocs/docs/stylesheets/style.css +++ b/mkdocs/docs/stylesheets/style.css @@ -10,12 +10,17 @@ font-family: 'Sen-Regular'; } -* { +p, a, span, h3 { font-family: Sen-Regular; } +code span { + font-family: monospace; +} + h1, -h2 { +h2, +strong { font-family: Sen-Bold; } @@ -50,6 +55,11 @@ footer { --md-admonition-bg-color: var(--highlight-bg); --md-admonition-fg-color: var(--main-font); --md-footer-bg-color: var(--highlight-bg); + --md-code-hl-punctuation-color: var(--main-font); + --md-code-hl-name-color: var(--accent-font-light); + --md-code-hl-string-color: var(--accent-font-dark); + --md-code-hl-number-color: var(--highlight-error-light); + --md-code-hl-operator-color: var(--highlight-error); } :root { diff --git a/mkdocs/mkdocs.yml b/mkdocs/mkdocs.yml index 316a606..858eb2f 100644 --- a/mkdocs/mkdocs.yml +++ b/mkdocs/mkdocs.yml @@ -21,6 +21,15 @@ nav: - Configuration: - 'LDAP Authentication': 'configuration/ldap.md' - 'Cast Support': 'configuration/cast.md' + - API: + - 'Introduction': 'api/introduction.md' + - 'Video': 'api/video.md' + - 'Channel': 'api/channel.md' + - 'Playlist': 'api/playlist.md' + - 'Download': 'api/download.md' + - 'Snapshot': 'api/snapshot.md' + - 'Task': 'api/task.md' + - 'Additional': 'api/additional.md' - Links: - 'Main site': https://www.tubearchivist.com - 'Join us on Discord!': https://www.tubearchivist.com/discord