add doc generator, tweak routes, add channel_id to presets and user, better defaults

This commit is contained in:
jb-alvarado 2022-07-05 18:08:00 +02:00
parent cb65d8084f
commit 7978eb1126
11 changed files with 596 additions and 250 deletions

View File

@ -3,7 +3,7 @@ Description=Rust and ffmpeg based playout solution
After=network.target remote-fs.target After=network.target remote-fs.target
[Service] [Service]
ExecStart= /usr/bin/ffplayout ExecStart=/usr/bin/ffplayout
ExecReload=/bin/kill -1 $MAINPID ExecReload=/bin/kill -1 $MAINPID
Restart=always Restart=always
RestartSec=1 RestartSec=1

View File

@ -10,7 +10,7 @@ general:
rpc_server: rpc_server:
help_text: Run a JSON RPC server, for getting infos about current playing, and help_text: Run a JSON RPC server, for getting infos about current playing, and
control for some functions. control for some functions.
enable: false enable: true
address: 127.0.0.1:7070 address: 127.0.0.1:7070
authorization: av2Kx8g67lF9qj5wEH3ym1bI4cCs authorization: av2Kx8g67lF9qj5wEH3ym1bI4cCs
@ -108,7 +108,7 @@ text:
'text_from_filename' activate the extraction from text of a filename. With 'style' 'text_from_filename' activate the extraction from text of a filename. With 'style'
you can define the drawtext parameters like position, color, etc. Post Text over you can define the drawtext parameters like position, color, etc. Post Text over
API will override this. With 'regex' you can format file names, to get a title from it. API will override this. With 'regex' you can format file names, to get a title from it.
add_text: false add_text: true
text_from_filename: false text_from_filename: false
fontfile: "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf" fontfile: "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"
style: "x=(w-tw)/2:y=(h-line_h)*0.9:fontsize=24:fontcolor=#ffffff:box=1:boxcolor=#000000:boxborderw=4" style: "x=(w-tw)/2:y=(h-line_h)*0.9:fontsize=24:fontcolor=#ffffff:box=1:boxcolor=#000000:boxborderw=4"

View File

@ -1,186 +1,313 @@
#### Possible endpoints ### Possible endpoints
Run the API thru the systemd service, or like: Run the API thru the systemd service, or like:
```BASH ```BASH
ffpapi -l 127.0.0.1:8080 ffpapi -l 127.0.0.1:8000
``` ```
For all endpoints an (Bearer) authentication is required.\ For all endpoints an (Bearer) authentication is required.\
`{id}` represent the channel id, and at default is 1. `{id}` represent the channel id, and at default is 1.
#### Login is #### User Handling
**Login**
```BASH
curl -X POST http://127.0.0.1:8000/auth/login/ -H "Content-Type: application/json" \
-d '{ "username": "<USER>", "password": "<PASS>" }'
```
**Response:**
- **POST** `/auth/login/`\
JSON Data: `{"username": "<USER>", "password": "<PASS>"}`\
JSON Response:
```JSON ```JSON
{ {
"message": "login correct!", "id": 1,
"status": 200, "mail": "user@example.org",
"data": { "username": "<USER>",
"id": 1, "token": "<TOKEN>"
"mail": "user@example.org",
"username": "user",
"token": "<TOKEN>"
}
} }
``` ```
From here on all request **must** contain the authorization header:\ From here on all request **must** contain the authorization header:\
`"Authorization: Bearer <TOKEN>"` `"Authorization: Bearer <TOKEN>"`
#### User **Get current User**
- **GET** `/api/user`\ ```BASH
Get current user, response is in JSON format curl -X GET 'http://localhost:8000/api/user' -H 'Content-Type: application/json' \
-H 'Authorization: Bearer <TOKEN>'
```
- **PUT** `/api/user/{user id}`\ **Update current User**
JSON Data: `{"mail": "<MAIL>", "password": "<PASS>"}`
```BASH
curl -X PUT http://localhost:8000/api/user/1 -H 'Content-Type: application/json' \
-d '{"mail": "<MAIL>", "password": "<PASS>"}' -H 'Authorization: <TOKEN>'
```
**Add User**
```BASH
curl -X POST 'http://localhost:8000/api/user/' -H 'Content-Type: application/json' \
-d '{"mail": "<MAIL>", "username": "<USER>", "password": "<PASS>", "role_id": 1, "channel_id": 1}' \
-H 'Authorization: Bearer <TOKEN>'
```
#### ffpapi Settings
**Get Settings**
```BASH
curl -X GET http://127.0.0.1:8000/api/settings/1 -H "Authorization: Bearer <TOKEN>"
```
**Response:**
- **POST** `/api/user/`\
JSON Data:
```JSON ```JSON
{ {
"mail": "<MAIL>", "id": 1,
"username": "<USER>", "channel_name": "Channel 1",
"password": "<PASS>", "preview_url": "http://localhost/live/preview.m3u8",
"role_id": 1 "config_path": "/etc/ffplayout/ffplayout.yml",
"extra_extensions": "jpg,jpeg,png",
"timezone": "UTC",
"service": "ffplayout.service"
} }
``` ```
#### API Settings **Get all Settings**
- **GET** `/api/settings`\ ```BASH
Response is in JSON format curl -X GET http://127.0.0.1:8000/api/settings -H "Authorization: Bearer <TOKEN>"
- **GET** `/api/settings/{id}`\
Response is in JSON format
- **PATCH** `/api/settings/{id}`\
JSON Data:
```JSON
"id": 1,
"channel_name": "Channel 1",
"preview_url": "http://localhost/live/stream.m3u8",
"config_path": "/etc/ffplayout/ffplayout.yml",
"extra_extensions": ".jpg,.jpeg,.png"
``` ```
#### Playout Config **Update Settings**
- **GET** `/api/playout/config/{id}`\ ```BASH
Response is in JSON format curl -X PATCH http://127.0.0.1:8000/api/settings/1 -H "Content-Type: application/json" \
-d '{ "id": 1, "channel_name": "Channel 1", "preview_url": "http://localhost/live/stream.m3u8", \
"config_path": "/etc/ffplayout/ffplayout.yml", "extra_extensions": "jpg,jpeg,png",
"role_id": 1, "channel_id": 1 }' \
-H "Authorization: Bearer <TOKEN>"
```
- **PUT** `/api/playout/config/{id}`\ #### ffplayout Config
JSON Data: `{ <CONFIG DATA> }`\
Response is in TEXT format **Get Config**
```BASH
curl -X GET http://localhost:8000/api/playout/config/1 -H 'Authorization: <TOKEN>'
```
Response is a JSON object from the ffplayout.yml
**Update Config**
```BASH
curl -X PUT http://localhost:8000/api/playout/config/1 -H "Content-Type: application/json" \
-d { <CONFIG DATA> } -H 'Authorization: <TOKEN>'
```
#### Text Presets #### Text Presets
- **GET** `/api/presets/`\ Text presets are made for sending text messages to the ffplayout engine, to overlay them as a lower third.
Response is in JSON format
**Get all Presets**
```BASH
curl -X GET http://localhost:8000/api/presets/ -H 'Content-Type: application/json' \
-H 'Authorization: <TOKEN>'
```
**Update Preset**
```BASH
curl -X PUT http://localhost:8000/api/presets/1 -H 'Content-Type: application/json' \
-d '{"name": "<PRESET NAME>", "text": "<TEXT>", "x": "<X>", "y": "<Y>", "fontsize": 24, \
"line_spacing": 4, "fontcolor": "#ffffff", "box": 1, "boxcolor": "#000000", "boxborderw": 4, "alpha": 1.0}' \
-H 'Authorization: <TOKEN>'
```
**Ad new Preset**
```BASH
curl -X POST http://localhost:8000/api/presets/ -H 'Content-Type: application/json' \
-d '{"name": "<PRESET NAME>", "text": "TEXT>", "x": "<X>", "y": "<Y>", "fontsize": 24, \
"line_spacing": 4, "fontcolor": "#ffffff", "box": 1, "boxcolor": "#000000", "boxborderw": 4, "alpha": 1.0}}' \
-H 'Authorization: <TOKEN>'
```
### ffplayout controlling
here we communicate with the engine for:
- jump to last or next clip
- reset playlist state
- get infos about current, next, last clip
- send text to the engine, for overlaying it (as lower third etc.)
**Send Text to ffplayout**
```BASH
curl -X POST http://localhost:8000/api/control/1/text/ \
-H 'Content-Type: application/json' -H 'Authorization: <TOKEN>' \
-d '{"text": "Hello from ffplayout", "x": "(w-text_w)/2", "y": "(h-text_h)/2", \
"fontsize": "24", "line_spacing": "4", "fontcolor": "#ffffff", "box": "1", \
"boxcolor": "#000000", "boxborderw": "4", "alpha": "1.0"}'
```
**Jump to next Clip**
```BASH
curl -X POST http://localhost:8000/api/control/1/playout/next/ -H 'Authorization: <TOKEN>'
```
**Jump to last Clip**
```BASH
curl -X POST http://localhost:8000/api/control/1/playout/back/ -H 'Authorization: <TOKEN>'
```
**Reset ffplayout State**
When before was jumped to next, or last clips, here we go back to the original clip.
```BASH
curl -X POST http://localhost:8000/api/control/1/playout/reset/ -H 'Authorization: <TOKEN>'
```
**Get current Clip**
```BASH
curl -X GET http://localhost:8000/api/control/1/media/current/
-H 'Content-Type: application/json' -H 'Authorization: <TOKEN>'
```
**Response:**
- **PUT** `/api/playout/presets/{id}`\
JSON Data:
```JSON ```JSON
{ {
"name": "<PRESET NAME>", "jsonrpc": "2.0",
"text": "<TEXT>", "result": {
"x": "<X>", "current_media": {
"y": "<Y>", "category": "",
"fontsize": 24, "duration": 154.2,
"line_spacing": 4, "out": 154.2,
"fontcolor": "#ffffff", "seek": 0.0,
"box": 1, "source": "/opt/tv-media/clip.mp4"
"boxcolor": "#000000", },
"boxborderw": 4, "index": 39,
"alpha": "<alpha>" "play_mode": "playlist",
} "played_sec": 67.80771999300123,
"remaining_sec": 86.39228000699876,
``` "start_sec": 24713.631999999998,
Response is in TEXT format "start_time": "06:51:53.631"
},
- **POST** `/api/playout/presets/`\ "id": 1
JSON Data: `{ <PRESET DATA> }`\
Response is in TEXT format
#### Playout Process Control
- **POST** `/api/control/{id}/text/`¸
JSON Data:
```JSON
{
"text": "Hello from ffplayout",
"x": "(w-text_w)/2",
"y": "(h-text_h)/2",
"fontsize": "24",
"line_spacing": "4",
"fontcolor": "#ffffff",
"box": "1",
"boxcolor": "#000000",
"boxborderw": "4",
"alpha": "1.0"
} }
``` ```
Response is in TEXT format
- **POST** `api/control/{id}/playout/next/`\ **Get next Clip**
Response is in TEXT format
- **POST** `api/control/{id}/playout/back/`\ ```BASH
Response is in TEXT format curl -X GET http://localhost:8000/api/control/1/media/next/ -H 'Authorization: <TOKEN>'
```
- **POST** `api/control/{id}/playout/reset/`\ **Get last Clip**
Response is in TEXT format
- **GET** `/api/control/{id}/media/current`\ ```BASH
Response is in JSON format curl -X GET http://localhost:8000/api/control/1/media/last/
-H 'Content-Type: application/json' -H 'Authorization: <TOKEN>'
```
- **GET** `/api/control/{id}/media/next`\ #### ffplayout Process Control
Response is in JSON format
- **GET** `/api/control/{id}/media/last`\ Control ffplayout process, like:
Response is in JSON format - start
- stop
- restart
- status
- **POST** `/api/control/{id}/process/`\ ```BASH
JSON Data: `{"command": "<start/stop/restart/status>"}` curl -X POST http://localhost:8000/api/control/1/process/
Response is in TEXT format -H 'Content-Type: application/json' -H 'Authorization: <TOKEN>'
-d '{"command": "start"}'
```
#### Playlist Operations #### ffplayout Playlist Operations
- **GET** `/api/playlist/{id}/2022-06-20`\ **Get playlist**
Response is in JSON format
- **POST** `/api/playlist/1/`\ ```BASH
JSON Data: `{ <PLAYLIST DATA> }`\ curl -X GET http://localhost:8000/api/playlist/1?date=2022-06-20
Response is in TEXT format -H 'Content-Type: application/json' -H 'Authorization: <TOKEN>'
```
- **GET** `/api/playlist/{id}/generate/2022-06-20`\ **Save playlist**
Response is in JSON format
- **DELETE** `/api/playlist/{id}/2022-06-20`\ ```BASH
Response is in TEXT format curl -X POST http://localhost:8000/api/playlist/1/
-H 'Content-Type: application/json' -H 'Authorization: <TOKEN>'
-- data "{<JSON playlist data>}"
```
#### Log File **Generate Playlist**
- **GET** `/api/file/{id}/browse/`\ A new playlist will be generated and response.
Response is in JSON format
```BASH
curl -X GET http://localhost:8000/api/playlist/1/generate/2022-06-20
-H 'Content-Type: application/json' -H 'Authorization: <TOKEN>'
```
#### File Operations **Delete Playlist**
- **GET** `/api/log/{id}(/{date})`\ ```BASH
Response is in TEXT format curl -X DELETE http://localhost:8000/api/playlist/1/2022-06-20
-H 'Content-Type: application/json' -H 'Authorization: <TOKEN>'
```
- **POST** `/api/file/{id}/move/`\ ### Log file
JSON Data: `{"source": "<SOURCE>", "target": "<TARGET>"}`\
Response is in JSON format
- **DELETE** `/api/file/{id}/remove/`\ **Read Log Life**
JSON Data: `{"source": "<SOURCE>"}`\
Response is in JSON format
- **POST** `/file/{id}/upload/`\ ```BASH
Multipart Form: `name=<TARGET PATH>, filename=<FILENAME>`\ curl -X Get http://localhost:8000/api/log/1
Response is in TEXT format -H 'Content-Type: application/json' -H 'Authorization: <TOKEN>'
```
### File Operations
**Get File/Folder List**
```BASH
curl -X POST http://localhost:8000/api/file/1/browse/ -H 'Content-Type: application/json'
-d '{ "source": "/" }' -H 'Authorization: <TOKEN>'
```
**Create Folder**
```BASH
curl -X POST http://localhost:8000/api/file/1/create-folder/ -H 'Content-Type: application/json'
-d '{"source": "<FOLDER PATH>"}' -H 'Authorization: <TOKEN>'
```
**Rename File**
```BASH
curl -X POST http://localhost:8000/api/file/1/rename/ -H 'Content-Type: application/json'
-d '{"source": "<SOURCE>", "target": "<TARGET>"}' -H 'Authorization: <TOKEN>'
```
**Remove File/Folder**
```BASH
curl -X POST http://localhost:8000/api/file/1/remove/ -H 'Content-Type: application/json'
-d '{"source": "<SOURCE>"}' -H 'Authorization: <TOKEN>'
```
**Upload File**
```BASH
curl -X POST http://localhost:8000/api/file/1/upload/ -H 'Authorization: <TOKEN>'
-F "file=@file.mp4"
```

View File

@ -17,9 +17,9 @@ use utils::{
routes::{ routes::{
add_dir, add_preset, add_user, del_playlist, file_browser, gen_playlist, get_all_settings, add_dir, add_preset, add_user, del_playlist, file_browser, gen_playlist, get_all_settings,
get_log, get_playlist, get_playout_config, get_presets, get_settings, get_user, get_log, get_playlist, get_playout_config, get_presets, get_settings, get_user,
jump_to_last, jump_to_next, login, media_current, media_last, media_next, move_rename, control_playout, login, media_current, media_last, media_next, move_rename,
patch_settings, process_control, remove, reset_playout, save_file, save_playlist, patch_settings, process_control, remove, save_file, save_playlist,
send_text_message, update_playout_config, update_preset, update_user, send_text_message, update_playout_config, update_preset, update_user, delete_preset,
}, },
run_args, Role, run_args, Role,
}; };
@ -83,14 +83,13 @@ async fn main() -> std::io::Result<()> {
.service(add_preset) .service(add_preset)
.service(get_presets) .service(get_presets)
.service(update_preset) .service(update_preset)
.service(delete_preset)
.service(get_settings) .service(get_settings)
.service(get_all_settings) .service(get_all_settings)
.service(patch_settings) .service(patch_settings)
.service(update_user) .service(update_user)
.service(send_text_message) .service(send_text_message)
.service(jump_to_next) .service(control_playout)
.service(jump_to_last)
.service(reset_playout)
.service(media_current) .service(media_current)
.service(media_next) .service(media_next)
.service(media_last) .service(media_last)

View File

@ -97,7 +97,7 @@ impl SystemD {
let output = Command::new("sudo").args(self.cmd).output()?; let output = Command::new("sudo").args(self.cmd).output()?;
Ok(String::from_utf8_lossy(&output.stdout).to_string()) Ok(String::from_utf8_lossy(&output.stdout).trim().to_string())
} }
} }

View File

@ -33,6 +33,17 @@ async fn create_schema() -> Result<SqliteQueryResult, sqlx::Error> {
name TEXT NOT NULL, name TEXT NOT NULL,
UNIQUE(name) UNIQUE(name)
); );
CREATE TABLE IF NOT EXISTS settings
(
id INTEGER PRIMARY KEY AUTOINCREMENT,
channel_name TEXT NOT NULL,
preview_url TEXT NOT NULL,
config_path TEXT NOT NULL,
extra_extensions TEXT NOT NULL,
timezone TEXT NOT NULL,
service TEXT NOT NULL,
UNIQUE(channel_name)
);
CREATE TABLE IF NOT EXISTS presets CREATE TABLE IF NOT EXISTS presets
( (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
@ -51,17 +62,6 @@ async fn create_schema() -> Result<SqliteQueryResult, sqlx::Error> {
FOREIGN KEY (channel_id) REFERENCES settings (id) ON UPDATE SET NULL ON DELETE SET NULL, FOREIGN KEY (channel_id) REFERENCES settings (id) ON UPDATE SET NULL ON DELETE SET NULL,
UNIQUE(name) UNIQUE(name)
); );
CREATE TABLE IF NOT EXISTS settings
(
id INTEGER PRIMARY KEY AUTOINCREMENT,
channel_name TEXT NOT NULL,
preview_url TEXT NOT NULL,
config_path TEXT NOT NULL,
extra_extensions TEXT NOT NULL,
timezone TEXT NOT NULL,
service TEXT NOT NULL,
UNIQUE(channel_name)
);
CREATE TABLE IF NOT EXISTS user CREATE TABLE IF NOT EXISTS user
( (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
@ -70,7 +70,9 @@ async fn create_schema() -> Result<SqliteQueryResult, sqlx::Error> {
password TEXT NOT NULL, password TEXT NOT NULL,
salt TEXT NOT NULL, salt TEXT NOT NULL,
role_id INTEGER NOT NULL DEFAULT 2, role_id INTEGER NOT NULL DEFAULT 2,
channel_id INTEGER NOT NULL DEFAULT 1,
FOREIGN KEY (role_id) REFERENCES roles (id) ON UPDATE SET NULL ON DELETE SET NULL, FOREIGN KEY (role_id) REFERENCES roles (id) ON UPDATE SET NULL ON DELETE SET NULL,
FOREIGN KEY (channel_id) REFERENCES settings (id) ON UPDATE SET NULL ON DELETE SET NULL,
UNIQUE(mail, username) UNIQUE(mail, username)
);"; );";
let result = sqlx::query(query).execute(&conn).await; let result = sqlx::query(query).execute(&conn).await;
@ -294,3 +296,12 @@ pub async fn db_add_preset(preset: TextPreset) -> Result<SqliteQueryResult, sqlx
Ok(result) Ok(result)
} }
pub async fn db_delete_preset(id: &i64) -> Result<SqliteQueryResult, sqlx::Error> {
let conn = db_connection().await?;
let query = "DELETE FROM presets WHERE id = $1;";
let result: SqliteQueryResult = sqlx::query(query).bind(id).execute(&conn).await?;
conn.close().await;
Ok(result)
}

View File

@ -159,6 +159,7 @@ pub async fn run_args(mut args: Args) -> Result<(), i32> {
password: args.password.unwrap(), password: args.password.unwrap(),
salt: None, salt: None,
role_id: Some(1), role_id: Some(1),
channel_id: Some(1),
token: None, token: None,
}; };

View File

@ -18,6 +18,9 @@ pub struct User {
#[serde(skip_serializing)] #[serde(skip_serializing)]
pub role_id: Option<i64>, pub role_id: Option<i64>,
#[sqlx(default)] #[sqlx(default)]
#[serde(skip_serializing)]
pub channel_id: Option<i64>,
#[sqlx(default)]
pub token: Option<String>, pub token: Option<String>,
} }
@ -42,7 +45,6 @@ pub struct TextPreset {
#[serde(skip_deserializing)] #[serde(skip_deserializing)]
pub id: i64, pub id: i64,
pub channel_id: i64, pub channel_id: i64,
#[serde(skip_deserializing)]
pub name: String, pub name: String,
pub text: String, pub text: String,
pub x: String, pub x: String,

View File

@ -1,3 +1,14 @@
/// ### Possible endpoints
///
/// Run the API thru the systemd service, or like:
///
/// ```BASH
/// ffpapi -l 127.0.0.1:8000
/// ```
///
/// For all endpoints an (Bearer) authentication is required.\
/// `{id}` represent the channel id, and at default is 1.
use std::collections::HashMap; use std::collections::HashMap;
use actix_multipart::Multipart; use actix_multipart::Multipart;
@ -21,6 +32,7 @@ use crate::utils::{
handles::{ handles::{
db_add_preset, db_add_user, db_get_all_settings, db_get_presets, db_get_settings, db_add_preset, db_add_user, db_get_all_settings, db_get_presets, db_get_settings,
db_get_user, db_login, db_role, db_update_preset, db_update_settings, db_update_user, db_get_user, db_login, db_role, db_update_preset, db_update_settings, db_update_user,
db_delete_preset,
}, },
models::{LoginUser, Settings, TextPreset, User}, models::{LoginUser, Settings, TextPreset, User},
playlist::{delete_playlist, generate_playlist, read_playlist, write_playlist}, playlist::{delete_playlist, generate_playlist, read_playlist, write_playlist},
@ -53,8 +65,24 @@ pub struct FileObj {
path: String, path: String,
} }
/// curl -X POST http://127.0.0.1:8080/auth/login/ -H "Content-Type: application/json" \ /// #### User Handling
/// -d '{"username": "<USER>", "password": "<PASS>" }' ///
/// **Login**
///
/// ```BASH
/// curl -X POST http://127.0.0.1:8000/auth/login/ -H "Content-Type: application/json" \
/// -d '{ "username": "<USER>", "password": "<PASS>" }'
/// ```
/// **Response:**
///
/// ```JSON
/// {
/// "id": 1,
/// "mail": "user@example.org",
/// "username": "<USER>",
/// "token": "<TOKEN>"
/// }
/// ```
#[post("/auth/login/")] #[post("/auth/login/")]
pub async fn login(credentials: web::Json<User>) -> impl Responder { pub async fn login(credentials: web::Json<User>) -> impl Responder {
match db_login(&credentials.username).await { match db_login(&credentials.username).await {
@ -107,8 +135,15 @@ pub async fn login(credentials: web::Json<User>) -> impl Responder {
} }
} }
/// curl -X GET 'http://localhost:8080/api/user' --header 'Content-Type: application/json' \ /// From here on all request **must** contain the authorization header:\
/// --header 'Authorization: Bearer <TOKEN>' /// `"Authorization: Bearer <TOKEN>"`
/// **Get current User**
///
/// ```BASH
/// curl -X GET 'http://localhost:8000/api/user' -H 'Content-Type: application/json' \
/// -H 'Authorization: Bearer <TOKEN>'
/// ```
#[get("/user")] #[get("/user")]
#[has_any_role("Role::Admin", "Role::User", type = "Role")] #[has_any_role("Role::Admin", "Role::User", type = "Role")]
async fn get_user(user: web::ReqData<LoginUser>) -> Result<impl Responder, ServiceError> { async fn get_user(user: web::ReqData<LoginUser>) -> Result<impl Responder, ServiceError> {
@ -121,8 +156,12 @@ async fn get_user(user: web::ReqData<LoginUser>) -> Result<impl Responder, Servi
} }
} }
/// curl -X PUT http://localhost:8080/api/user/1 --header 'Content-Type: application/json' \ /// **Update current User**
/// --data '{"mail": "<MAIL>", "password": "<PASS>"}' --header 'Authorization: <TOKEN>' ///
/// ```BASH
/// curl -X PUT http://localhost:8000/api/user/1 -H 'Content-Type: application/json' \
/// -d '{"mail": "<MAIL>", "password": "<PASS>"}' -H 'Authorization: <TOKEN>'
/// ```
#[put("/user/{id}")] #[put("/user/{id}")]
#[has_any_role("Role::Admin", "Role::User", type = "Role")] #[has_any_role("Role::Admin", "Role::User", type = "Role")]
async fn update_user( async fn update_user(
@ -160,9 +199,13 @@ async fn update_user(
Err(ServiceError::Unauthorized) Err(ServiceError::Unauthorized)
} }
/// curl -X POST 'http://localhost:8080/api/user/' --header 'Content-Type: application/json' \ /// **Add User**
/// -d '{"mail": "<MAIL>", "username": "<USER>", "password": "<PASS>", "role_id": 1}' \ ///
/// --header 'Authorization: Bearer <TOKEN>' /// ```BASH
/// curl -X POST 'http://localhost:8000/api/user/' -H 'Content-Type: application/json' \
/// -d '{"mail": "<MAIL>", "username": "<USER>", "password": "<PASS>", "role_id": 1, "channel_id": 1}' \
/// -H 'Authorization: Bearer <TOKEN>'
/// ```
#[post("/user/")] #[post("/user/")]
#[has_any_role("Role::Admin", type = "Role")] #[has_any_role("Role::Admin", type = "Role")]
async fn add_user(data: web::Json<User>) -> Result<impl Responder, ServiceError> { async fn add_user(data: web::Json<User>) -> Result<impl Responder, ServiceError> {
@ -175,7 +218,27 @@ async fn add_user(data: web::Json<User>) -> Result<impl Responder, ServiceError>
} }
} }
/// curl -X GET http://127.0.0.1:8080/api/settings/1 -H "Authorization: Bearer <TOKEN>" /// #### ffpapi Settings
///
/// **Get Settings**
///
/// ```BASH
/// curl -X GET http://127.0.0.1:8000/api/settings/1 -H "Authorization: Bearer <TOKEN>"
/// ```
///
/// **Response:**
///
/// ```JSON
/// {
/// "id": 1,
/// "channel_name": "Channel 1",
/// "preview_url": "http://localhost/live/preview.m3u8",
/// "config_path": "/etc/ffplayout/ffplayout.yml",
/// "extra_extensions": "jpg,jpeg,png",
/// "timezone": "UTC",
/// "service": "ffplayout.service"
/// }
/// ```
#[get("/settings/{id}")] #[get("/settings/{id}")]
#[has_any_role("Role::Admin", "Role::User", type = "Role")] #[has_any_role("Role::Admin", "Role::User", type = "Role")]
async fn get_settings(id: web::Path<i64>) -> Result<impl Responder, ServiceError> { async fn get_settings(id: web::Path<i64>) -> Result<impl Responder, ServiceError> {
@ -186,7 +249,11 @@ async fn get_settings(id: web::Path<i64>) -> Result<impl Responder, ServiceError
Err(ServiceError::InternalServerError) Err(ServiceError::InternalServerError)
} }
/// curl -X GET http://127.0.0.1:8080/api/settings -H "Authorization: Bearer <TOKEN>" /// **Get all Settings**
///
/// ```BASH
/// curl -X GET http://127.0.0.1:8000/api/settings -H "Authorization: Bearer <TOKEN>"
/// ```
#[get("/settings")] #[get("/settings")]
#[has_any_role("Role::Admin", type = "Role")] #[has_any_role("Role::Admin", type = "Role")]
async fn get_all_settings() -> Result<impl Responder, ServiceError> { async fn get_all_settings() -> Result<impl Responder, ServiceError> {
@ -197,10 +264,15 @@ async fn get_all_settings() -> Result<impl Responder, ServiceError> {
Err(ServiceError::InternalServerError) Err(ServiceError::InternalServerError)
} }
/// curl -X PATCH http://127.0.0.1:8080/api/settings/1 -H "Content-Type: application/json" \ /// **Update Settings**
/// --data '{"id":1,"channel_name":"Channel 1","preview_url":"http://localhost/live/stream.m3u8", \ ///
/// "config_path":"/etc/ffplayout/ffplayout.yml","extra_extensions":".jpg,.jpeg,.png"}' \ /// ```BASH
/// curl -X PATCH http://127.0.0.1:8000/api/settings/1 -H "Content-Type: application/json" \
/// -d '{ "id": 1, "channel_name": "Channel 1", "preview_url": "http://localhost/live/stream.m3u8", \
/// "config_path": "/etc/ffplayout/ffplayout.yml", "extra_extensions": "jpg,jpeg,png",
/// "role_id": 1, "channel_id": 1 }' \
/// -H "Authorization: Bearer <TOKEN>" /// -H "Authorization: Bearer <TOKEN>"
/// ```
#[patch("/settings/{id}")] #[patch("/settings/{id}")]
#[has_any_role("Role::Admin", type = "Role")] #[has_any_role("Role::Admin", type = "Role")]
async fn patch_settings( async fn patch_settings(
@ -214,7 +286,15 @@ async fn patch_settings(
Err(ServiceError::InternalServerError) Err(ServiceError::InternalServerError)
} }
/// curl -X GET http://localhost:8080/api/playout/config/1 --header 'Authorization: <TOKEN>' /// #### ffplayout Config
///
/// **Get Config**
///
/// ```BASH
/// curl -X GET http://localhost:8000/api/playout/config/1 -H 'Authorization: <TOKEN>'
/// ```
///
/// Response is a JSON object from the ffplayout.yml
#[get("/playout/config/{id}")] #[get("/playout/config/{id}")]
#[has_any_role("Role::Admin", "Role::User", type = "Role")] #[has_any_role("Role::Admin", "Role::User", type = "Role")]
async fn get_playout_config( async fn get_playout_config(
@ -230,8 +310,12 @@ async fn get_playout_config(
Err(ServiceError::InternalServerError) Err(ServiceError::InternalServerError)
} }
/// curl -X PUT http://localhost:8080/api/playout/config/1 -H "Content-Type: application/json" \ /// **Update Config**
/// --data { <CONFIG DATA> } --header 'Authorization: <TOKEN>' ///
/// ```BASH
/// curl -X PUT http://localhost:8000/api/playout/config/1 -H "Content-Type: application/json" \
/// -d { <CONFIG DATA> } -H 'Authorization: <TOKEN>'
/// ```
#[put("/playout/config/{id}")] #[put("/playout/config/{id}")]
#[has_any_role("Role::Admin", type = "Role")] #[has_any_role("Role::Admin", type = "Role")]
async fn update_playout_config( async fn update_playout_config(
@ -255,8 +339,16 @@ async fn update_playout_config(
Err(ServiceError::InternalServerError) Err(ServiceError::InternalServerError)
} }
/// curl -X GET http://localhost:8080/api/presets/ --header 'Content-Type: application/json' \ /// #### Text Presets
/// --data '{"mail": "<MAIL>", "password": "<PASS>"}' --header 'Authorization: <TOKEN>' ///
/// Text presets are made for sending text messages to the ffplayout engine, to overlay them as a lower third.
///
/// **Get all Presets**
///
/// ```BASH
/// curl -X GET http://localhost:8000/api/presets/ -H 'Content-Type: application/json' \
/// -H 'Authorization: <TOKEN>'
/// ```
#[get("/presets/{id}")] #[get("/presets/{id}")]
#[has_any_role("Role::Admin", "Role::User", type = "Role")] #[has_any_role("Role::Admin", "Role::User", type = "Role")]
async fn get_presets(id: web::Path<i64>) -> Result<impl Responder, ServiceError> { async fn get_presets(id: web::Path<i64>) -> Result<impl Responder, ServiceError> {
@ -267,10 +359,14 @@ async fn get_presets(id: web::Path<i64>) -> Result<impl Responder, ServiceError>
Err(ServiceError::InternalServerError) Err(ServiceError::InternalServerError)
} }
/// curl -X PUT http://localhost:8080/api/presets/1 --header 'Content-Type: application/json' \ /// **Update Preset**
/// --data '{"name": "<PRESET NAME>", "text": "<TEXT>", "x": "<X>", "y": "<Y>", "fontsize": 24, \ ///
/// "line_spacing": 4, "fontcolor": "#ffffff", "box": 1, "boxcolor": "#000000", "boxborderw": 4, "alpha": 1.0}' \ /// ```BASH
/// --header 'Authorization: <TOKEN>' /// curl -X PUT http://localhost:8000/api/presets/1 -H 'Content-Type: application/json' \
/// -d '{ "name": "<PRESET NAME>", "text": "<TEXT>", "x": "<X>", "y": "<Y>", "fontsize": 24, \
/// "line_spacing": 4, "fontcolor": "#ffffff", "box": 1, "boxcolor": "#000000", "boxborderw": 4, "alpha": 1.0, "channel_id": 1 }' \
/// -H 'Authorization: <TOKEN>'
/// ```
#[put("/presets/{id}")] #[put("/presets/{id}")]
#[has_any_role("Role::Admin", "Role::User", type = "Role")] #[has_any_role("Role::Admin", "Role::User", type = "Role")]
async fn update_preset( async fn update_preset(
@ -284,10 +380,14 @@ async fn update_preset(
Err(ServiceError::InternalServerError) Err(ServiceError::InternalServerError)
} }
/// curl -X POST http://localhost:8080/api/presets/ --header 'Content-Type: application/json' \ /// **Add new Preset**
/// --data '{"name": "<PRESET NAME>", "text": "TEXT>", "x": "<X>", "y": "<Y>", "fontsize": 24, \ ///
/// "line_spacing": 4, "fontcolor": "#ffffff", "box": 1, "boxcolor": "#000000", "boxborderw": 4, "alpha": 1.0}}' \ /// ```BASH
/// --header 'Authorization: <TOKEN>' /// curl -X POST http://localhost:8000/api/presets/ -H 'Content-Type: application/json' \
/// -d '{ "name": "<PRESET NAME>", "text": "TEXT>", "x": "<X>", "y": "<Y>", "fontsize": 24, \
/// "line_spacing": 4, "fontcolor": "#ffffff", "box": 1, "boxcolor": "#000000", "boxborderw": 4, "alpha": 1.0, "channel_id": 1 }' \
/// -H 'Authorization: <TOKEN>'
/// ```
#[post("/presets/")] #[post("/presets/")]
#[has_any_role("Role::Admin", "Role::User", type = "Role")] #[has_any_role("Role::Admin", "Role::User", type = "Role")]
async fn add_preset(data: web::Json<TextPreset>) -> Result<impl Responder, ServiceError> { async fn add_preset(data: web::Json<TextPreset>) -> Result<impl Responder, ServiceError> {
@ -298,21 +398,39 @@ async fn add_preset(data: web::Json<TextPreset>) -> Result<impl Responder, Servi
Err(ServiceError::InternalServerError) Err(ServiceError::InternalServerError)
} }
/// ---------------------------------------------------------------------------- /// **Delete Preset**
/// ffplayout process controlling ///
/// ```BASH
/// curl -X DELETE http://localhost:8000/api/presets/1 -H 'Content-Type: application/json' \
/// -H 'Authorization: <TOKEN>'
/// ```
#[delete("/presets/{id}")]
#[has_any_role("Role::Admin", "Role::User", type = "Role")]
async fn delete_preset(id: web::Path<i64>) -> Result<impl Responder, ServiceError> {
if db_delete_preset(&id).await.is_ok() {
return Ok("Delete preset Success");
}
Err(ServiceError::InternalServerError)
}
/// ### ffplayout controlling
/// ///
/// here we communicate with the engine for: /// here we communicate with the engine for:
/// - jump to last or next clip /// - jump to last or next clip
/// - reset playlist state /// - reset playlist state
/// - get infos about current, next, last clip /// - get infos about current, next, last clip
/// - send text the the engine, for overlaying it (as lower third etc.) /// - send text to the engine, for overlaying it (as lower third etc.)
/// ---------------------------------------------------------------------------- ///
/// **Send Text to ffplayout**
/// curl -X POST http://localhost:8080/api/control/1/text/ \ ///
/// --header 'Content-Type: application/json' --header 'Authorization: <TOKEN>' \ /// ```BASH
/// --data '{"text": "Hello from ffplayout", "x": "(w-text_w)/2", "y": "(h-text_h)/2", \ /// curl -X POST http://localhost:8000/api/control/1/text/ \
/// -H 'Content-Type: application/json' -H 'Authorization: <TOKEN>' \
/// -d '{"text": "Hello from ffplayout", "x": "(w-text_w)/2", "y": "(h-text_h)/2", \
/// "fontsize": "24", "line_spacing": "4", "fontcolor": "#ffffff", "box": "1", \ /// "fontsize": "24", "line_spacing": "4", "fontcolor": "#ffffff", "box": "1", \
/// "boxcolor": "#000000", "boxborderw": "4", "alpha": "1.0"}' /// "boxcolor": "#000000", "boxborderw": "4", "alpha": "1.0"}'
/// ```
#[post("/control/{id}/text/")] #[post("/control/{id}/text/")]
#[has_any_role("Role::Admin", "Role::User", type = "Role")] #[has_any_role("Role::Admin", "Role::User", type = "Role")]
pub async fn send_text_message( pub async fn send_text_message(
@ -325,41 +443,55 @@ pub async fn send_text_message(
} }
} }
/// curl -X POST http://localhost:8080/api/control/1/playout/next/ /// **Control Playout**
/// --header 'Content-Type: application/json' --header 'Authorization: <TOKEN>' ///
#[post("/control/{id}/playout/next/")] /// - next
/// - back
/// - reset
///
/// ```BASH
/// curl -X POST http://localhost:8000/api/control/1/playout/next/ -H 'Content-Type: application/json'
/// -d '{ "command": "reset" }' -H 'Authorization: <TOKEN>'
/// ```
#[post("/control/{id}/playout/")]
#[has_any_role("Role::Admin", "Role::User", type = "Role")] #[has_any_role("Role::Admin", "Role::User", type = "Role")]
pub async fn jump_to_next(id: web::Path<i64>) -> Result<impl Responder, ServiceError> { pub async fn control_playout(id: web::Path<i64>, control: web::Json<Process>) -> Result<impl Responder, ServiceError> {
match control_state(*id, "next".into()).await { match control_state(*id, control.command.clone()).await {
Ok(res) => return Ok(res.text().await.unwrap_or_else(|_| "Success".into())), Ok(res) => return Ok(res.text().await.unwrap_or_else(|_| "Success".into())),
Err(e) => Err(e), Err(e) => Err(e),
} }
} }
/// curl -X POST http://localhost:8080/api/control/1/playout/back/ /// **Get current Clip**
/// --header 'Content-Type: application/json' --header 'Authorization: <TOKEN>' ///
#[post("/control/{id}/playout/back/")] /// ```BASH
#[has_any_role("Role::Admin", "Role::User", type = "Role")] /// curl -X GET http://localhost:8000/api/control/1/media/current
pub async fn jump_to_last(id: web::Path<i64>) -> Result<impl Responder, ServiceError> { /// -H 'Content-Type: application/json' -H 'Authorization: <TOKEN>'
match control_state(*id, "back".into()).await { /// ```
Ok(res) => return Ok(res.text().await.unwrap_or_else(|_| "Success".into())), ///
Err(e) => Err(e), /// **Response:**
} ///
} /// ```JSON
/// {
/// curl -X POST http://localhost:8080/api/control/1/playout/reset/ /// "jsonrpc": "2.0",
/// --header 'Content-Type: application/json' --header 'Authorization: <TOKEN>' /// "result": {
#[post("/control/{id}/playout/reset/")] /// "current_media": {
#[has_any_role("Role::Admin", "Role::User", type = "Role")] /// "category": "",
pub async fn reset_playout(id: web::Path<i64>) -> Result<impl Responder, ServiceError> { /// "duration": 154.2,
match control_state(*id, "reset".into()).await { /// "out": 154.2,
Ok(res) => return Ok(res.text().await.unwrap_or_else(|_| "Success".into())), /// "seek": 0.0,
Err(e) => Err(e), /// "source": "/opt/tv-media/clip.mp4"
} /// },
} /// "index": 39,
/// "play_mode": "playlist",
/// curl -X GET http://localhost:8080/api/control/1/media/current/ /// "played_sec": 67.80771999300123,
/// --header 'Content-Type: application/json' --header 'Authorization: <TOKEN>' /// "remaining_sec": 86.39228000699876,
/// "start_sec": 24713.631999999998,
/// "start_time": "06:51:53.631"
/// },
/// "id": 1
/// }
/// ```
#[get("/control/{id}/media/current")] #[get("/control/{id}/media/current")]
#[has_any_role("Role::Admin", "Role::User", type = "Role")] #[has_any_role("Role::Admin", "Role::User", type = "Role")]
pub async fn media_current(id: web::Path<i64>) -> Result<impl Responder, ServiceError> { pub async fn media_current(id: web::Path<i64>) -> Result<impl Responder, ServiceError> {
@ -369,8 +501,11 @@ pub async fn media_current(id: web::Path<i64>) -> Result<impl Responder, Service
} }
} }
/// curl -X GET http://localhost:8080/api/control/1/media/next/ /// **Get next Clip**
/// --header 'Content-Type: application/json' --header 'Authorization: <TOKEN>' ///
/// ```BASH
/// curl -X GET http://localhost:8000/api/control/1/media/next/ -H 'Authorization: <TOKEN>'
/// ```
#[get("/control/{id}/media/next")] #[get("/control/{id}/media/next")]
#[has_any_role("Role::Admin", "Role::User", type = "Role")] #[has_any_role("Role::Admin", "Role::User", type = "Role")]
pub async fn media_next(id: web::Path<i64>) -> Result<impl Responder, ServiceError> { pub async fn media_next(id: web::Path<i64>) -> Result<impl Responder, ServiceError> {
@ -380,8 +515,12 @@ pub async fn media_next(id: web::Path<i64>) -> Result<impl Responder, ServiceErr
} }
} }
/// curl -X GET http://localhost:8080/api/control/1/media/last/ /// **Get last Clip**
/// --header 'Content-Type: application/json' --header 'Authorization: <TOKEN>' ///
/// ```BASH
/// curl -X GET http://localhost:8000/api/control/1/media/last/
/// -H 'Content-Type: application/json' -H 'Authorization: <TOKEN>'
/// ```
#[get("/control/{id}/media/last")] #[get("/control/{id}/media/last")]
#[has_any_role("Role::Admin", "Role::User", type = "Role")] #[has_any_role("Role::Admin", "Role::User", type = "Role")]
pub async fn media_last(id: web::Path<i64>) -> Result<impl Responder, ServiceError> { pub async fn media_last(id: web::Path<i64>) -> Result<impl Responder, ServiceError> {
@ -391,9 +530,19 @@ pub async fn media_last(id: web::Path<i64>) -> Result<impl Responder, ServiceErr
} }
} }
/// curl -X GET http://localhost:8080/api/control/1/process/ /// #### ffplayout Process Control
/// --header 'Content-Type: application/json' --header 'Authorization: <TOKEN>' ///
/// Control ffplayout process, like:
/// - start
/// - stop
/// - restart
/// - status
///
/// ```BASH
/// curl -X POST http://localhost:8000/api/control/1/process/
/// -H 'Content-Type: application/json' -H 'Authorization: <TOKEN>'
/// -d '{"command": "start"}' /// -d '{"command": "start"}'
/// ```
#[post("/control/{id}/process/")] #[post("/control/{id}/process/")]
#[has_any_role("Role::Admin", "Role::User", type = "Role")] #[has_any_role("Role::Admin", "Role::User", type = "Role")]
pub async fn process_control( pub async fn process_control(
@ -403,13 +552,14 @@ pub async fn process_control(
control_service(*id, &proc.command).await control_service(*id, &proc.command).await
} }
/// ---------------------------------------------------------------------------- /// #### ffplayout Playlist Operations
/// ffplayout playlist operations
/// ///
/// ---------------------------------------------------------------------------- /// **Get playlist**
///
/// curl -X GET http://localhost:8080/api/playlist/1?date=2022-06-20 /// ```BASH
/// --header 'Content-Type: application/json' --header 'Authorization: <TOKEN>' /// curl -X GET http://localhost:8000/api/playlist/1?date=2022-06-20
/// -H 'Content-Type: application/json' -H 'Authorization: <TOKEN>'
/// ```
#[get("/playlist/{id}")] #[get("/playlist/{id}")]
#[has_any_role("Role::Admin", "Role::User", type = "Role")] #[has_any_role("Role::Admin", "Role::User", type = "Role")]
pub async fn get_playlist( pub async fn get_playlist(
@ -422,9 +572,13 @@ pub async fn get_playlist(
} }
} }
/// curl -X POST http://localhost:8080/api/playlist/1/ /// **Save playlist**
/// --header 'Content-Type: application/json' --header 'Authorization: <TOKEN>' ///
/// ```BASH
/// curl -X POST http://localhost:8000/api/playlist/1/
/// -H 'Content-Type: application/json' -H 'Authorization: <TOKEN>'
/// -- data "{<JSON playlist data>}" /// -- data "{<JSON playlist data>}"
/// ```
#[post("/playlist/{id}/")] #[post("/playlist/{id}/")]
#[has_any_role("Role::Admin", "Role::User", type = "Role")] #[has_any_role("Role::Admin", "Role::User", type = "Role")]
pub async fn save_playlist( pub async fn save_playlist(
@ -437,8 +591,14 @@ pub async fn save_playlist(
} }
} }
/// curl -X GET http://localhost:8080/api/playlist/1/generate/2022-06-20 /// **Generate Playlist**
/// --header 'Content-Type: application/json' --header 'Authorization: <TOKEN>' ///
/// A new playlist will be generated and response.
///
/// ```BASH
/// curl -X GET http://localhost:8000/api/playlist/1/generate/2022-06-20
/// -H 'Content-Type: application/json' -H 'Authorization: <TOKEN>'
/// ```
#[get("/playlist/{id}/generate/{date}")] #[get("/playlist/{id}/generate/{date}")]
#[has_any_role("Role::Admin", "Role::User", type = "Role")] #[has_any_role("Role::Admin", "Role::User", type = "Role")]
pub async fn gen_playlist( pub async fn gen_playlist(
@ -450,8 +610,12 @@ pub async fn gen_playlist(
} }
} }
/// curl -X DELETE http://localhost:8080/api/playlist/1/2022-06-20 /// **Delete Playlist**
/// --header 'Content-Type: application/json' --header 'Authorization: <TOKEN>' ///
/// ```BASH
/// curl -X DELETE http://localhost:8000/api/playlist/1/2022-06-20
/// -H 'Content-Type: application/json' -H 'Authorization: <TOKEN>'
/// ```
#[delete("/playlist/{id}/{date}")] #[delete("/playlist/{id}/{date}")]
#[has_any_role("Role::Admin", "Role::User", type = "Role")] #[has_any_role("Role::Admin", "Role::User", type = "Role")]
pub async fn del_playlist( pub async fn del_playlist(
@ -463,11 +627,14 @@ pub async fn del_playlist(
} }
} }
/// ---------------------------------------------------------------------------- /// ### Log file
/// read log file
/// ///
/// ---------------------------------------------------------------------------- /// **Read Log Life**
///
/// ```BASH
/// curl -X Get http://localhost:8000/api/log/1
/// -H 'Content-Type: application/json' -H 'Authorization: <TOKEN>'
/// ```
#[get("/log/{id}")] #[get("/log/{id}")]
#[has_any_role("Role::Admin", "Role::User", type = "Role")] #[has_any_role("Role::Admin", "Role::User", type = "Role")]
pub async fn get_log( pub async fn get_log(
@ -477,13 +644,14 @@ pub async fn get_log(
read_log_file(&id, &log.date).await read_log_file(&id, &log.date).await
} }
/// ---------------------------------------------------------------------------- /// ### File Operations
/// file operations
/// ///
/// ---------------------------------------------------------------------------- /// **Get File/Folder List**
///
/// curl -X GET http://localhost:8080/api/file/1/browse/ /// ```BASH
/// --header 'Content-Type: application/json' --header 'Authorization: <TOKEN>' /// curl -X POST http://localhost:8000/api/file/1/browse/ -H 'Content-Type: application/json'
/// -d '{ "source": "/" }' -H 'Authorization: <TOKEN>'
/// ```
#[post("/file/{id}/browse/")] #[post("/file/{id}/browse/")]
#[has_any_role("Role::Admin", "Role::User", type = "Role")] #[has_any_role("Role::Admin", "Role::User", type = "Role")]
pub async fn file_browser( pub async fn file_browser(
@ -496,9 +664,12 @@ pub async fn file_browser(
} }
} }
/// curl -X POST http://localhost:8080/api/file/1/create-folder/ /// **Create Folder**
/// --header 'Content-Type: application/json' --header 'Authorization: <TOKEN>' ///
/// -d '{"source": "<FOLDER PATH>"}' /// ```BASH
/// curl -X POST http://localhost:8000/api/file/1/create-folder/ -H 'Content-Type: application/json'
/// -d '{"source": "<FOLDER PATH>"}' -H 'Authorization: <TOKEN>'
/// ```
#[post("/file/{id}/create-folder/")] #[post("/file/{id}/create-folder/")]
#[has_any_role("Role::Admin", "Role::User", type = "Role")] #[has_any_role("Role::Admin", "Role::User", type = "Role")]
pub async fn add_dir( pub async fn add_dir(
@ -508,9 +679,12 @@ pub async fn add_dir(
create_directory(*id, &data.into_inner()).await create_directory(*id, &data.into_inner()).await
} }
/// curl -X POST http://localhost:8080/api/file/1/move/ /// **Rename File**
/// --header 'Content-Type: application/json' --header 'Authorization: <TOKEN>' ///
/// -d '{"source": "<SOURCE>", "target": "<TARGET>"}' /// ```BASH
/// curl -X POST http://localhost:8000/api/file/1/rename/ -H 'Content-Type: application/json'
/// -d '{"source": "<SOURCE>", "target": "<TARGET>"}' -H 'Authorization: <TOKEN>'
/// ```
#[post("/file/{id}/rename/")] #[post("/file/{id}/rename/")]
#[has_any_role("Role::Admin", "Role::User", type = "Role")] #[has_any_role("Role::Admin", "Role::User", type = "Role")]
pub async fn move_rename( pub async fn move_rename(
@ -523,9 +697,12 @@ pub async fn move_rename(
} }
} }
/// curl -X POST http://localhost:8080/api/file/1/remove/ /// **Remove File/Folder**
/// --header 'Content-Type: application/json' --header 'Authorization: <TOKEN>' ///
/// -d '{"source": "<SOURCE>"}' /// ```BASH
/// curl -X POST http://localhost:8000/api/file/1/remove/ -H 'Content-Type: application/json'
/// -d '{"source": "<SOURCE>"}' -H 'Authorization: <TOKEN>'
/// ```
#[post("/file/{id}/remove/")] #[post("/file/{id}/remove/")]
#[has_any_role("Role::Admin", "Role::User", type = "Role")] #[has_any_role("Role::Admin", "Role::User", type = "Role")]
pub async fn remove( pub async fn remove(
@ -538,6 +715,12 @@ pub async fn remove(
} }
} }
/// **Upload File**
///
/// ```BASH
/// curl -X POST http://localhost:8000/api/file/1/upload/ -H 'Authorization: <TOKEN>'
/// -F "file=@file.mp4"
/// ```
#[put("/file/{id}/upload/")] #[put("/file/{id}/upload/")]
#[has_any_role("Role::Admin", "Role::User", type = "Role")] #[has_any_role("Role::Admin", "Role::User", type = "Role")]
async fn save_file( async fn save_file(

23
scripts/gen_doc.sh Executable file
View File

@ -0,0 +1,23 @@
#!/usr/bin/bash
input=$1
output=$2
print_block=false
if [ ! "$input" ] || [ ! "$output" ]; then
echo "Run script like: den_doc.sh input.rs output.md"
fi
:> "$output"
while IFS= read -r line; do
if echo $line | grep -Eq "^///"; then
echo "$line" | sed -E "s|^/// ?||g" >> "$output"
print_block=true
fi
if [ -z "$line" ] && [[ $print_block == true ]]; then
echo "" >> "$output"
print_block=false
fi
done < "$input"