70 lines
2.1 KiB
Rust
70 lines
2.1 KiB
Rust
use crate::Bytes;
|
|
use anyhow::anyhow;
|
|
use log::debug;
|
|
use once_cell::sync::OnceCell;
|
|
use reqwest::header::HeaderMap;
|
|
use reqwest::multipart::{Form, Part};
|
|
use reqwest::{Body, Client, IntoUrl};
|
|
use serde_json::Value;
|
|
use std::fmt::Display;
|
|
|
|
static CLIENT: OnceCell<Client> = OnceCell::new();
|
|
|
|
pub async fn upload_webhook<T: Into<Body>>(
|
|
webhook: &str,
|
|
file: T,
|
|
filename: &str,
|
|
) -> anyhow::Result<String> {
|
|
debug!("Uploading '{}' to Discord", filename);
|
|
let client = CLIENT.get_or_init(Client::new);
|
|
let form = Form::new().part("file", Part::stream(file).file_name(filename.to_string()));
|
|
let req = client
|
|
.post(webhook)
|
|
.multipart(form)
|
|
.send()
|
|
.await?
|
|
.json::<Value>()
|
|
.await?;
|
|
if let Some(u) = req["attachments"][0]["url"].as_str() {
|
|
Ok(u.into())
|
|
} else {
|
|
Err(anyhow!("Discord response didn't include the URL"))
|
|
}
|
|
}
|
|
|
|
fn extract_headers(h: &HeaderMap) -> Option<(u64, String)> {
|
|
let content_length = h
|
|
.get("content-length")?
|
|
.to_str()
|
|
.ok()?
|
|
.parse::<u64>()
|
|
.ok()?;
|
|
let mime = h.get("content-type")?.to_str().ok()?.to_string();
|
|
Some((content_length, mime))
|
|
}
|
|
|
|
pub async fn head<U: IntoUrl + Display>(url: U) -> anyhow::Result<(u64, String)> {
|
|
debug!("Downloading headers of '{}' from Discord", url);
|
|
let client = CLIENT.get_or_init(Client::new);
|
|
let resp = client.head(url).send().await?;
|
|
let headers = resp.headers();
|
|
if let Some(o) = extract_headers(headers) {
|
|
Ok(o)
|
|
} else {
|
|
Err(anyhow!("Discord response didn't include the URL"))
|
|
}
|
|
}
|
|
|
|
pub async fn get<U: IntoUrl + Display>(url: U) -> anyhow::Result<(u64, String, Bytes)> {
|
|
debug!("Downloading '{}' from Discord", url);
|
|
let client = CLIENT.get_or_init(Client::new);
|
|
let resp = client.get(url).send().await?;
|
|
let headers = extract_headers(resp.headers());
|
|
let bytes = resp.bytes().await?;
|
|
if let Some(o) = headers {
|
|
Ok((o.0, o.1, bytes))
|
|
} else {
|
|
Err(anyhow!("Discord response didn't include the URL"))
|
|
}
|
|
}
|