hangups-rs

Rust version of hangups (WIP) Currently Login not possible
git clone git://archive.git.mtrnord.blog/Nordgedanken/hangups-rs.git
Log | Files | Refs | README | LICENSE

commit ae1471370ad2546d76d1c91f0ba3e41192d82c84
parent f3a0dd5a81ba2d768ab792186c7051d5560f3b51
Author: MTRNord <mtrnord1@gmail.com>
Date:   Thu, 13 Apr 2017 00:07:18 +0200

Prepare send message

Diffstat:
M.gitignore | 1+
MCargo.toml | 7++++---
Msrc/lib.rs | 164+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
3 files changed, 144 insertions(+), 28 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -8,3 +8,4 @@ Cargo.lock target/ **/*.rs.bk Cargo.lock +src/proto/**/* diff --git a/Cargo.toml b/Cargo.toml @@ -1,12 +1,13 @@ [package] name = "hangups" -version = "0.1.0" +version = "0.0.1" authors = ["MTRNord"] [dependencies] yup-oauth2 = "1.0.5" hyper = "0.10.2" +hyper-native-tls = "0.2.2" serde = "0.9" serde_json = "0.9" -serde_derive = "0.9" -hyper-native-tls = "0.2.2" +protobuf = "1.2.2" +rand = "0.3" diff --git a/src/lib.rs b/src/lib.rs @@ -1,15 +1,20 @@ +#[macro_use] extern crate hyper; extern crate hyper_native_tls; extern crate yup_oauth2 as oauth2; extern crate serde; extern crate serde_json; +extern crate protobuf; +extern crate rand; + pub mod auth { pub fn get_auth(client_email: String) { use hyper::Client; use hyper::net::HttpsConnector; use hyper_native_tls::NativeTlsClient; - use oauth2::{Authenticator, DefaultAuthenticatorDelegate, MemoryStorage, GetToken, ApplicationSecret}; - use std::io::{stdin,stdout,Write}; + use oauth2::{Authenticator, DefaultAuthenticatorDelegate, MemoryStorage, GetToken, + ApplicationSecret}; + use std::io::{stdin, stdout, Write}; let ssl = NativeTlsClient::new().unwrap(); let connector = HttpsConnector::new(ssl); @@ -23,58 +28,167 @@ pub mod auth { if client_email == String::from("") { let mut client_email = String::new(); println!("Please enter Google Email: "); - let _=stdout().flush(); - stdin().read_line(&mut client_email).expect("Did not enter a correct Email"); - if let Some('\n')=client_email.chars().next_back() { + let _ = stdout().flush(); + stdin() + .read_line(&mut client_email) + .expect("Did not enter a correct Email"); + if let Some('\n') = client_email.chars().next_back() { client_email.pop(); } - if let Some('\r')=client_email.chars().next_back() { + if let Some('\r') = client_email.chars().next_back() { client_email.pop(); } } - println!("You typed: {}",client_email); + println!("You typed: {}", client_email); - let secret = ApplicationSecret {client_id: client_id, client_secret: client_secret, token_uri: token_uri, auth_uri: auth_uri, redirect_uris: vec![redirect_uri], project_id: None, client_email: None, auth_provider_x509_cert_url: None, client_x509_cert_url: None}; - let res = Authenticator::new(&secret, DefaultAuthenticatorDelegate, - client, - <MemoryStorage as Default>::default(), None) - .token(&["https://www.googleapis.com/auth/userinfo.email"]); + let secret = ApplicationSecret { + client_id: client_id, + client_secret: client_secret, + token_uri: token_uri, + auth_uri: auth_uri, + redirect_uris: vec![redirect_uri], + project_id: None, + client_email: None, + auth_provider_x509_cert_url: None, + client_x509_cert_url: None, + }; + let res = Authenticator::new(&secret, + DefaultAuthenticatorDelegate, + client, + <MemoryStorage as Default>::default(), + None) + .token(&["https://www.googleapis.com/auth/userinfo.email"]); match res { Ok(t) => { - // now you can use t.access_token to authenticate API calls within your - // given scopes. It will not be valid forever, but Authenticator will automatically - // refresh the token for you. println!("Acquired access_token: {}", t.access_token); println!("Acquired access_token: {}", t.refresh_token); - }, + } Err(err) => println!("Failed to acquire token: {}", err), } } } +#[path = "."] +pub mod hangups { + #[path = "proto/hangouts.rs"] mod hangouts; + use self::hangouts::{MessageContent, Segment, SegmentType, RequestHeader, EventRequestHeader, + SendChatMessageRequest, DeliveryMediumType, OffTheRecordStatus, + EventType, SendChatMessageResponse, DeliveryMedium, ConversationId}; + use protobuf::RepeatedField; + use rand::random; + use hyper::header::Headers; + use hyper::header::Cookie; + use hyper::client::{Client, IntoUrl}; + use hyper::client::RequestBuilder; + use hyper::method::Method; + header! { (Content_Type, "content-type") => [String] } + header! { + (XGoogEncodeResponseIfExecutable, "X-Goog-Encode-Response-If-Executable") => [String] + } + + fn GetAuthHeaders() {} + + fn ApiRequest(endpointUrl: String, contentType: String, cookies: String, payload: SendChatMessageRequest) { + let mut headers = Headers::new(); + headers.set(Cookie(vec![String::from(cookies.to_owned())])); + headers.set(Content_Type(String::from(contentType.to_owned()))); + headers.set(XGoogEncodeResponseIfExecutable(String::from("base64".to_owned()))); + let client = Client::new(); + let custom_request = RequestBuilder { + client: &client, + url: endpointUrl.into_url(), + headers: Some(headers), + method: Method::Post, + body: payload + }; + } + + fn ProtobufApiRequest(apiEndpoint: String, + requestStruct: SendChatMessageRequest, + responseStruct: SendChatMessageResponse) { + let url = format!("https://clients6.google.com/chat/v1/{}", apiEndpoint); + let output = self::ApiRequest(url, + String::from("application/x-protobuf"), + String::from("proto"), + requestStruct); + } + + pub fn send_message(message: String, conv_id_raw: String) { + //Prepare message + let segment_type = SegmentType::SEGMENT_TYPE_TEXT; + let mut segment_raw = Segment::new(); + segment_raw.set_field_type(segment_type); + segment_raw.set_text(message); + let mut segment = RepeatedField::new(); + segment.push(segment_raw); + let mut message_content = MessageContent::new(); + message_content.set_segment(segment); + + + //Prepare Request + let request_header = RequestHeader::new(); + request_header.set_language_code(String::from("en")); + + let deliveryMedium = DeliveryMedium::new(); + deliveryMedium.set_medium_type(DeliveryMediumType::DELIVERY_MEDIUM_BABEL); + let expectedOtr = OffTheRecordStatus::OFF_THE_RECORD_STATUS_ON_THE_RECORD; + let clientGeneratedId = random::<u64>(); + let eventType = EventType::EVENT_TYPE_REGULAR_CHAT_MESSAGE; + let event_request_header = EventRequestHeader::new(); + let conv_id = ConversationId::new(); + conv_id.set_id(conv_id_raw); + event_request_header.set_conversation_id(conv_id); + event_request_header.set_delivery_medium(deliveryMedium); + event_request_header.set_expected_otr(expectedOtr); + event_request_header.set_client_generated_id(clientGeneratedId); + event_request_header.set_event_type(eventType); + + let request = SendChatMessageRequest::new(); + request.set_request_header(request_header); + request.set_message_content(message_content); + request.set_event_request_header(event_request_header); + + //Prepare response + let response = SendChatMessageResponse::new(); + } +} + #[cfg(test)] mod tests { - use super::auth::get_auth; - use std::io::{stdin,stdout,Write}; - use std::env; #[test] - fn get_auth_token() { + fn test_get_auth_token() { + use super::auth::get_auth; + use std::io::{stdin, stdout, Write}; + use std::env; + match env::var_os("CI") { - Some() => println!("CI's currently not supported at this test"), + #[allow(unused_variables)] + Some(env) => println!("CI's currently not supported at this test"), None => { let mut client_email = String::new(); println!("Please enter Google Email: "); - let _=stdout().flush(); - stdin().read_line(&mut client_email).expect("Did not enter a correct Email"); - if let Some('\n')=client_email.chars().next_back() { + let _ = stdout().flush(); + stdin() + .read_line(&mut client_email) + .expect("Did not enter a correct Email"); + if let Some('\n') = client_email.chars().next_back() { client_email.pop(); } - if let Some('\r')=client_email.chars().next_back() { + if let Some('\r') = client_email.chars().next_back() { client_email.pop(); } get_auth(client_email); } } } + + #[test] + fn test_send_message() { + use super::hangups::send_message; + + let test_message = String::from("TEST!"); + let test_conv = String::from("Ugxu9JRlbNPSqk5Ye1V4AaABAQ"); + send_message(test_message, test_conv); + } }