use super::{FromUpdate, FromUpdateParts, Parts, Update};
use crate::{
responses::{ButtonPressCallback, Members, Message, User},
util::NdArray,
Error, RequestBuilder, VK,
};
use serde_json::json;
use std::sync::Arc;
#[derive(Clone)]
#[must_use]
pub struct Ctx<T> {
request: Arc<RequestBuilder>,
body: T,
}
impl Ctx<Message> {
pub async fn reply(&self, message: impl Into<String>) -> crate::Result<()> {
self.request
.post(
VK,
"messages.send",
&[
("message", message.into()),
("peer_id", self.message.peer_id.to_string()),
("random_id", String::from("0")),
],
{},
)
.await?;
Ok(())
}
pub async fn reply_rnd(
&self,
message: impl Into<String>,
random_id: String,
) -> crate::Result<()> {
self.request
.post(
VK,
"messages.send",
&[
("message", message.into()),
("peer_id", self.message.peer_id.to_string()),
("random_id", random_id),
],
{},
)
.await?;
Ok(())
}
pub async fn get_users(&self, user_ids: &[i32]) -> crate::Result<Vec<User>> {
let serialized = serde_json::to_string(&user_ids[0])?;
let response = self
.request
.post(VK, "users.get", &[("user_ids", &serialized)], {})
.await?;
Ok(crate::parse_response!(response, Vec<User>)?)
}
pub async fn get_members(
&self,
offset: Option<u16>,
count: Option<u16>,
extended: bool,
) -> crate::Result<Members> {
let mut params = vec![("peer_id", self.message.peer_id.to_string())];
if extended {
params.push(("extended", String::from("1")));
} else {
params.push(("extended", String::from("0")));
}
if let Some(offset_val) = offset {
params.push(("offset", offset_val.to_string()));
}
if let Some(count_val) = count {
params.push(("count", count_val.to_string()));
}
let res = self
.request
.post(VK, "messages.getConversationMembers", ¶ms, {})
.await?;
return Ok(crate::parse_response!(res, Members)?);
}
pub async fn keyboard<T: serde::Serialize, N: NdArray<T>>(
&self,
message: impl Into<String>,
one_time: bool,
inline: bool,
buttons: N,
) -> crate::Result<()> {
let dim_1 = buttons.shape().dims()[1];
let dim_2 = buttons.shape().dims()[0];
if dim_1 > 5 {
return Err(Error::DimOutOfRange {
shape: buttons.shape(),
dim: dim_1 as i32,
});
} else if dim_2 > 10 {
return Err(Error::DimOutOfRange {
shape: buttons.shape(),
dim: dim_2 as i32,
});
}
let keyboard = json!({
"one_time": one_time,
"inline": inline,
"buttons": json!(buttons.slice()),
});
let keyboard = serde_json::to_string(&keyboard)?;
self.request
.post(
VK,
"messages.send",
&[
("message", message.into()),
("peer_id", self.message.peer_id.to_string()),
("keyboard", keyboard),
("random_id", String::from("0")),
],
{},
)
.await?;
Ok(())
}
}
impl Ctx<Update> {
pub async fn reply(&self, message: &str) -> crate::Result<()> {
for update in self.updates.as_ref().unwrap() {
if let Some(peer_id) = update.object.get("peer_id") {
self.request
.post(
VK,
"messages.send",
&[
("message", message.to_string()),
("peer_id", peer_id.to_string()),
("random_id", String::from("0")),
],
{},
)
.await?;
}
}
Ok(())
}
pub async fn keyboard_callback<
'de,
T: serde::Serialize,
A: serde::de::DeserializeOwned + PartialEq + serde::Serialize,
>(
&self,
callback: T,
payload: A,
) -> crate::Result<Option<A>> {
for update in self.updates.as_ref().unwrap() {
if let Ok(valid_data) =
serde_json::from_value::<ButtonPressCallback<A>>(update.object.clone())
{
let event_data = serde_json::to_string(&callback).unwrap();
let res = self
.request
.post(
VK,
"messages.sendMessageEventAnswer",
&[
("event_data", event_data),
("user_id", valid_data.user_id.to_string()),
("event_id", valid_data.event_id),
("peer_id", valid_data.peer_id.to_string()),
],
{},
)
.await?;
if let Ok(response) = crate::parse_response!(res, EventAnswer) {
if response.get_status().is_ok() {
return Ok(Some(payload));
}
}
}
}
Ok(None)
}
}
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
pub struct EventAnswer(i8);
impl EventAnswer {
pub fn get_status(&self) -> crate::Result<i8> {
let status = self.0;
match status {
1 => Ok(status),
_ => Err(Error::EventAnswerUnkownStatus { status }),
}
}
}
impl<T> std::ops::Deref for Ctx<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.body
}
}
impl<S> FromUpdate<S> for Ctx<Message>
where
S: Send + Sync,
{
async fn from_update(
update: Update,
_state: &S,
request: Arc<RequestBuilder>,
) -> Result<Self, ()> {
let message: Message =
serde_json::from_value(update.updates.unwrap()[0].object.clone()).unwrap();
Ok(Ctx {
request,
body: message,
})
}
}
impl<S> FromUpdateParts<S> for Arc<RequestBuilder>
where
S: Send + Sync,
{
async fn from_update_parts(
_parts: &mut Parts,
_state: &S,
request: Arc<RequestBuilder>,
) -> Result<Self, ()> {
Ok(request)
}
}
impl<S> FromUpdate<S> for Ctx<Update>
where
S: Send + Sync,
{
async fn from_update(
update: Update,
_state: &S,
request: Arc<RequestBuilder>,
) -> Result<Self, ()> {
Ok(Ctx {
request,
body: update,
})
}
}