use std::collections::HashMap;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use serde_json::Value;
use crate::client::Client;
use crate::error::{Error, Result};
use crate::message::Message;
use crate::rest::{CallbackType, EditOptions, ReplyOptions};
use crate::types::*;
#[derive(Clone, Debug)]
pub struct Interaction {
pub id: Id,
pub token: String,
pub kind: InteractionType,
pub channel_id: Id,
pub guild_id: Option<Id>,
pub user: User,
pub member: Option<Member>,
pub command: Option<String>,
pub options: HashMap<String, Value>,
pub custom_id: Option<String>,
pub message: Option<Message>,
pub data: InteractionData,
replied: Arc<AtomicBool>,
client: Client,
}
impl Interaction {
pub(crate) fn new(client: Client, data: InteractionData) -> Self {
let options = data
.command
.as_ref()
.map(|c| {
c.options
.iter()
.map(|o| (o.name.clone(), o.value.clone()))
.collect()
})
.unwrap_or_default();
Self {
id: data.id.clone(),
token: data.token.clone(),
kind: data.kind,
channel_id: data.channel_id.clone(),
guild_id: data.guild_id.clone(),
user: data.user.clone(),
member: data.member.clone(),
command: data.command.as_ref().map(|c| c.name.clone()),
options,
custom_id: data.custom_id.clone(),
message: data
.message
.clone()
.map(|m| Message::new(client.clone(), m)),
data,
replied: Arc::new(AtomicBool::new(false)),
client,
}
}
pub fn client(&self) -> &Client {
&self.client
}
pub fn is_button(&self) -> bool {
self.kind == InteractionType::Button
}
pub fn option(&self, name: &str) -> Option<&Value> {
self.options.get(name)
}
pub fn option_str(&self, name: &str) -> Option<&str> {
self.option(name)?.as_str()
}
pub fn option_i64(&self, name: &str) -> Option<i64> {
let v = self.option(name)?;
v.as_i64()
.or_else(|| v.as_f64().map(|f| f as i64))
.or_else(|| v.as_str()?.trim().parse().ok())
}
pub fn option_f64(&self, name: &str) -> Option<f64> {
let v = self.option(name)?;
v.as_f64().or_else(|| v.as_str()?.trim().parse().ok())
}
pub fn option_bool(&self, name: &str) -> Option<bool> {
self.option(name)?.as_bool()
}
pub fn channel(&self) -> Option<Channel> {
self.client.channel(&self.channel_id)
}
pub fn replied(&self) -> bool {
self.replied.load(Ordering::Relaxed)
}
pub async fn reply(&self, answer: impl Into<ReplyOptions>) -> Result<Message> {
let d = self
.client
.rest()
.interaction_callback(&self.id, &self.token, CallbackType::Message, answer.into())
.await?;
self.replied.store(true, Ordering::Relaxed);
Ok(Message::new(self.client.clone(), d))
}
pub async fn update(&self, edit: impl Into<EditOptions>) -> Result<Message> {
if !self.is_button() {
return Err(Error::Other("update() é só para cliques em botões".into()));
}
let d = self
.client
.rest()
.interaction_callback(&self.id, &self.token, CallbackType::Update, edit.into())
.await?;
self.replied.store(true, Ordering::Relaxed);
Ok(Message::new(self.client.clone(), d))
}
}