Compare commits

...

6 Commits

Author SHA1 Message Date
Emma Tebibyte 132d82680b Merge pull request 'Fix error when no facets are specifed' (#16) from BlankParenthesis/hopper:fix-filter into main
Reviewed-on: minecrust/hopper#16
2022-12-24 04:06:21 +00:00
Emma Tebibyte 5ae5aa668d Merge pull request 'Implement Error parsing for API responses' (#18) from BlankParenthesis/hopper:handle-status-errors into main
fixes #20
2022-12-24 03:56:06 +00:00
Emma Tebibyte 3c87609720 Merge pull request 'Add User-Agent to requests' (#17) from BlankParenthesis/hopper:add-user-agent into main
Reviewed-on: minecrust/hopper#17
2022-12-24 03:47:48 +00:00
[ ] 552d75cbff Implement Error parsing for API responses 2022-12-09 06:01:37 +00:00
[ ] 9064888265 Add User-Agent to requests
Modrinth strongly encourages (via the following response header) that
access to their services be done with a uniquely identifying user-agent
string.

> "x-user-agent-notice": "!!!!! Hey, you! Yes, **you**! You need to
> change your User-Agent ASAP or you may be blocked from using
> Modrinth's services! For more information see the documentation:
> https://docs.modrinth.com/api-spec/#section/User-Agents !!!!!"

The one added here follows the documentation recommendation for the
"best" example of a user-agent string.
2022-12-09 05:13:43 +00:00
[ ] f7ba63b492 Fix error when no facets are specifed
The Modrinth API seemingly doesn't support an empty list for the facets
parameter. This solution simply skips adding that paremeter if it is
empty.
2022-12-09 04:18:15 +00:00
2 changed files with 48 additions and 16 deletions

View File

@ -1,6 +1,6 @@
use console::style;
use serde::Deserialize;
use std::collections::HashMap;
use std::{collections::HashMap, fmt};
#[derive(Deserialize, Debug)]
pub struct SearchResponse {
@ -140,3 +140,17 @@ pub struct ModVersionFile {
pub primary: bool,
pub size: isize,
}
#[derive(Deserialize, Debug)]
pub struct Error {
pub error: String,
pub description: String,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}: {}", self.error, self.description)
}
}
impl std::error::Error for Error {}

View File

@ -1,4 +1,4 @@
use crate::api::{ModInfo, ModResult, ModVersion, ModVersionFile, SearchResponse};
use crate::api::{ModInfo, ModResult, ModVersion, ModVersionFile, SearchResponse, Error as APIError};
use crate::config::{Args, Config, PackageType, SearchArgs};
use futures_util::StreamExt;
use log::*;
@ -14,7 +14,10 @@ impl HopperClient {
pub fn new(config: Config) -> Self {
Self {
config: config,
client: reqwest::Client::new(),
client: reqwest::ClientBuilder::new()
.user_agent(format!("tebibytemedia/hopper/{} (tebibyte.media)", env!("CARGO_PKG_VERSION")))
.build()
.unwrap(),
}
}
@ -51,18 +54,20 @@ impl HopperClient {
.to_string();
facets.push(package_type_facet);
}
params.push(("facets", format!("[{}]", facets.join(","))));
if !facets.is_empty() {
params.push(("facets", format!("[{}]", facets.join(","))));
}
let url = reqwest::Url::parse_with_params(url.as_str(), &params)?;
info!("GET {}", url);
let response = self
.client
.get(url)
.send()
.await?
.json::<SearchResponse>()
.await?;
Ok(response)
let response = self.client.get(url).send().await?;
if response.status().is_success() {
Ok(response.json::<SearchResponse>().await?)
} else {
Err(response.json::<APIError>().await?.into())
}
}
pub async fn fetch_mod_info(&self, mod_result: &ModResult) -> anyhow::Result<ModInfo> {
@ -78,8 +83,12 @@ impl HopperClient {
);
info!("GET {}", url);
let response = self.client.get(url).send().await?;
let response = response.json::<ModInfo>().await?;
Ok(response)
if response.status().is_success() {
Ok(response.json::<ModInfo>().await?)
} else {
Err(response.json::<APIError>().await?.into())
}
}
pub async fn fetch_mod_version(&self, version_id: &String) -> anyhow::Result<ModVersion> {
@ -91,8 +100,12 @@ impl HopperClient {
);
info!("GET {}", url);
let response = self.client.get(url).send().await?;
let response = response.json::<ModVersion>().await?;
Ok(response)
if response.status().is_success() {
Ok(response.json::<ModVersion>().await?)
} else {
Err(response.json::<APIError>().await?.into())
}
}
pub async fn download_version_file(
@ -119,6 +132,11 @@ impl HopperClient {
let url = &file.url;
info!("GET {}", url);
let response = self.client.get(url).send().await?;
if !response.status().is_success() {
return Err(response.json::<APIError>().await?.into())
}
let total_size = response.content_length().unwrap();
// TODO better colors and styling!