forked from torrust/torrust-index
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: [torrust#453] new console command
New console command to upload torrent to the Index remotely by using the API client. ```console cargo run --bin seeder -- --api-base-url <API_BASE_URL> --number-of-torrents <NUMBER_OF_TORRENTS> --user <USER> --password <PASSWORD> --interval <INTERVAL> ``` For example: ```console cargo run --bin seeder -- --api-base-url "localhost:3001" --number-of-torrents 1000 --user admin --password 12345678 --interval 0 ``` That command would upload 1000 random torrents to the Index using the user account `admin` with password `123456` and waiting `1` second between uploads.
- Loading branch information
1 parent
df3a9be
commit c94b566
Showing
8 changed files
with
242 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
//! Program to upload random torrents to a live Index API. | ||
use torrust_index::console::commands::seeder::app; | ||
|
||
fn main() -> anyhow::Result<()> { | ||
app::run() | ||
#[tokio::main] | ||
async fn main() -> anyhow::Result<()> { | ||
app::run().await | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
use crate::web::api::client::v1::client::Client; | ||
use crate::web::api::client::v1::contexts::category::forms::AddCategoryForm; | ||
use crate::web::api::client::v1::contexts::category::responses::{ListItem, ListResponse}; | ||
use crate::web::api::client::v1::contexts::torrent::forms::UploadTorrentMultipartForm; | ||
use crate::web::api::client::v1::contexts::torrent::responses::{UploadedTorrent, UploadedTorrentResponse}; | ||
use crate::web::api::client::v1::contexts::user::forms::LoginForm; | ||
use crate::web::api::client::v1::contexts::user::responses::{LoggedInUserData, SuccessfulLoginResponse}; | ||
use crate::web::api::client::v1::responses::TextResponse; | ||
|
||
use log::debug; | ||
use thiserror::Error; | ||
|
||
#[derive(Error, Debug)] | ||
pub enum Error { | ||
#[error("Torrent with the same info-hash already exist in the database")] | ||
TorrentInfoHashAlreadyExists, | ||
#[error("Torrent with the same title already exist in the database")] | ||
TorrentTitleAlreadyExists, | ||
} | ||
|
||
/// It uploads a torrent file to the Torrust Index. | ||
/// | ||
/// # Errors | ||
/// | ||
/// It returns an error if the torrent already exists in the database. | ||
/// | ||
/// # Panics | ||
/// | ||
/// Panics if the response body is not a valid JSON. | ||
pub async fn upload_torrent(client: &Client, upload_torrent_form: UploadTorrentMultipartForm) -> Result<UploadedTorrent, Error> { | ||
let categories = get_categories(client).await; | ||
|
||
if !contains_category_with_name(&categories, &upload_torrent_form.category) { | ||
add_category(client, &upload_torrent_form.category).await; | ||
} | ||
|
||
let response = client.upload_torrent(upload_torrent_form.into()).await; | ||
|
||
debug!("response: {}", response.status); | ||
|
||
if response.status == 400 { | ||
if response.body.contains("This torrent already exists in our database") { | ||
return Err(Error::TorrentInfoHashAlreadyExists); | ||
} | ||
|
||
if response.body.contains("This torrent title has already been used") { | ||
return Err(Error::TorrentTitleAlreadyExists); | ||
} | ||
} | ||
|
||
assert!(response.is_json_and_ok(), "Error uploading torrent: {}", response.body); | ||
|
||
let uploaded_torrent_response: UploadedTorrentResponse = | ||
serde_json::from_str(&response.body).expect("a valid JSON response should be returned from the Torrust Index API"); | ||
|
||
Ok(uploaded_torrent_response.data) | ||
} | ||
|
||
/// It logs in the user and returns the user data. | ||
/// | ||
/// # Panics | ||
/// | ||
/// Panics if the response body is not a valid JSON. | ||
pub async fn login(client: &Client, username: &str, password: &str) -> LoggedInUserData { | ||
let response = client | ||
.login_user(LoginForm { | ||
login: username.to_owned(), | ||
password: password.to_owned(), | ||
}) | ||
.await; | ||
|
||
let res: SuccessfulLoginResponse = serde_json::from_str(&response.body).unwrap_or_else(|_| { | ||
panic!( | ||
"a valid JSON response should be returned after login. Received: {}", | ||
response.body | ||
) | ||
}); | ||
|
||
res.data | ||
} | ||
|
||
/// It returns all the index categories. | ||
/// | ||
/// # Panics | ||
/// | ||
/// Panics if the response body is not a valid JSON. | ||
pub async fn get_categories(client: &Client) -> Vec<ListItem> { | ||
let response = client.get_categories().await; | ||
|
||
let res: ListResponse = serde_json::from_str(&response.body).unwrap(); | ||
|
||
res.data | ||
} | ||
|
||
/// It adds a new category. | ||
pub async fn add_category(client: &Client, name: &str) -> TextResponse { | ||
client | ||
.add_category(AddCategoryForm { | ||
name: name.to_owned(), | ||
icon: None, | ||
}) | ||
.await | ||
} | ||
|
||
/// It checks if the category list contains the given category. | ||
fn contains_category_with_name(items: &[ListItem], category_name: &str) -> bool { | ||
items.iter().any(|item| item.name == category_name) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
use log::{debug, LevelFilter}; | ||
|
||
/// # Panics | ||
/// | ||
/// | ||
pub fn setup(level: LevelFilter) { | ||
if let Err(_err) = fern::Dispatch::new() | ||
.format(|out, message, record| { | ||
out.finish(format_args!( | ||
"{} [{}][{}] {}", | ||
chrono::Local::now().format("%+"), | ||
record.target(), | ||
record.level(), | ||
message | ||
)); | ||
}) | ||
.level(level) | ||
.chain(std::io::stdout()) | ||
.apply() | ||
{ | ||
panic!("Failed to initialize logging.") | ||
} | ||
|
||
debug!("logging initialized."); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,3 @@ | ||
pub mod api; | ||
pub mod app; | ||
pub mod logging; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters