Compare commits

...

10 Commits

Author SHA1 Message Date
Tom Alexander ed2e5159df
Better handling of events. 1 year ago
Tom Alexander 9a27ee8d5b
Fix handling of empty responses. 2 years ago
Tom Alexander 155fb7ae00
Add todo comment. 2 years ago
Tom Alexander 1be697b8bf
Throw away results from the first poll since those are historical. 2 years ago
Tom Alexander c8b9e73c75
Add call to create notification. 2 years ago
Tom Alexander 11ddea7f53
Parse out the title and state of the pull request. 2 years ago
Tom Alexander 51bbe22bdf
Add parsing of the URL to view the pull request. 2 years ago
Tom Alexander f46a5f8a9c
Filtering to 'opened' pull request events. 2 years ago
Tom Alexander be9dcee422
Move the handling of events into a struct.
I am going to start parsing fields out of the json event objects, so it makes sense to give each event its own type to avoid the verbosity of parsing the values out of the json object every time they are needed.
2 years ago
Tom Alexander f7d2a2e57d
Filtering for pull request events. 2 years ago

696
Cargo.lock generated

@ -22,6 +22,99 @@ dependencies = [
"memchr",
]
[[package]]
name = "async-broadcast"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bbd92a9bd0e9c1298118ecf8a2f825e86b12c3ec9e411573e34aaf3a0c03cdd"
dependencies = [
"easy-parallel",
"event-listener",
"futures-core",
"parking_lot 0.11.2",
]
[[package]]
name = "async-channel"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319"
dependencies = [
"concurrent-queue",
"event-listener",
"futures-core",
]
[[package]]
name = "async-executor"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965"
dependencies = [
"async-task",
"concurrent-queue",
"fastrand",
"futures-lite",
"once_cell",
"slab",
]
[[package]]
name = "async-io"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a811e6a479f2439f0c04038796b5cfb3d2ad56c230e0f2d3f7b04d68cfee607b"
dependencies = [
"concurrent-queue",
"futures-lite",
"libc",
"log",
"once_cell",
"parking",
"polling",
"slab",
"socket2",
"waker-fn",
"winapi",
]
[[package]]
name = "async-lock"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6"
dependencies = [
"event-listener",
]
[[package]]
name = "async-recursion"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7d78656ba01f1b93024b7c3a0467f1608e4be67d725749fdcd7d2c7678fd7a2"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "async-task"
version = "4.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30696a84d817107fc028e049980e09d5e140e8da8f1caeb17e8e950658a3cea9"
[[package]]
name = "async-trait"
version = "0.1.53"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "atoi"
version = "0.4.0"
@ -60,6 +153,12 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "block"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
[[package]]
name = "block-buffer"
version = "0.9.0"
@ -87,6 +186,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
[[package]]
name = "cache-padded"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c"
[[package]]
name = "cc"
version = "1.0.73"
@ -99,6 +204,15 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "concurrent-queue"
version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3"
dependencies = [
"cache-padded",
]
[[package]]
name = "core-foundation"
version = "0.9.3"
@ -159,6 +273,17 @@ dependencies = [
"lazy_static",
]
[[package]]
name = "derivative"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "digest"
version = "0.9.0"
@ -168,12 +293,39 @@ dependencies = [
"generic-array",
]
[[package]]
name = "dirs-next"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
dependencies = [
"cfg-if",
"dirs-sys-next",
]
[[package]]
name = "dirs-sys-next"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
dependencies = [
"libc",
"redox_users",
"winapi",
]
[[package]]
name = "dotenv"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
[[package]]
name = "easy-parallel"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6907e25393cdcc1f4f3f513d9aac1e840eb1cc341a0fccb01171f7d14d10b946"
[[package]]
name = "either"
version = "1.6.1"
@ -189,6 +341,27 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "enumflags2"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e75d4cd21b95383444831539909fbb14b9dc3fdceb2a6f5d36577329a1f55ccb"
dependencies = [
"enumflags2_derive",
"serde",
]
[[package]]
name = "enumflags2_derive"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f58dc3c5e468259f19f2d46304a6b28f1c3d034442e14b322d2b850e36f6d5ae"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "env_logger"
version = "0.7.1"
@ -202,6 +375,12 @@ dependencies = [
"termcolor",
]
[[package]]
name = "event-listener"
version = "2.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71"
[[package]]
name = "fastrand"
version = "1.7.0"
@ -254,6 +433,12 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "futures-channel"
version = "0.3.21"
@ -292,6 +477,27 @@ dependencies = [
"parking_lot 0.11.2",
]
[[package]]
name = "futures-io"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
[[package]]
name = "futures-lite"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48"
dependencies = [
"fastrand",
"futures-core",
"futures-io",
"memchr",
"parking",
"pin-project-lite",
"waker-fn",
]
[[package]]
name = "futures-sink"
version = "0.3.21"
@ -344,6 +550,7 @@ name = "github_watcher"
version = "0.1.0"
dependencies = [
"log",
"notify-rust",
"pretty_env_logger",
"reqwest",
"serde_json",
@ -594,6 +801,28 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "mac-notification-sys"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "297c13fc8ff9fa8b2d0e53850f80e0aa962628e865d447031ce58cdb062e5b29"
dependencies = [
"cc",
"dirs-next",
"objc-foundation",
"objc_id",
"time",
]
[[package]]
name = "malloc_buf"
version = "0.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
dependencies = [
"libc",
]
[[package]]
name = "matches"
version = "0.1.9"
@ -606,6 +835,15 @@ version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]]
name = "memoffset"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
dependencies = [
"autocfg",
]
[[package]]
name = "mime"
version = "0.3.16"
@ -659,6 +897,19 @@ dependencies = [
"tempfile",
]
[[package]]
name = "nix"
version = "0.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6"
dependencies = [
"bitflags",
"cc",
"cfg-if",
"libc",
"memoffset",
]
[[package]]
name = "nom"
version = "7.1.1"
@ -669,6 +920,20 @@ dependencies = [
"minimal-lexical",
]
[[package]]
name = "notify-rust"
version = "4.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a995a3d2834cefa389218e7a35156e8ce544bc95f836900da01ee0b26a07e9d4"
dependencies = [
"mac-notification-sys",
"serde",
"winrt-notification",
"zbus",
"zvariant",
"zvariant_derive",
]
[[package]]
name = "ntapi"
version = "0.3.7"
@ -697,6 +962,44 @@ dependencies = [
"libc",
]
[[package]]
name = "num_threads"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
dependencies = [
"libc",
]
[[package]]
name = "objc"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
dependencies = [
"malloc_buf",
]
[[package]]
name = "objc-foundation"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9"
dependencies = [
"block",
"objc",
"objc_id",
]
[[package]]
name = "objc_id"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b"
dependencies = [
"objc",
]
[[package]]
name = "once_cell"
version = "1.10.0"
@ -742,6 +1045,22 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "ordered-stream"
version = "0.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44630c059eacfd6e08bdaa51b1db2ce33119caa4ddc1235e923109aa5f25ccb1"
dependencies = [
"futures-core",
"pin-project-lite",
]
[[package]]
name = "parking"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72"
[[package]]
name = "parking_lot"
version = "0.11.2"
@ -840,6 +1159,25 @@ version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
[[package]]
name = "polling"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259"
dependencies = [
"cfg-if",
"libc",
"log",
"wepoll-ffi",
"winapi",
]
[[package]]
name = "ppv-lite86"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
[[package]]
name = "pretty_env_logger"
version = "0.4.0"
@ -850,6 +1188,16 @@ dependencies = [
"log",
]
[[package]]
name = "proc-macro-crate"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a"
dependencies = [
"thiserror",
"toml",
]
[[package]]
name = "proc-macro2"
version = "1.0.37"
@ -874,6 +1222,73 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
dependencies = [
"fuchsia-cprng",
"libc",
"rand_core 0.3.1",
"rdrand",
"winapi",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core 0.6.3",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core 0.6.3",
]
[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
dependencies = [
"rand_core 0.4.2",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[package]]
name = "rand_core"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
dependencies = [
"getrandom",
]
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "redox_syscall"
version = "0.2.13"
@ -883,6 +1298,17 @@ dependencies = [
"bitflags",
]
[[package]]
name = "redox_users"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
dependencies = [
"getrandom",
"redox_syscall",
"thiserror",
]
[[package]]
name = "regex"
version = "1.5.5"
@ -1033,6 +1459,20 @@ name = "serde"
version = "1.0.136"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.136"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
@ -1045,6 +1485,17 @@ dependencies = [
"serde",
]
[[package]]
name = "serde_repr"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2ad84e47328a31223de7fed7a4f5087f2d6ddfe586cf3ca25b7a165bc0a5aed"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_urlencoded"
version = "0.7.1"
@ -1057,6 +1508,21 @@ dependencies = [
"serde",
]
[[package]]
name = "sha1"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770"
dependencies = [
"sha1_smol",
]
[[package]]
name = "sha1_smol"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
[[package]]
name = "sha2"
version = "0.9.9"
@ -1211,6 +1677,12 @@ dependencies = [
"tokio-rustls",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "stringprep"
version = "0.1.2"
@ -1221,6 +1693,27 @@ dependencies = [
"unicode-normalization",
]
[[package]]
name = "strum"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7ac893c7d471c8a21f31cfe213ec4f6d9afeed25537c772e08ef3f005f8729e"
dependencies = [
"strum_macros",
]
[[package]]
name = "strum_macros"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "339f799d8b549e3744c7ac7feb216383e4005d94bdb22561b3ab8f3b808ae9fb"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "syn"
version = "1.0.91"
@ -1232,6 +1725,16 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "tempdir"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
dependencies = [
"rand 0.4.6",
"remove_dir_all",
]
[[package]]
name = "tempfile"
version = "3.3.0"
@ -1275,6 +1778,16 @@ dependencies = [
"syn",
]
[[package]]
name = "time"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2702e08a7a860f005826c6815dcac101b19b5eb330c27fe4a5928fec1d20ddd"
dependencies = [
"libc",
"num_threads",
]
[[package]]
name = "tinyvec"
version = "1.5.1"
@ -1367,6 +1880,15 @@ dependencies = [
"tracing",
]
[[package]]
name = "toml"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
dependencies = [
"serde",
]
[[package]]
name = "tower-service"
version = "0.3.1"
@ -1417,6 +1939,16 @@ version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
[[package]]
name = "uds_windows"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "486992108df0fe0160680af1941fe856c521be931d5a5ecccefe0de86dc47e4a"
dependencies = [
"tempdir",
"winapi",
]
[[package]]
name = "unicode-bidi"
version = "0.3.7"
@ -1480,6 +2012,12 @@ version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "waker-fn"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
[[package]]
name = "want"
version = "0.3.0"
@ -1597,6 +2135,15 @@ dependencies = [
"webpki",
]
[[package]]
name = "wepoll-ffi"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb"
dependencies = [
"cc",
]
[[package]]
name = "winapi"
version = "0.3.9"
@ -1628,6 +2175,18 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9f39345ae0c8ab072c0ac7fe8a8b411636aa34f89be19ddd0d9226544f13944"
dependencies = [
"windows_i686_gnu 0.24.0",
"windows_i686_msvc 0.24.0",
"windows_x86_64_gnu 0.24.0",
"windows_x86_64_msvc 0.24.0",
]
[[package]]
name = "windows-sys"
version = "0.34.0"
@ -1635,10 +2194,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5acdd78cb4ba54c0045ac14f62d8f94a03d10047904ae2a40afa1e99d8f70825"
dependencies = [
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_msvc",
"windows_i686_gnu 0.34.0",
"windows_i686_msvc 0.34.0",
"windows_x86_64_gnu 0.34.0",
"windows_x86_64_msvc 0.34.0",
]
[[package]]
@ -1647,24 +2206,48 @@ version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d"
[[package]]
name = "windows_i686_gnu"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0866510a3eca9aed73a077490bbbf03e5eaac4e1fd70849d89539e5830501fd"
[[package]]
name = "windows_i686_gnu"
version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed"
[[package]]
name = "windows_i686_msvc"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf0ffed56b7e9369a29078d2ab3aaeceea48eb58999d2cff3aa2494a275b95c6"
[[package]]
name = "windows_i686_msvc"
version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956"
[[package]]
name = "windows_x86_64_gnu"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "384a173630588044205a2993b6864a2f56e5a8c1e7668c07b93ec18cf4888dc4"
[[package]]
name = "windows_x86_64_gnu"
version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4"
[[package]]
name = "windows_x86_64_msvc"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bd8f062d8ca5446358159d79a90be12c543b3a965c847c8f3eedf14b321d399"
[[package]]
name = "windows_x86_64_msvc"
version = "0.34.0"
@ -1679,3 +2262,108 @@ checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
dependencies = [
"winapi",
]
[[package]]
name = "winrt-notification"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "007a0353840b23e0c6dc73e5b962ff58ed7f6bc9ceff3ce7fe6fbad8d496edf4"
dependencies = [
"strum",
"windows",
"xml-rs",
]
[[package]]
name = "xml-rs"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3"
[[package]]
name = "zbus"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53819092b9db813b2c6168b097b4b13ad284d81c9f2b0165a0a1b190e505a1f3"
dependencies = [
"async-broadcast",
"async-channel",
"async-executor",
"async-io",
"async-lock",
"async-recursion",
"async-task",
"async-trait",
"byteorder",
"derivative",
"enumflags2",
"event-listener",
"futures-core",
"futures-sink",
"futures-util",
"hex",
"lazy_static",
"nix",
"once_cell",
"ordered-stream",
"rand 0.8.5",
"serde",
"serde_repr",
"sha1",
"static_assertions",
"uds_windows",
"winapi",
"zbus_macros",
"zbus_names",
"zvariant",
]
[[package]]
name = "zbus_macros"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7174ebe6722c280d6d132d694bb5664ce50a788cb70eeb518e7fc1ca095a114"
dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"regex",
"syn",
]
[[package]]
name = "zbus_names"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45dfcdcf87b71dad505d30cc27b1b7b88a64b6d1c435648f48f9dbc1fdc4b7e1"
dependencies = [
"serde",
"static_assertions",
"zvariant",
]
[[package]]
name = "zvariant"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e18ba99d71e03af262953f476071607da0c44e225236cf9b5b9f7f11f1d0b6b0"
dependencies = [
"byteorder",
"enumflags2",
"libc",
"serde",
"static_assertions",
"zvariant_derive",
]
[[package]]
name = "zvariant_derive"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9042892ebdca35261951a83d17bcbfd4d3d528cb3bde828498a9b306b50d05c0"
dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn",
]

@ -5,6 +5,7 @@ edition = "2021"
[dependencies]
log = "0.4.17"
notify-rust = "4.5.8"
pretty_env_logger = "0.4.0"
reqwest = { version = "0.11.10", features = ["json"] }
serde_json = "1.0.81"

@ -1,4 +1,6 @@
use reqwest::header::HeaderValue;
use reqwest::RequestBuilder;
use reqwest::Response;
use std::time::{SystemTime, UNIX_EPOCH};
use tokio::time::{sleep, Duration};
@ -36,9 +38,26 @@ impl GithubEndpointWatcher {
})
}
pub async fn get_results(
&mut self,
) -> Result<Option<serde_json::Value>, Box<dyn std::error::Error>> {
pub async fn skip_results_before_now(&mut self) -> Result<(), Box<dyn std::error::Error>> {
// This will incur an API call to get the headers for ETAG and
// last modified at but it will throw away the results.
// TODO: Can this be done without a request? We wouldn't get
// an ETAG but we should be able to calculate our own date
// string for last modified.
let request = self.build_request()?;
self.sleep_until_next_poll().await?;
self.sleep_until_ratelimit().await?;
let request_started_at = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs();
info!("Hitting url {}", self.url);
let response = request.send().await?;
self.update_headers_from_response(&response, request_started_at)?;
response.error_for_status()?;
Ok(())
}
fn build_request(&mut self) -> Result<RequestBuilder, Box<dyn std::error::Error>> {
let mut request = self
.http_client
.get(&self.url)
@ -58,14 +77,16 @@ impl GithubEndpointWatcher {
);
request = request.header(reqwest::header::IF_MODIFIED_SINCE, last_modified_at);
}
self.sleep_until_next_poll().await?;
self.sleep_until_ratelimit().await?;
let request_started_at = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs();
info!("Hitting url {}", self.url);
let response = request.send().await?;
Ok(request)
}
fn update_headers_from_response(
&mut self,
response: &Response,
request_started_at: u64,
) -> Result<(), Box<dyn std::error::Error>> {
let headers = response.headers();
let etag = headers.get(reqwest::header::ETAG).map(|x| x.to_owned());
self.etag = headers.get(reqwest::header::ETAG).map(|x| x.to_owned());
let poll_interval = number_header(headers.get("x-poll-interval"))?;
if let Some(interval) = poll_interval {
self.previous_poll_interval = Some(interval);
@ -75,38 +96,39 @@ impl GithubEndpointWatcher {
self.ratelimit_reset = number_header(headers.get("x-ratelimit-reset"))?;
// let ratelimit_used = headers.get("x-ratelimit-used").map(|x| x.to_owned());
// let ratelimit_resource = headers.get("x-ratelimit-resource").map(|x| x.to_owned());
let last_modified_at = headers
self.last_modified_at = headers
.get(reqwest::header::LAST_MODIFIED)
.map(|x| x.to_owned());
if let reqwest::StatusCode::NOT_MODIFIED = response.status() {
self.etag = etag;
self.last_modified_at = last_modified_at;
let poll_interval_parsed: u64 = poll_interval.unwrap_or_else(|| {
let fallback_interval = self.previous_poll_interval.unwrap_or(300);
info!(
"No poll interval returned, defaulting to {} second polling.",
fallback_interval
);
let poll_interval_parsed: u64 = poll_interval.unwrap_or_else(|| {
let fallback_interval = self.previous_poll_interval.unwrap_or(300);
info!(
"No poll interval returned, defaulting to {} second polling.",
fallback_interval
});
self.next_poll_allowed = request_started_at + poll_interval_parsed;
);
fallback_interval
});
self.next_poll_allowed = request_started_at + poll_interval_parsed;
Ok(())
}
pub async fn get_results(
&mut self,
) -> Result<Option<serde_json::Value>, Box<dyn std::error::Error>> {
let request = self.build_request()?;
self.sleep_until_next_poll().await?;
self.sleep_until_ratelimit().await?;
let request_started_at = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs();
info!("Hitting url {}", self.url);
let response = request.send().await?;
self.update_headers_from_response(&response, request_started_at)?;
let response_status = response.status();
if let reqwest::StatusCode::NOT_MODIFIED = response_status {
return Ok(None);
} else {
let body = response.json::<serde_json::Value>().await?;
self.etag = etag;
self.last_modified_at = last_modified_at;
let poll_interval_parsed: u64 = poll_interval.unwrap_or_else(|| {
let fallback_interval = self.previous_poll_interval.unwrap_or(300);
info!(
"No poll interval returned, defaulting to {} second polling.",
fallback_interval
);
fallback_interval
});
self.next_poll_allowed = request_started_at + poll_interval_parsed;
return Ok(Some(body));
}
}

@ -1,3 +1,5 @@
use crate::json_util::get_json_string;
use std::collections::HashSet;
use tokio::sync::mpsc;
use super::github_endpoint_watcher::GithubEndpointWatcher;
@ -75,8 +77,10 @@ impl<'a> GithubCtl<'a> {
let event_stream = self.event_writer.clone();
tokio::spawn(async move {
let mut already_seen_event_ids = HashSet::new();
let mut endpoint_watcher = GithubEndpointWatcher::new(username, token, url)
.expect("Failed to create endpoint watcher.");
let mut should_notify: bool = false; // Skip the first page of results because theses events already occurred in the past
loop {
let api_result = match endpoint_watcher.get_results().await {
Ok(result) => result,
@ -87,9 +91,17 @@ impl<'a> GithubCtl<'a> {
};
if let Some(serde_json::Value::Array(events)) = api_result {
for event in events {
if let Err(_) = event_stream.send(event).await {
error!("Receiver dropped.");
return;
let event_id = event
.get("id")
.map(get_json_string)
.expect("Ran into an event without a id.")
.to_owned();
if should_notify && already_seen_event_ids.insert(event_id) {
if let Err(_) = event_stream.send(event).await {
error!("Receiver dropped.");
return;
}
}
}
} else if let None = api_result {
@ -97,6 +109,7 @@ impl<'a> GithubCtl<'a> {
} else {
error!("Unsupported JSON type.");
}
should_notify = true;
}
});
}

@ -1,4 +1,6 @@
mod github_endpoint_watcher;
mod githubctl;
mod pull_request_event;
pub use githubctl::GithubCtl;
pub use pull_request_event::PullRequestEvent;

@ -0,0 +1,57 @@
use crate::json_util::get_json_object;
use crate::json_util::get_json_string;
pub struct PullRequestEvent<'a> {
original_event: &'a serde_json::Value,
pub action: &'a String,
pub html_url: &'a String,
pub state: &'a String,
pub title: &'a String,
}
impl<'a> PullRequestEvent<'a> {
pub fn new(original_event: &'a serde_json::Value) -> Result<Self, Box<dyn std::error::Error>> {
let payload = original_event
.get("payload")
.map(get_json_object)
.expect("Ran into a PullRequestEvent without a payload.");
let payload_action = payload
.get("action")
.map(get_json_string)
.expect("Ran into a PullRequestEvent without a payload.action.");
let payload_pull_request = payload
.get("pull_request")
.map(get_json_object)
.expect("Ran into a PullRequestEvent without a payload.pull_request.");
let payload_pull_request_html_url = payload_pull_request
.get("html_url")
.map(get_json_string)
.expect("Ran into a PullRequestEvent without a payload.pull_request.html_url.");
let payload_pull_request_state = payload_pull_request
.get("state")
.map(get_json_string)
.expect("Ran into a PullRequestEvent without a payload.pull_request.state.");
let payload_pull_request_title = payload_pull_request
.get("title")
.map(get_json_string)
.expect("Ran into a PullRequestEvent without a payload.pull_request.title.");
Ok(PullRequestEvent {
original_event,
action: payload_action,
html_url: payload_pull_request_html_url,
state: payload_pull_request_state,
title: payload_pull_request_title,
})
}
pub fn is_a(event: &'a serde_json::Value) -> Result<bool, Box<dyn std::error::Error>> {
let event_type = event.get("type").map(get_json_string);
match event_type {
Some(event_type_string) if event_type_string == "PullRequestEvent" => {
return Ok(true);
}
_ => Ok(false),
}
}
}

@ -0,0 +1,23 @@
use serde_json::{self, Map};
pub fn get_json_object(obj: &serde_json::Value) -> &Map<String, serde_json::Value> {
match obj {
serde_json::Value::Null => panic!("Unexpected json type"),
serde_json::Value::Bool(_) => panic!("Unexpected json type"),
serde_json::Value::Number(_) => panic!("Unexpected json type"),
serde_json::Value::String(_) => panic!("Unexpected json type"),
serde_json::Value::Array(_) => panic!("Unexpected json type"),
serde_json::Value::Object(event_object) => event_object,
}
}
pub fn get_json_string(str: &serde_json::Value) -> &String {
match str {
serde_json::Value::Null => panic!("Unexpected json type"),
serde_json::Value::Bool(_) => panic!("Unexpected json type"),
serde_json::Value::Number(_) => panic!("Unexpected json type"),
serde_json::Value::String(txt) => txt,
serde_json::Value::Array(_) => panic!("Unexpected json type"),
serde_json::Value::Object(_) => panic!("Unexpected json type"),
}
}

@ -2,7 +2,10 @@
extern crate log;
mod githubctl;
mod json_util;
use githubctl::PullRequestEvent;
use notify_rust::{Hint, Notification};
use serde_json;
const USERNAME: &'static str = include_str!("../.username");
@ -17,6 +20,35 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
github.watch_repo(ORG, REPO).await?;
loop {
let event = github.get_event().await?;
println!("{}", serde_json::to_string(&event)?);
// println!("{}", serde_json::to_string(&event)?);
handle_event(event)?;
}
}
fn handle_event(json_event: serde_json::Value) -> Result<(), Box<dyn std::error::Error>> {
if PullRequestEvent::is_a(&json_event)? {
let event = PullRequestEvent::new(&json_event)?;
if event.action == "opened" {
// println!("PullRequestEvent action {}", event.action);
println!("{}", serde_json::to_string(&json_event)?);
let notification_body = format!("Pull Request opened: {}", event.title);
Notification::new()
.summary("Pull request opened.")
.body(notification_body.as_str())
// .icon("can be a full path to an image file")
.appname("github_watcher")
.hint(Hint::Category("im.received".to_owned()))
.hint(Hint::Resident(true))
.timeout(0)
.show()?
.wait_for_action(|action| match action {
"default" => info!("you clicked \"default\""),
"clicked" => info!("that was correct"),
// here "__closed" is a hard coded keyword
"__closed" => info!("the notification was closed"),
_ => info!("Unrecognized action {}", action),
});
}
}
Ok(())
}

Loading…
Cancel
Save