safe-vk 0.3.0-alpha

A simple library to create your own vk bot for conversations
Documentation
use crate::{extract::Update, service::Service, RequestBuilder, Response};
use std::{
    future::{poll_fn, Future, IntoFuture},
    marker::PhantomData,
    pin::Pin,
    sync::Arc,
    task::{Context, Poll},
};

pub struct Polling<M, S> {
    request: Arc<RequestBuilder>,
    safevk: M,
    _marker: PhantomData<S>,
}

pub fn start_polling<M, S>(token: &str, group_id: u32, safevk: M) -> Polling<M, S>
where
    M: Service<(), Response = S>,
    S: Service<Update, Response = ()> + Clone + Send + 'static,
    S::Future: Send,
{
    let request = Arc::new(RequestBuilder::new(token, group_id));
    Polling {
        request,
        safevk,
        _marker: PhantomData,
    }
}

impl<M, S> IntoFuture for Polling<M, S>
where
    M: Service<(), Response = S> + Send + Clone + 'static + Service<Update>,
    <M as Service<Update>>::Future: Send,
    S: Service<Update, Response = ()> + Clone + Send + 'static,
    S::Future: Send,
{
    type Output = Response<()>;
    type IntoFuture = PollFuture;

    fn into_future(self) -> Self::IntoFuture {
        PollFuture(Box::pin(async move {
            let Self {
                request,
                mut safevk,
                _marker: _,
            } = self;
            loop {
                let res = request.build_long_poll_request().await?;

                if let Some(updates) = res.updates {
                    for event in updates {
                        poll_fn(|cx| <M as Service<Update>>::poll_ready(&mut safevk, cx))
                            .await
                            .unwrap();

                        let request = Arc::clone(&request);
                        let mut safevk = safevk.clone();

                        let _: tokio::task::JoinHandle<Response<()>> = tokio::spawn(async move {
                            match safevk.call(event, request).await {
                                Ok(..) => Ok(()),
                                Err(err) => panic!("{err}"),
                            }
                        });
                    }
                }
            }
        }))
    }
}

pub struct PollFuture(pub(super) futures_util::future::BoxFuture<'static, Response<()>>);

impl Future for PollFuture {
    type Output = Response<()>;

    #[inline]
    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        self.0.as_mut().poll(cx)
    }
}