This repository has been archived on 2022-03-12. You can view files and clone it, but cannot push or open issues or pull requests.
xuproxy/src/discord.rs

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"))
}
}