use humantime::format_duration;
use std::time::SystemTime;
use windmark::response::Response;
#[derive(Debug)]
pub enum Error {
NetworkFailure,
ResourceNotFound,
Restricted,
Throttled(Option<SystemTime>),
Unauthorized,
UnexpectedResponse,
}
impl core::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::NetworkFailure => write!(f, "Failed to communicate with the git forge"),
Self::ResourceNotFound => write!(f, "The requested resource was not found"),
Self::Restricted => write!(f, "The forge has asked us not to go here"),
Self::Throttled(None) => {
writeln!(f, "The forge asked us to wait a while before trying again")
}
Self::Throttled(Some(retry_after)) => {
match retry_after.duration_since(SystemTime::now()) {
Err(_) => writeln!(f, "The forge asked us to wait a while before trying again"),
Ok(remaining) => writeln!(
f,
"The forge asked us to wait another {} before trying again",
format_duration(remaining)
),
}
}
Self::Unauthorized => write!(
f,
"We are not authorized to access the upstream; make sure FORGE_SECRET_KEY is set"
),
Self::UnexpectedResponse => {
write!(
f,
"Can't understand the response from the upstream; is FORGE_TYPE set correctly?"
)
}
}
}
}
impl Error {
pub fn gemini_response(&self) -> Response {
match self {
Self::NetworkFailure => Response::proxy_error("Couldn't communicate with the forge"),
Self::ResourceNotFound | Self::Unauthorized => Response::not_found("Not found"),
Self::Restricted => Response::proxy_refused(format!("{self}")),
Self::Throttled(_) => Response::temporary_failure(format!("{self}")),
Self::UnexpectedResponse => {
Response::temporary_failure("The upstream gave us a response we don't understand")
}
}
}
}
impl std::error::Error for Error {}