use reqwest::{Client, Error}; use serde::Deserialize; use serde_json::Value; use crate::emotes::{EmoteBase, RetrieveEmoteAPI}; #[derive(Debug, Deserialize, Clone)] pub struct BetterTTVEmote { pub id: String, pub code: String, #[serde(rename = "originalCode")] pub original_code: Option, #[serde(rename = "imageType")] pub image_type: String, pub animated: bool, } impl EmoteBase for BetterTTVEmote { fn get_id(&self) -> &String { &self.id } fn get_code(&self) -> &String { &self.code } fn get_original_code(&self) -> &Option { &self.original_code } } pub struct BetterTTVAPIClient { client: Client, base_url: String, } impl BetterTTVAPIClient { pub fn new() -> Self { Self { client: Client::new(), base_url: "https://api.betterttv.net/3".into(), } } } impl RetrieveEmoteAPI for BetterTTVAPIClient { async fn get_channel_emotes(&self, channel_id: &str) -> Result, Error> { let response = self .client .get(format!( "{}/cached/users/twitch/{}", self.base_url, channel_id )) .send() .await? .error_for_status()?; let json: Value = response.json().await?; let mut emotes = Vec::new(); if let Some(shared_emotes) = json.get("sharedEmotes") { let shared_emotes: Vec = serde_json::from_value(shared_emotes.clone()).unwrap(); emotes.extend(shared_emotes); } if let Some(channel_emotes) = json.get("channelEmotes") { let channel_emotes: Vec = serde_json::from_value(channel_emotes.clone()).unwrap(); emotes.extend(channel_emotes); } Ok(emotes) } async fn get_global_emotes(&self) -> Result, Error> { let response = self .client .get(format!("{}/cached/emotes/global", self.base_url)) .send() .await? .error_for_status()?; let json: Value = response.json().await?; Ok(serde_json::from_value(json).unwrap()) } }