diff --git a/Cargo.lock b/Cargo.lock index b15b0e0..f33039c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -994,7 +994,7 @@ checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" [[package]] name = "vkapi" -version = "0.1.0" +version = "0.2.0" dependencies = [ "bytes", "futures", diff --git a/examples/1.jpg b/examples/1.jpg index 0f744c3..5552096 100644 Binary files a/examples/1.jpg and b/examples/1.jpg differ diff --git a/examples/get_group_members.rs b/examples/get_group_members.rs index 9a23105..b82cc43 100644 --- a/examples/get_group_members.rs +++ b/examples/get_group_members.rs @@ -5,11 +5,7 @@ extern crate vkapi; async fn main() { let mut params = param!{"group_id" => "194950468", "fields" => "bdate,first_name,last_name"}; - let mut vk_api = vkapi::VK::new("5.103", "en"); - vk_api.set_access_token( - "db619ee5e3e018f25fc3a1d27153198c22d8c84850be604e3a2bb2d66a8a5d13771b56198d08ea3ac358e" - .to_string(), - ); + let mut vk_api = vkapi::VK::new("5.103", "en", "db619ee5e3e018f25fc3a1d27153198c22d8c84850be604e3a2bb2d66a8a5d13771b56198d08ea3ac358e".into()); let response = vk_api .request("groups.getMembers", &mut params) .await diff --git a/examples/longpoll.rs b/examples/longpoll.rs index c0da8b3..ed52a55 100644 --- a/examples/longpoll.rs +++ b/examples/longpoll.rs @@ -1,13 +1,17 @@ +use vkapi::longpoll::EventType; + #[tokio::main] async fn main() { - let mut vk_api = vkapi::VK::new("5.103", "ru"); - vk_api.set_access_token("db619ee5e3e018f25fc3a1d27153198c22d8c84850be604e3a2bb2d66a8a5d13771b56198d08ea3ac358e".to_string()); - - vk_api.start_longpoll( + let mut vk_api = vkapi::VK::new("5.103", "ru", "db619ee5e3e018f25fc3a1d27153198c22d8c84850be604e3a2bb2d66a8a5d13771b56198d08ea3ac358e".into()); + let ch = vk_api.start_longpoll( 194950468, 25, - Box::new(|event| { - println!("callback, event: {} ", event); - }), - ).await; + ); + + for event in ch { + match event.0 { + EventType::NewMessage => println!("new message: {}", event.1), + EventType::Other(name) => println!("new event type {} {}", name, event.1) + }; + } } diff --git a/examples/upload_file.rs b/examples/upload_file.rs index c2cabb4..92011b3 100644 --- a/examples/upload_file.rs +++ b/examples/upload_file.rs @@ -1,15 +1,12 @@ use vkapi::types::{destination::Destination, file::File}; +use vkapi::param; #[tokio::main] async fn main() { println!("Hello, world!"); - let mut vk_api = vkapi::VK::new("5.103", "ru"); - vk_api.set_access_token( - "db619ee5e3e018f25fc3a1d27153198c22d8c84850be604e3a2bb2d66a8a5d13771b56198d08ea3ac358e" - .into(), - ); + let mut vk_api = vkapi::VK::new("5.103", "ru", "db619ee5e3e018f25fc3a1d27153198c22d8c84850be604e3a2bb2d66a8a5d13771b56198d08ea3ac358e".into()); let file = File::new("examples/1.jpg", Destination::Message); - let r = vk_api.upload(file).await.unwrap(); + let r = vk_api.upload(file, param!{}).await.unwrap(); println!("{}", r); } diff --git a/src/lib.rs b/src/lib.rs index 8be3fe6..1bfb4f4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,11 +10,12 @@ //! println!("Имя: {}, Фамилия: {}, Дата рождения: {}", user["first_name"], user["last_name"], user["bdate"]); // Print all users information //! } //! ``` -//! Other examples are [hLongpollere](https://github.com/DuckerMan/vk_api/tree/master/examples) +//! Other examples are [there](https://github.com/DuckerMan/vk_api/tree/master/examples) #![warn(clippy::all)] #[macro_use] extern crate json; extern crate futures; +pub extern crate tokio; pub mod longpoll; #[macro_use] diff --git a/src/longpoll.rs b/src/longpoll.rs index 31cd474..aced66a 100644 --- a/src/longpoll.rs +++ b/src/longpoll.rs @@ -2,13 +2,27 @@ use super::params::Params; use super::vk::VK; use std::sync::RwLock; use std::thread; +use std::sync::mpsc::{channel, Sender, Receiver}; +/// TODO: Add more event types +#[derive(Debug, Clone)] +pub enum EventType { + NewMessage, + Other(String) +} + +impl EventType { + pub fn new(event: &str) -> Self { + match event { + "message_new" => EventType::NewMessage, + _ => EventType::Other(event.to_owned()) + } + } +} pub struct Longpoll { - server: Option, - key: Option, group_id: String, wait: u16, - token: Option, + token: String, api_version: String, lang: String, } @@ -17,13 +31,11 @@ impl Longpoll { pub fn new( group_id: u32, wait: u16, - token: Option, + token: String, api_version: String, lang: String, ) -> Self { Self { - server: None, - key: None, group_id: group_id.to_string(), wait: wait, token, @@ -32,15 +44,23 @@ impl Longpoll { } } - pub async fn start(&self, callback: Box ()>) { + pub fn start(&self) -> Receiver<(EventType, json::JsonValue)> { + let (tx, rx) = channel(); + let token = self.token.clone(); + let api_version = self.api_version.clone(); + let lang = self.lang.clone(); + let group_id = self.group_id.clone(); + let wait = self.wait; + + tokio::spawn(async move { let mut params = Params::new(); - params.add_param("group_id", &self.group_id); + params.add_param("group_id", &group_id); let data = VK::request_public( "groups.getLongPollServer", &mut params, - &self.token, - &self.api_version, - &self.lang, + &token, + &api_version, + &lang, ) .await .unwrap(); @@ -49,16 +69,16 @@ impl Longpoll { let mut ts = data["response"]["ts"].as_str().unwrap().to_owned(); loop { - let data = Longpoll::poll(&server, &key, ts, self.wait).await; + let data = Longpoll::poll(&server, &key, ts, wait).await; ts = data["ts"].as_str().unwrap().to_owned(); let updates = &data["updates"]; if !data["failed"].is_null() { let new_data = VK::request_public( "groups.getLongPollServer", &mut params, - &self.token, - &self.api_version, - &self.lang, + &token, + &api_version, + &lang, ) .await .unwrap(); @@ -69,9 +89,14 @@ impl Longpoll { } updates.members().for_each(|event| { - callback(event); + let event_type = EventType::new(&event["type"].as_str().unwrap()); + let event = event["object"].clone(); + tx.send((event_type, event)).unwrap(); }); } + }); + + rx } pub fn stop() { diff --git a/src/params.rs b/src/params.rs index d4f1de3..e073e97 100644 --- a/src/params.rs +++ b/src/params.rs @@ -51,6 +51,7 @@ impl Params { /// /// let param = param!{"group_id" => "1", "fields" => "bdate"}; macro_rules! param( + () => {let mut params = vkapi::params::Params::new(); params}; { $($key:expr => $value:expr),+ } => { { let mut params = vkapi::params::Params::new(); diff --git a/src/vk.rs b/src/vk.rs index ec6a658..ffa62b5 100644 --- a/src/vk.rs +++ b/src/vk.rs @@ -5,13 +5,14 @@ use crate::longpoll::Longpoll; use crate::params::Params; use crate::types::destination::Destination; use crate::types::file::File; +use std::sync::mpsc::{channel, Sender, Receiver}; /// Request type - used for make request to VK API type Request = String; /// VK structure, used for call api method, use longpoll api and etc pub struct VK<'a> { - access_token: Option, + access_token: String, api_version: &'a str, language: &'a str, } @@ -22,9 +23,9 @@ impl<'a> VK<'a> { /// # Arguments: /// * `api_version` - pick up one [here](https://vk.com/dev/versions) /// * `language` - [here](https://vk.com/dev/api_requests) - pub fn new(api_version: &'a str, language: &'a str) -> Self { + pub fn new(api_version: &'a str, language: &'a str, access_token: String) -> Self { Self { - access_token: None, + access_token, api_version, language, } @@ -32,12 +33,12 @@ impl<'a> VK<'a> { /// Set access token pub fn set_access_token(&mut self, token: String) { - self.access_token = Some(token); + self.access_token = token; } /// Get a reference to token - pub fn get_access_token(&self) -> &String { - self.access_token.as_ref().unwrap() + pub fn get_access_token(&self) -> String { + self.access_token.clone() } /// This methond starts to longpolling, It's sad, but as for now there're ways to stop it (but I'm gonna make it) @@ -45,21 +46,21 @@ impl<'a> VK<'a> { /// * `group_id` - your group ID /// * `wait` - Maximal time to waiting, max value is 90 /// * `callback` - closure which have 1 argument: [event](https://vk.com/dev/groups_events) - pub async fn start_longpoll( + pub fn start_longpoll( &self, group_id: u32, wait: u16, - callback: Box ()>, - ) { + ) -> Receiver<(crate::longpoll::EventType, json::JsonValue)> { let access_token = self.access_token.clone(); let longpoll = Longpoll::new( group_id, wait, - access_token, + access_token.to_owned(), self.api_version.to_string().clone(), self.language.to_string().clone(), ); - longpoll.start(callback).await; + + longpoll.start() } /// Use if you want to upload any file @@ -141,15 +142,11 @@ impl<'a> VK<'a> { // TODO: get rid of shitcode method: &str, params: &mut Params, - access_token: &Option, + access_token: &str, api_version: &str, language: &str, ) -> std::result::Result { let request_url = { - if access_token.is_none() { - panic!("Access token is empty! Did you forget to call set_access_token() ?"); - } - let access_token = access_token.as_ref().unwrap(); let result = format!( "https://api.vk.com/method/{}?{}access_token={}&v={}&lang={}", method, @@ -197,12 +194,7 @@ impl<'a> VK<'a> { } fn build_request(&self, method: &str, params: &mut Params) -> Request { - let access_token = self.access_token.as_ref(); - if access_token.is_none() { - panic!("Access token is empty! Did you forget to call set_access_token() ?"); - } - - let access_token = access_token.unwrap(); + let access_token = &self.access_token; let result = format!( "https://api.vk.com/method/{}?{}access_token={}&v={}&lang={}", method,