Add delete operation to Discord wrapper
This commit is contained in:
parent
d7e68e827e
commit
c58db54696
|
@ -1,12 +1,16 @@
|
||||||
use crate::Bytes;
|
use crate::Bytes;
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use log::debug;
|
use log::{debug, trace, warn};
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use reqwest::header::HeaderMap;
|
use reqwest::header::HeaderMap;
|
||||||
use reqwest::multipart::{Form, Part};
|
use reqwest::multipart::{Form, Part};
|
||||||
use reqwest::{Body, Client, IntoUrl};
|
use reqwest::{Body, Client, IntoUrl, StatusCode};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
use std::time::Duration;
|
||||||
|
use tokio::time::sleep;
|
||||||
|
|
||||||
|
// note: only delete has rate-limit handling
|
||||||
|
|
||||||
static CLIENT: OnceCell<Client> = OnceCell::new();
|
static CLIENT: OnceCell<Client> = OnceCell::new();
|
||||||
|
|
||||||
|
@ -14,21 +18,22 @@ pub async fn upload_webhook<T: Into<Body>>(
|
||||||
webhook: &str,
|
webhook: &str,
|
||||||
file: T,
|
file: T,
|
||||||
filename: &str,
|
filename: &str,
|
||||||
) -> anyhow::Result<String> {
|
) -> anyhow::Result<(String, u64)> {
|
||||||
debug!("Uploading '{}' to Discord", filename);
|
debug!("Uploading '{}' to Discord", filename);
|
||||||
let client = CLIENT.get_or_init(Client::new);
|
let client = CLIENT.get_or_init(Client::new);
|
||||||
let form = Form::new().part("file", Part::stream(file).file_name(filename.to_string()));
|
let form = Form::new().part("file", Part::stream(file).file_name(filename.to_string()));
|
||||||
let req = client
|
let resp = client
|
||||||
.post(webhook)
|
.post(webhook)
|
||||||
.multipart(form)
|
.multipart(form)
|
||||||
.send()
|
.send()
|
||||||
.await?
|
.await?
|
||||||
.json::<Value>()
|
.json::<Value>()
|
||||||
.await?;
|
.await?;
|
||||||
if let Some(u) = req["attachments"][0]["url"].as_str() {
|
trace!("Received JSON from Discord: {}", resp);
|
||||||
Ok(u.into())
|
if let (Some(u), Some(i)) = (resp["attachments"][0]["url"].as_str(), resp["id"].as_str().and_then(|f| f.parse::<u64>().ok())) {
|
||||||
|
Ok((u.into(), i))
|
||||||
} else {
|
} else {
|
||||||
Err(anyhow!("Discord response didn't include the URL"))
|
Err(anyhow!("Discord response didn't include the URL or message ID"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,3 +72,33 @@ pub async fn get<U: IntoUrl + Display>(url: U) -> anyhow::Result<(u64, String, B
|
||||||
Err(anyhow!("Discord response didn't include the URL"))
|
Err(anyhow!("Discord response didn't include the URL"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn delete(webhook: &str, mid: u64) -> anyhow::Result<()> {
|
||||||
|
debug!("Deleting message with ID {}", mid);
|
||||||
|
let client = CLIENT.get_or_init(Client::new);
|
||||||
|
let resp = client.delete(format!("{}/messages/{}", webhook, mid)).send().await?;
|
||||||
|
if resp.status() != StatusCode::NO_CONTENT {
|
||||||
|
Err(anyhow!(resp.text().await?))
|
||||||
|
} else {
|
||||||
|
let rt_header = resp.headers()
|
||||||
|
.get("X-RateLimit-Remaining")
|
||||||
|
.and_then(|v| v.to_str().ok()?.parse::<u64>().ok())
|
||||||
|
.and_then(|v| {
|
||||||
|
if v == 0 {
|
||||||
|
resp.headers()
|
||||||
|
.get("X-RateLimit-Reset-After")
|
||||||
|
.and_then(|v| v.to_str().ok()?.parse::<f64>().ok())
|
||||||
|
} else {
|
||||||
|
Some(0.0)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if let Some(rt) = rt_header {
|
||||||
|
if rt > 0.0 {
|
||||||
|
sleep(Duration::from_secs_f64(rt)).await;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warn!("Couldn't await the rate-limit, because there was a problem with the rate-limit header in Discord's response")
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
Reference in a new issue