use serde::{Deserialize, Serialize};
use crate::types::{File, Snowflake, Sticker};
use super::{Body, BotClient, Response, Result, Transport, route::routes};
routes! {
GET_STICKER = Get "/stickers/{sticker_id}";
LIST_STICKER_PACKS = Get "/sticker-packs";
LIST_GUILD_STICKERS = Get "/guilds/{guild_id}/stickers";
GET_GUILD_STICKER = Get "/guilds/{guild_id}/stickers/{sticker_id}";
CREATE_GUILD_STICKER = Post "/guilds/{guild_id}/stickers";
MODIFY_GUILD_STICKER = Patch "/guilds/{guild_id}/stickers/{sticker_id}";
DELETE_GUILD_STICKER = Delete "/guilds/{guild_id}/stickers/{sticker_id}";
}
#[derive(Debug, Clone, Copy)]
pub struct CreateSticker<'a> {
pub name: &'a str,
pub description: &'a str,
pub tags: &'a str,
pub file: &'a File,
pub reason: Option<&'a str>,
}
#[derive(Debug, Clone, Copy, Default, Serialize)]
pub struct ModifySticker<'a> {
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<Option<&'a str>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tags: Option<&'a str>,
#[serde(skip)]
pub reason: Option<&'a str>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct StickerPack {
pub id: Snowflake,
pub stickers: Vec<Sticker>,
pub name: String,
pub sku_id: Snowflake,
pub cover_sticker_id: Option<Snowflake>,
pub description: String,
pub banner_asset_id: Option<Snowflake>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct StickerPacks {
pub sticker_packs: Vec<StickerPack>,
}
impl<T: Transport> BotClient<T> {
pub async fn get_sticker(&self, sticker_id: Snowflake) -> Result<Response<Sticker>> {
let url = self.rest.url(GET_STICKER, &[&sticker_id]);
self.rest.call(GET_STICKER, url, Body::NONE, None).await
}
pub async fn list_sticker_packs(&self) -> Result<Response<StickerPacks>> {
let url = self.rest.url(LIST_STICKER_PACKS, &[]);
self.rest
.call(LIST_STICKER_PACKS, url, Body::NONE, None)
.await
}
pub async fn list_guild_stickers(&self, guild_id: Snowflake) -> Result<Response<Vec<Sticker>>> {
let url = self.rest.url(LIST_GUILD_STICKERS, &[&guild_id]);
self.rest
.call(LIST_GUILD_STICKERS, url, Body::NONE, None)
.await
}
pub async fn get_guild_sticker(
&self,
guild_id: Snowflake,
sticker_id: Snowflake,
) -> Result<Response<Sticker>> {
let url = self.rest.url(GET_GUILD_STICKER, &[&guild_id, &sticker_id]);
self.rest
.call(GET_GUILD_STICKER, url, Body::NONE, None)
.await
}
pub async fn create_guild_sticker(
&self,
guild_id: Snowflake,
sticker: &CreateSticker<'_>,
) -> Result<Response<Sticker>> {
let url = self.rest.url(CREATE_GUILD_STICKER, &[&guild_id]);
let fields = [
("name", sticker.name),
("description", sticker.description),
("tags", sticker.tags),
];
self.rest
.call(
CREATE_GUILD_STICKER,
url,
Body::<()>::Form(&fields, sticker.file),
sticker.reason,
)
.await
}
pub async fn modify_guild_sticker(
&self,
guild_id: Snowflake,
sticker_id: Snowflake,
sticker: &ModifySticker<'_>,
) -> Result<Response<Sticker>> {
let url = self
.rest
.url(MODIFY_GUILD_STICKER, &[&guild_id, &sticker_id]);
self.rest
.call(
MODIFY_GUILD_STICKER,
url,
Body::Json(sticker),
sticker.reason,
)
.await
}
pub async fn delete_guild_sticker(
&self,
guild_id: Snowflake,
sticker_id: Snowflake,
reason: Option<&str>,
) -> Result<()> {
let url = self
.rest
.url(DELETE_GUILD_STICKER, &[&guild_id, &sticker_id]);
self.rest
.call_empty(DELETE_GUILD_STICKER, url, Body::NONE, reason)
.await
}
}
#[cfg(test)]
mod tests {
use futures::executor::block_on;
use serde_json::json;
use super::super::{Method::*, testing::MockTransport};
use super::*;
#[test]
fn routes() {
let c = BotClient::new(MockTransport::default(), "t", Snowflake::from_u64(1));
let (g, s) = (Snowflake::from_u64(5), Snowflake::from_u64(6));
let file = File::new("wave.png", b"PNG".to_vec()).content_type("image/png");
block_on(c.get_sticker(s)).unwrap();
block_on(c.list_sticker_packs()).unwrap();
block_on(c.list_guild_stickers(g)).unwrap();
block_on(c.get_guild_sticker(g, s)).unwrap();
block_on(c.create_guild_sticker(
g,
&CreateSticker {
name: "wave",
description: "hi",
tags: "wave",
file: &file,
reason: Some("fun"),
},
))
.unwrap();
block_on(c.modify_guild_sticker(
g,
s,
&ModifySticker {
description: Some(None),
..Default::default()
},
))
.unwrap();
block_on(c.delete_guild_sticker(g, s, None)).unwrap();
let t = c.transport();
assert_eq!(
t.sent(),
[
(Get, "/stickers/6".into()),
(Get, "/sticker-packs".into()),
(Get, "/guilds/5/stickers".into()),
(Get, "/guilds/5/stickers/6".into()),
(Post, "/guilds/5/stickers".into()),
(Patch, "/guilds/5/stickers/6".into()),
(Delete, "/guilds/5/stickers/6".into()),
]
);
let create = t.request(4);
let body = String::from_utf8_lossy(create.body.as_deref().unwrap()).into_owned();
assert!(body.contains("name=\"name\"\r\n\r\nwave\r\n"));
assert!(body.contains("name=\"file\"; filename=\"wave.png\""));
assert!(!body.contains("payload_json"));
assert_eq!(create.header("x-audit-log-reason"), Some("fun"));
assert_eq!(t.body(5), json!({ "description": null }));
}
}