~ciriarte/apizotl

82394162010af7cfb5bc8d5bbabd5b0ed8b6e30e — Carlos Iriarte 2 years ago faedbd8
feat: add other command stubs
11 files changed, 837 insertions(+), 111 deletions(-)

M .gitignore
M Cargo.lock
M Cargo.toml
A README.md
A rustfmt.toml
A src/deputies.rs
A src/dof.rs
M src/main.rs
A src/opt.rs
A src/presidents.rs
A src/senators.rs
M .gitignore => .gitignore +1 -0
@@ 1,1 1,2 @@
/target
**/*.rs.bk
\ No newline at end of file

M Cargo.lock => Cargo.lock +536 -11
@@ 1,6 1,21 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "addr2line"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c0929d69e78dd9bf5408269919fcbcaeb2e35e5d43e5815517cdc6a8e11a423"
dependencies = [
 "gimli",
]

[[package]]
name = "adler"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"

[[package]]
name = "aho-corasick"
version = "0.7.15"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 10,12 25,185 @@ dependencies = [
]

[[package]]
name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
dependencies = [
 "winapi 0.3.9",
]

[[package]]
name = "apizotl"
version = "0.1.0"
dependencies = [
 "async-std",
 "colored",
 "failure",
 "kuchiki",
 "regex",
 "reqwest",
 "serde",
 "serde_json",
 "structopt",
]

[[package]]
name = "async-channel"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59740d83946db6a5af71ae25ddf9562c2b176b2ca42cf99a455f09f4a220d6b9"
dependencies = [
 "concurrent-queue",
 "event-listener",
 "futures-core",
]

[[package]]
name = "async-executor"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb877970c7b440ead138f6321a3b5395d6061183af779340b65e20c0fede9146"
dependencies = [
 "async-task",
 "concurrent-queue",
 "fastrand",
 "futures-lite",
 "once_cell",
 "vec-arena",
]

[[package]]
name = "async-global-executor"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73079b49cd26b8fd5a15f68fc7707fc78698dc2a3d61430f2a7a9430230dfa04"
dependencies = [
 "async-executor",
 "async-io",
 "futures-lite",
 "num_cpus",
 "once_cell",
]

[[package]]
name = "async-io"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9315f8f07556761c3e48fec2e6b276004acf426e6dc068b2c2251854d65ee0fd"
dependencies = [
 "concurrent-queue",
 "fastrand",
 "futures-lite",
 "libc",
 "log",
 "nb-connect",
 "once_cell",
 "parking",
 "polling",
 "vec-arena",
 "waker-fn",
 "winapi 0.3.9",
]

[[package]]
name = "async-mutex"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e"
dependencies = [
 "event-listener",
]

[[package]]
name = "async-process"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c8cea09c1fb10a317d1b5af8024eeba256d6554763e85ecd90ff8df31c7bbda"
dependencies = [
 "async-io",
 "blocking",
 "cfg-if 0.1.10",
 "event-listener",
 "futures-lite",
 "once_cell",
 "signal-hook",
 "winapi 0.3.9",
]

[[package]]
name = "async-std"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f9f84f1280a2b436a2c77c2582602732b6c2f4321d5494d6e799e6c367859a8"
dependencies = [
 "async-channel",
 "async-global-executor",
 "async-io",
 "async-mutex",
 "async-process",
 "blocking",
 "crossbeam-utils",
 "futures-channel",
 "futures-core",
 "futures-io",
 "futures-lite",
 "gloo-timers",
 "kv-log-macro",
 "log",
 "memchr",
 "num_cpus",
 "once_cell",
 "pin-project-lite 0.2.0",
 "pin-utils",
 "slab",
 "wasm-bindgen-futures",
]

[[package]]
name = "async-task"
version = "4.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0"

[[package]]
name = "atomic-waker"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a"

[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
 "hermit-abi",
 "libc",
 "winapi 0.3.9",
]

[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"

[[package]]
name = "backtrace"
version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef5140344c85b01f9bbb4d4b7288a8aa4b3287ccef913a14bcc78a1063623598"
dependencies = [
 "addr2line",
 "cfg-if 1.0.0",
 "libc",
 "miniz_oxide",
 "object",
 "rustc-demangle",
]

[[package]]
name = "base64"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 28,6 216,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"

[[package]]
name = "blocking"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5e170dbede1f740736619b776d7251cb1b9095c435c34d8ca9f57fcd2f335e9"
dependencies = [
 "async-channel",
 "async-task",
 "atomic-waker",
 "fastrand",
 "futures-lite",
 "once_cell",
]

[[package]]
name = "bumpalo"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 46,6 248,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"

[[package]]
name = "cache-padded"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba"

[[package]]
name = "cc"
version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 64,6 272,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"

[[package]]
name = "clap"
version = "2.33.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
dependencies = [
 "ansi_term",
 "atty",
 "bitflags",
 "strsim",
 "textwrap",
 "unicode-width",
 "vec_map",
]

[[package]]
name = "colored"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59"
dependencies = [
 "atty",
 "lazy_static",
 "winapi 0.3.9",
]

[[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.1"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 80,6 323,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b"

[[package]]
name = "crossbeam-utils"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
dependencies = [
 "autocfg",
 "cfg-if 1.0.0",
 "lazy_static",
]

[[package]]
name = "cssparser"
version = "0.27.2"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 142,6 396,43 @@ dependencies = [
]

[[package]]
name = "event-listener"
version = "2.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59"

[[package]]
name = "failure"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86"
dependencies = [
 "backtrace",
 "failure_derive",
]

[[package]]
name = "failure_derive"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
dependencies = [
 "proc-macro2",
 "quote",
 "syn",
 "synstructure",
]

[[package]]
name = "fastrand"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca5faf057445ce5c9d4329e382b2ce7ca38550ef3b73a5348362d5f24e0c7fe3"
dependencies = [
 "instant",
]

[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 220,6 511,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "611834ce18aaa1bd13c4b374f5d653e1027cf99b6b502584ff8c9a64413b30bb"

[[package]]
name = "futures-lite"
version = "1.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4481d0cd0de1d204a4fa55e7d45f07b1d958abcb06714b3446438e2eff695fb"
dependencies = [
 "fastrand",
 "futures-core",
 "futures-io",
 "memchr",
 "parking",
 "pin-project-lite 0.2.0",
 "waker-fn",
]

[[package]]
name = "futures-sink"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 270,6 576,25 @@ dependencies = [
]

[[package]]
name = "gimli"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce"

[[package]]
name = "gloo-timers"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47204a46aaff920a1ea58b11d03dec6f704287d27561724a4631e450654a891f"
dependencies = [
 "futures-channel",
 "futures-core",
 "js-sys",
 "wasm-bindgen",
 "web-sys",
]

[[package]]
name = "h2"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 296,6 621,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"

[[package]]
name = "heck"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac"
dependencies = [
 "unicode-segmentation",
]

[[package]]
name = "hermit-abi"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 410,6 744,15 @@ dependencies = [
]

[[package]]
name = "instant"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
dependencies = [
 "cfg-if 1.0.0",
]

[[package]]
name = "iovec"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 462,6 805,15 @@ dependencies = [
]

[[package]]
name = "kv-log-macro"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f"
dependencies = [
 "log",
]

[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 518,17 870,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"

[[package]]
name = "mexico"
version = "0.1.0"
dependencies = [
 "kuchiki",
 "regex",
 "reqwest",
 "serde",
 "serde_json",
]

[[package]]
name = "mime"
version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 545,6 886,16 @@ dependencies = [
]

[[package]]
name = "miniz_oxide"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d"
dependencies = [
 "adler",
 "autocfg",
]

[[package]]
name = "mio"
version = "0.6.23"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 594,6 945,16 @@ dependencies = [
]

[[package]]
name = "nb-connect"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8123a81538e457d44b933a02faf885d3fe8408806b23fa700e8f01c6c3a98998"
dependencies = [
 "libc",
 "winapi 0.3.9",
]

[[package]]
name = "net2"
version = "0.2.37"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 627,6 988,12 @@ dependencies = [
]

[[package]]
name = "object"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397"

[[package]]
name = "once_cell"
version = "1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 666,6 1033,12 @@ dependencies = [
]

[[package]]
name = "parking"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72"

[[package]]
name = "percent-encoding"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 790,6 1163,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"

[[package]]
name = "polling"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2a7bc6b2a29e632e45451c941832803a18cce6781db04de8a04696cdca8bde4"
dependencies = [
 "cfg-if 0.1.10",
 "libc",
 "log",
 "wepoll-sys",
 "winapi 0.3.9",
]

[[package]]
name = "ppv-lite86"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 802,6 1188,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"

[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
 "proc-macro-error-attr",
 "proc-macro2",
 "quote",
 "syn",
 "version_check",
]

[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
 "proc-macro2",
 "quote",
 "version_check",
]

[[package]]
name = "proc-macro-hack"
version = "0.5.19"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 945,6 1355,12 @@ dependencies = [
]

[[package]]
name = "rustc-demangle"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232"

[[package]]
name = "ryu"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1057,6 1473,25 @@ dependencies = [
]

[[package]]
name = "signal-hook"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e31d442c16f047a671b5a71e2161d6e68814012b7f5379d269ebd915fac2729"
dependencies = [
 "libc",
 "signal-hook-registry",
]

[[package]]
name = "signal-hook-registry"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6"
dependencies = [
 "libc",
]

[[package]]
name = "siphasher"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1117,6 1552,36 @@ dependencies = [
]

[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"

[[package]]
name = "structopt"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5277acd7ee46e63e5168a80734c9f6ee81b1367a7d8772a2d765df2a3705d28c"
dependencies = [
 "clap",
 "lazy_static",
 "structopt-derive",
]

[[package]]
name = "structopt-derive"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ba9cdfda491b814720b6b06e0cac513d922fc407582032e8706e9f137976f90"
dependencies = [
 "heck",
 "proc-macro-error",
 "proc-macro2",
 "quote",
 "syn",
]

[[package]]
name = "syn"
version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1128,6 1593,18 @@ dependencies = [
]

[[package]]
name = "synstructure"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
dependencies = [
 "proc-macro2",
 "quote",
 "syn",
 "unicode-xid",
]

[[package]]
name = "tempfile"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1153,6 1630,15 @@ dependencies = [
]

[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
 "unicode-width",
]

[[package]]
name = "thin-slice"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1295,6 1781,18 @@ dependencies = [
]

[[package]]
name = "unicode-segmentation"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"

[[package]]
name = "unicode-width"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"

[[package]]
name = "unicode-xid"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1325,12 1823,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb"

[[package]]
name = "vec-arena"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eafc1b9b2dfc6f5529177b62cf806484db55b32dc7c9658a118e11bbeb33061d"

[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"

[[package]]
name = "version_check"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"

[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1425,6 1941,15 @@ dependencies = [
]

[[package]]
name = "wepoll-sys"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fcb14dea929042224824779fbc82d9fab8d2e6d3cbc0ac404de8edf489e77ff"
dependencies = [
 "cc",
]

[[package]]
name = "winapi"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"

M Cargo.toml => Cargo.toml +8 -2
@@ 1,5 1,5 @@
[package]
name = "mexico"
name = "apizotl"
version = "0.1.0"
authors = ["Carlos Iriarte <me@carlosiriarte.com>"]
edition = "2018"


@@ 11,4 11,10 @@ reqwest= { version = "0.10.0-alpha.2", features = ["blocking"] }
kuchiki= "*"
regex = { version = "1.4.2" }
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0" }
\ No newline at end of file
serde_json = { version = "1.0" }

async-std = { version = "1.0", features = ['unstable'] }

colored = "1.9"
failure = "0.1"
structopt = "0.3"
\ No newline at end of file

A README.md => README.md +0 -0
A rustfmt.toml => rustfmt.toml +2 -0
@@ 0,0 1,2 @@
edition = "2018"
merge_imports = true
\ No newline at end of file

A src/deputies.rs => src/deputies.rs +5 -0
@@ 0,0 1,5 @@
use crate::opt::Opt;

pub fn run(_opts: Opt) {

}
\ No newline at end of file

A src/dof.rs => src/dof.rs +0 -0
M src/main.rs => src/main.rs +22 -98
@@ 1,106 1,30 @@
use std::error::Error;
use colored::Colorize;
use failure::Error;

use kuchiki::traits::*;
use regex::Regex;
mod opt;
mod presidents;
mod senators;
mod deputies;

use serde::{Deserialize, Serialize};
use crate::opt::OutputType;

#[derive(Serialize, Deserialize, Debug)]
struct Person {
    name: String,
    dob: i32,
    #[serde(skip_serializing_if = "Option::is_none")]
    dod: Option<i32>,
    img: String,
    start: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    end: Option<String>,
}

fn main() -> std::result::Result<(), Box<dyn Error>> {
    let url = "https://en.wikipedia.org/wiki/List_of_heads_of_state_of_Mexico";

    let mut res = reqwest::blocking::get(url)?;

    let mut buf: Vec<u8> = vec![];
    res.copy_to(&mut buf)?;
    let s: String = String::from_utf8(buf)?;

    let mut presidents: Vec<Person> = vec![];
    let table_selector = ".wikitable:not(:last-of-type)";
    let document = kuchiki::parse_html().one(s);
    for table_match in document.select(table_selector).unwrap() {
        let name_pattern = Regex::new(r"(?:^\s+\d+\W+)([A-zÁ-ÿ\s]{2,})(?:\s\s|\()").unwrap();
        let dob_pattern = Regex::new(r"\((?:(?:born\s)?(\d+))?(?:–\d+)?\)").unwrap();
        let dod_pattern = Regex::new(r"\(\d+–(\d+)\)").unwrap();
        let tenure_pattern =
            Regex::new(r"(\w+\s\d+,\s+\d+)\s*((?:\w+\s\d+,\s+\d+)|Incumbent)?").unwrap();

        let node = table_match.as_node();
        for row_match in node.select("tr:not(:first-child)").unwrap() {
            let text = row_match.text_contents().replace("\n", " ");

            let img = row_match.as_node().select_first("img");

            let img = if let Ok(i) = img {
                i.attributes
                    .borrow()
                    .get("src")
                    .unwrap_or_default()
                    .to_string()
            } else {
                "".to_string()
            };

            let img = img
                .replace("thumb/", "")
                .rsplitn(2, '/')
                .last()
                .unwrap_or_default()
                .to_string();
const VERSION: &str = env!("CARGO_PKG_VERSION");

            let caps = name_pattern.captures(&text);
            if caps.is_none() {
                continue;
            }
            let name = caps.unwrap().get(1).unwrap().as_str();
fn main() {
    let output_type = crate::opt::parse_opts();

            let caps = dob_pattern.captures(&text).unwrap();
            let dob = caps.get(1).unwrap().as_str();

            let caps = dod_pattern.captures(&text);
            let dod = if let Some(x) = caps {
                let dod_str  = x.get(1).unwrap().as_str();
                Some(dod_str.parse::<i32>().unwrap())
            } else {
                None
            };

            let caps = tenure_pattern.captures(&text).unwrap();
            let start = caps.get(1).unwrap().as_str();

            let end = if let Some(x) = caps.get(2) {
                Some(x.as_str().to_string())
            } else {
                None
            };

            let person = Person {
                name: name.to_string(),
                dob: dob.parse::<i32>().unwrap(),
                dod,
                start: start.to_string(),
                end,
                img: format!("https:{}", img),
            };

            presidents.push(person);
        }
    match output_type {
        OutputType::Presidents(opts) => crate::presidents::run(opts),
        OutputType::Senators(opts) => crate::senators::run(opts),
        OutputType::Deputies(opts) => crate::deputies::run(opts),
    }
}

    let j = serde_json::to_string(&presidents)?;

    println!("{}", j);

    Ok(())
pub fn log_error(e: &Error) {
    let error_colored = "ERROR".red();
    eprintln!("\n{}: {}", error_colored, e);
    for cause in e.iter_causes() {
        let caused_colored = "Caused by:".yellow();
        eprintln!("\n{} {}", caused_colored, cause);
    }
}

A src/opt.rs => src/opt.rs +39 -0
@@ 0,0 1,39 @@
use structopt::{clap::AppSettings::DeriveDisplayOrder, StructOpt};

use crate::VERSION;

#[derive(StructOpt, Debug, Clone)]
#[structopt(
    name = "apizotl",
    about = "Means \"glutton\" in Nahuatl, the Aztec's language. Eats raw data and organizes as an API",
    version = VERSION,
    author = "ciriarte <me@ciriarte.dev>",
    setting = DeriveDisplayOrder,
)]
pub struct Opt {
    #[structopt(subcommand)]
    pub command: Command,
}

#[derive(StructOpt, Debug, PartialEq, Clone)]
pub enum Command {
    Presidents,
    Deputies,
    Senators,
}

pub fn parse_opts() -> OutputType {
    let opts = Opt::from_args();

    match opts.command {
        Command::Presidents { .. } => OutputType::Presidents(opts),
        Command::Deputies { .. } => OutputType::Deputies(opts),
        Command::Senators { .. } => OutputType::Senators(opts),
    }
}

pub enum OutputType {
    Presidents(Opt),
    Deputies(Opt),
    Senators(Opt),
}
\ No newline at end of file

A src/presidents.rs => src/presidents.rs +120 -0
@@ 0,0 1,120 @@
use kuchiki::traits::*;
use regex::Regex;

use serde::{Deserialize, Serialize};
use async_std::{process, task};
use failure::Error;

use crate::{
    log_error,
    opt::Opt,
};

#[derive(Serialize, Deserialize, Debug)]
struct Person {
    name: String,
    dob: i32,
    #[serde(skip_serializing_if = "Option::is_none")]
    dod: Option<i32>,
    img: String,
    start: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    end: Option<String>,
}

pub fn run(opts: Opt) {
    task::block_on(async {
        if let Err(e) = process(&opts).await {
            log_error(&e);
            process::exit(1);
        };
    });
}

async fn process(_opts: &Opt) -> std::result::Result<(), Error> {
    let url = "https://en.wikipedia.org/wiki/List_of_heads_of_state_of_Mexico";

    let mut res = reqwest::blocking::get(url)?;

    let mut buf: Vec<u8> = vec![];
    res.copy_to(&mut buf)?;
    let s: String = String::from_utf8(buf)?;

    let mut presidents: Vec<Person> = vec![];
    let table_selector = ".wikitable:not(:last-of-type)";
    let document = kuchiki::parse_html().one(s);
    for table_match in document.select(table_selector).unwrap() {
        let name_pattern = Regex::new(r"(?:^\s+\d+\W+)([A-zÁ-ÿ\s]{2,})(?:\s\s|\()").unwrap();
        let dob_pattern = Regex::new(r"\((?:(?:born\s)?(\d+))?(?:–\d+)?\)").unwrap();
        let dod_pattern = Regex::new(r"\(\d+–(\d+)\)").unwrap();
        let tenure_pattern =
            Regex::new(r"(\w+\s\d+,\s+\d+)\s*((?:\w+\s\d+,\s+\d+)|Incumbent)?").unwrap();

        let node = table_match.as_node();
        for row_match in node.select("tr:not(:first-child)").unwrap() {
            let text = row_match.text_contents().replace("\n", " ");

            let img = row_match.as_node().select_first("img");

            let img = if let Ok(i) = img {
                i.attributes
                    .borrow()
                    .get("src")
                    .unwrap_or_default()
                    .to_string()
            } else {
                "".to_string()
            };

            let img = img
                .replace("thumb/", "")
                .rsplitn(2, '/')
                .last()
                .unwrap_or_default()
                .to_string();

            let caps = name_pattern.captures(&text);
            if caps.is_none() {
                continue;
            }
            let name = caps.unwrap().get(1).unwrap().as_str();

            let caps = dob_pattern.captures(&text).unwrap();
            let dob = caps.get(1).unwrap().as_str();

            let caps = dod_pattern.captures(&text);
            let dod = if let Some(x) = caps {
                let dod_str  = x.get(1).unwrap().as_str();
                Some(dod_str.parse::<i32>().unwrap())
            } else {
                None
            };

            let caps = tenure_pattern.captures(&text).unwrap();
            let start = caps.get(1).unwrap().as_str();

            let end = if let Some(x) = caps.get(2) {
                Some(x.as_str().to_string())
            } else {
                None
            };

            let person = Person {
                name: name.to_string(),
                dob: dob.parse::<i32>().unwrap(),
                dod,
                start: start.to_string(),
                end,
                img: format!("https:{}", img),
            };

            presidents.push(person);
        }
    }

    let j = serde_json::to_string(&presidents)?;

    println!("{}", j);

    Ok(())
}

A src/senators.rs => src/senators.rs +104 -0
@@ 0,0 1,104 @@
use async_std::{process, task};
use failure::Error;

use kuchiki::traits::*;

use crate::{log_error, opt::Opt};

use reqwest::Url;

pub fn run(opts: Opt) {
    task::block_on(async {
        if let Err(e) = process(&opts).await {
            log_error(&e);
            process::exit(1);
        };
    });
}

async fn process(_opts: &Opt) -> std::result::Result<(), Error> {
    let url = 
        Url::parse(
            "https://es.wikipedia.org/wiki/Anexo:Congresos_y_Legislaturas_del_Congreso_de_la_Uni%C3%B3n_de_M%C3%A9xico"
        )?;

    let mut res = reqwest::blocking::get(url.to_owned())?;

    let mut buf: Vec<u8> = vec![];
    res.copy_to(&mut buf)?;
    let s: String = String::from_utf8(buf)?;

    let table_selector = ".wikitable";
    let document = kuchiki::parse_html().one(s);

    for table_match in document.select(table_selector).unwrap() {
        let node = table_match.as_node();
        for a in node.select("td:first-child a").unwrap() {
            let href = a
                .attributes
                .borrow()
                .get("href")
                .unwrap_or_default()
                .to_string();

            let link = if href.starts_with("/wiki") {
                let link_str =
                    format!("{}://{}{}", url.scheme(), url.host_str().unwrap(), href).to_string();
                Some(link_str)
            } else {
                None
            };

            match link {
                Some(l) => extract(l)?,
                None => {}
            }
        }
    }

    Ok(())
}

fn extract(link: String) -> std::result::Result<(), Error> {
    println!("{:?}", link);
    let url = Url::parse(&link)?;

    let mut res = reqwest::blocking::get(url.to_owned())?;

    let mut buf: Vec<u8> = vec![];
    res.copy_to(&mut buf)?;
    let s: String = String::from_utf8(buf)?;

    let document = kuchiki::parse_html().one(s);
    let h3_list = document.select("h3").unwrap();

    for h3 in h3_list.filter_map(|h| with_title(h, "Diputados por".to_string())) {
        let table = h3.as_node().next_sibling().unwrap().next_sibling().unwrap();
        println!("  {:?}", h3.as_node().text_contents());
        for tr in table.select("tr:not(:first-child)").unwrap() {
            print!("      ");
            for td in tr.as_node().select("td:not(:nth-child(n+4))").unwrap() {
                print!("{:?} ", td.as_node().text_contents());
            }
            println!();
            print!("      ");
            for td in tr.as_node().select("td:nth-child(n+4)").unwrap() {
                print!("{:?} ", td.as_node().text_contents());
            }
            println!();
        }
    }

    Ok(())
}

fn with_title(
    h: kuchiki::NodeDataRef<kuchiki::ElementData>,
    title: String,
) -> Option<kuchiki::NodeDataRef<kuchiki::ElementData>> {
    if h.text_contents().starts_with(&title) {
        Some(h)
    } else {
        None
    }
}