From 31be915ab71dcab004b64b313b20188af85c5d24 Mon Sep 17 00:00:00 2001 From: David Li Date: Mon, 19 Oct 2015 08:36:50 -0400 Subject: Initial commit --- .gitignore | 1 + Cargo.lock | 277 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 9 ++ src/main.rs | 77 ++++++++++++++++ src/message.rs | 94 ++++++++++++++++++++ 5 files changed, 458 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/main.rs create mode 100644 src/message.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eb5a316 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..6d0a73f --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,277 @@ +[root] +name = "rust-pushbullet" +version = "0.1.0" +dependencies = [ + "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "websocket 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "advapi32-sys" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bitflags" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byteorder" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cookie" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "openssl 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", + "url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gcc" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "advapi32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hpack" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "httparse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "hyper" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cookie 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "language-tags 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", + "solicit 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", + "traitobject 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "kernel32-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "language-tags" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazy_static" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libressl-pnacl-sys" +version = "2.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "pnacl-build-helper 1.4.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "log" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "matches" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "mime" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num_cpus" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "openssl" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "openssl-sys" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libressl-pnacl-sys 2.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pkg-config" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pnacl-build-helper" +version = "1.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "tempdir 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "advapi32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc-serialize" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "solicit" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hpack 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tempdir" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "time" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "toml" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "traitobject" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "typeable" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicase" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "url" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "websocket" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..c46b3b9 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "rust-pushbullet" +version = "0.1.0" +authors = ["David Li "] + +[dependencies] +websocket = "~0.12.2" +rustc-serialize = "0.3" +toml = "0.1" diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..ddf4feb --- /dev/null +++ b/src/main.rs @@ -0,0 +1,77 @@ +use std::process::Command; +use std::fs::File; +use std::io::prelude::*; + +extern crate toml; +extern crate websocket; +extern crate rustc_serialize; +use rustc_serialize::{Decodable}; +use rustc_serialize::json::{Json, Decoder}; + +mod message; +use message::{Message, Push}; + +fn main() { + use websocket::{Receiver}; + use websocket::client::request::Url; + use websocket::Client; + + let mut cfg_file = File::open("config.toml").unwrap(); + let mut s = String::new(); + cfg_file.read_to_string(&mut s); + let cfg = toml::Parser::new(s.as_ref()).parse().unwrap(); + let token = cfg.get("pushbullet").unwrap().as_table().unwrap().get("token").expect("Could not find 'token' in config.toml").as_str().unwrap(); + + let wss_url = format!("wss://stream.pushbullet.com/websocket/{}", token); + let url = Url::parse(wss_url.as_ref()).unwrap(); + let request = Client::connect(url).unwrap(); + let response = request.send().unwrap(); + response.validate().unwrap(); + + let (mut sender, mut receiver) = response.begin().split(); + + for message in receiver.incoming_messages() { + let message = match message { + Ok(m) => m, + Err(e) => { + println!("Error: {:?}", e); + return; + } + }; + + match message { + websocket::Message::Close(_) => { + return; + } + websocket::Message::Text(message) => { + let json = Json::from_str(message.as_ref()).unwrap(); + let mut decoder = Decoder::new(json); + let msg = Decodable::decode(&mut decoder).unwrap(); + println!("Got {:?}", msg); + match msg { + Message::Nop => {} + Message::Push(Push::Mirror { + notification_id, + title, + body, + application_name, + .. + }) => { + let _ = Command::new("notify-send") + .arg(title) + .arg(body) + .arg("-t") + .arg("8000") + .status().unwrap(); + } + Message::Push(Push::Dismissal { notification_id }) => { + + } + } + } + _ => { + println!("Got {:?}", message); + } + } + } +} diff --git a/src/message.rs b/src/message.rs new file mode 100644 index 0000000..c0a766c --- /dev/null +++ b/src/message.rs @@ -0,0 +1,94 @@ +extern crate rustc_serialize; + +use self::rustc_serialize::{json, Decodable, Decoder}; + +#[derive(Debug)] +pub enum Push { + Mirror { + notification_id: i32, + title: String, + body: String, + application_name: String, + package_name: String, + icon: String + }, + Dismissal { + notification_id: i32 + } +} + +#[derive(Debug)] +pub enum Message { + Nop, + Push(Push) +} + +impl Decodable for Push { + fn decode(d: &mut D) -> Result { + d.read_struct("root", 0, |d| { + let type_ : String = try!(d.read_struct_field("type", 0, Decodable::decode)); + match type_.as_ref() { + "mirror" => { + let id = try!( + d.read_struct_field("notification_id", 0, Decodable::decode)); + let title = try!( + d.read_struct_field("title", 0, Decodable::decode)); + let body = try!( + d.read_struct_field("body", 0, Decodable::decode)); + let app_name = try!( + d.read_struct_field("application_name", 0, Decodable::decode)); + let package_name = try!( + d.read_struct_field("package_name", 0, Decodable::decode)); + let icon = try!( + d.read_struct_field("icon", 0, Decodable::decode)); + + Ok(Push::Mirror { + title: title, + body: body, + application_name: app_name, + package_name: package_name, + notification_id: id, + icon: icon + }) + } + "dismissal" => { + let id = try!( + d.read_struct_field("notification_id", 0, Decodable::decode)); + + Ok(Push::Dismissal { + notification_id: id + }) + } + _ => { + let err_msg = format!( + "Invalid value for push type: {} (expected 'mirror' or 'dismissal')", + type_); + Err(d.error(err_msg.as_ref())) + } + } + }) + } +} + +impl Decodable for Message { + fn decode(d: &mut D) -> Result { + d.read_struct("root", 0, |d| { + let type_ : String = try!(d.read_struct_field("type", 0, Decodable::decode)); + + match type_.as_ref() { + "nop" => Ok(Message::Nop), + "push" => { + d.read_struct_field("push", 0, |d| { + Ok(Message::Push(try!(Decodable::decode(d)))) + }) + }, + _ => { + let err_msg = format!( + "Invalid value for message type: {}", + type_); + Err(d.error(err_msg.as_ref())) + } + } + }) + } +} -- cgit v1.2.3