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