Pull private messages only to self.

- I am experimenting with using these as private notes.
This commit is contained in:
Thomas Gideon 2023-07-25 17:08:34 -04:00
parent 6bc62f52cd
commit 8a9a3174ab
4 changed files with 220 additions and 149 deletions

2
.gitignore vendored
View file

@ -15,3 +15,5 @@ target/
# Added by cargo # Added by cargo
/target /target
.envrc

174
Cargo.lock generated
View file

@ -92,19 +92,19 @@ dependencies = [
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.71" version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854"
[[package]] [[package]]
name = "async-trait" name = "async-trait"
version = "0.1.71" version = "0.1.72"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a564d521dd56509c4c47480d00b80ee55f7e385ae48db5744c67ad50c92d2ebf" checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.25", "syn 2.0.27",
] ]
[[package]] [[package]]
@ -228,9 +228,9 @@ dependencies = [
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.3.12" version = "4.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3eab9e8ceb9afdade1ab3f0fd8dbce5b1b2f468ad653baf10e771781b2b67b73" checksum = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
"clap_derive", "clap_derive",
@ -239,9 +239,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_builder" name = "clap_builder"
version = "4.3.12" version = "4.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f2763db829349bf00cfc06251268865ed4363b93a943174f638daf3ecdba2cd" checksum = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1"
dependencies = [ dependencies = [
"anstream", "anstream",
"anstyle", "anstyle",
@ -258,7 +258,7 @@ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.25", "syn 2.0.27",
] ]
[[package]] [[package]]
@ -481,12 +481,9 @@ dependencies = [
[[package]] [[package]]
name = "fastrand" name = "fastrand"
version = "1.9.0" version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"
dependencies = [
"instant",
]
[[package]] [[package]]
name = "fd-lock" name = "fd-lock"
@ -495,7 +492,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef033ed5e9bad94e55838ca0ca906db0e043f517adda0c8b79c7a8c66c93c1b5" checksum = "ef033ed5e9bad94e55838ca0ca906db0e043f517adda0c8b79c7a8c66c93c1b5"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"rustix 0.38.4", "rustix",
"windows-sys", "windows-sys",
] ]
@ -568,7 +565,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.25", "syn 2.0.27",
] ]
[[package]] [[package]]
@ -849,26 +846,6 @@ dependencies = [
"hashbrown", "hashbrown",
] ]
[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if",
]
[[package]]
name = "io-lifetimes"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
dependencies = [
"hermit-abi",
"libc",
"windows-sys",
]
[[package]] [[package]]
name = "ipnet" name = "ipnet"
version = "2.8.0" version = "2.8.0"
@ -882,15 +859,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
dependencies = [ dependencies = [
"hermit-abi", "hermit-abi",
"rustix 0.38.4", "rustix",
"windows-sys", "windows-sys",
] ]
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.8" version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a" checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]] [[package]]
name = "jni" name = "jni"
@ -953,12 +930,6 @@ version = "0.2.147"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
[[package]]
name = "linux-raw-sys"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
[[package]] [[package]]
name = "linux-raw-sys" name = "linux-raw-sys"
version = "0.4.3" version = "0.4.3"
@ -1015,9 +986,9 @@ dependencies = [
[[package]] [[package]]
name = "megalodon" name = "megalodon"
version = "0.8.7" version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6715f17d5f0686ebf32cbf0731139d2abd068e0502fd1c7d20688044176f0839" checksum = "8041cc58b39d60da6d92aa9f255a80a20a39d6cb528a2b01b60fbc25357aa244"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"chrono", "chrono",
@ -1133,9 +1104,9 @@ dependencies = [
[[package]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.15" version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
dependencies = [ dependencies = [
"autocfg", "autocfg",
] ]
@ -1208,7 +1179,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.25", "syn 2.0.27",
] ]
[[package]] [[package]]
@ -1328,9 +1299,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.64" version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78803b62cbf1f46fde80d7c0e803111524b9877184cfe7c3033659490ac7a7da" checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@ -1347,9 +1318,9 @@ dependencies = [
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.29" version = "1.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -1510,20 +1481,6 @@ version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
name = "rustix"
version = "0.37.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06"
dependencies = [
"bitflags 1.3.2",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys 0.3.8",
"windows-sys",
]
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.38.4" version = "0.38.4"
@ -1533,7 +1490,7 @@ dependencies = [
"bitflags 2.3.3", "bitflags 2.3.3",
"errno", "errno",
"libc", "libc",
"linux-raw-sys 0.4.3", "linux-raw-sys",
"windows-sys", "windows-sys",
] ]
@ -1593,9 +1550,9 @@ dependencies = [
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.14" version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
[[package]] [[package]]
name = "same-file" name = "same-file"
@ -1617,9 +1574,9 @@ dependencies = [
[[package]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.1.0" version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]] [[package]]
name = "sct" name = "sct"
@ -1633,9 +1590,9 @@ dependencies = [
[[package]] [[package]]
name = "security-framework" name = "security-framework"
version = "2.9.1" version = "2.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de"
dependencies = [ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
"core-foundation", "core-foundation",
@ -1646,9 +1603,9 @@ dependencies = [
[[package]] [[package]]
name = "security-framework-sys" name = "security-framework-sys"
version = "2.9.0" version = "2.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a"
dependencies = [ dependencies = [
"core-foundation-sys", "core-foundation-sys",
"libc", "libc",
@ -1656,29 +1613,29 @@ dependencies = [
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.171" version = "1.0.175"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9" checksum = "5d25439cd7397d044e2748a6fe2432b5e85db703d6d097bd014b3c0ad1ebff0b"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.171" version = "1.0.175"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682" checksum = "b23f7ade6f110613c0d63858ddb8b94c1041f550eab58a16b371bdf2c9c80ab4"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.25", "syn 2.0.27",
] ]
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.102" version = "1.0.103"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5062a995d481b2308b6064e9af76011f2921c35f97b0468811ed9f6cd91dfed" checksum = "d03b412469450d4404fe8499a268edd7f8b79fecb074b0d812ad64ca21f4031b"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@ -1687,9 +1644,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_path_to_error" name = "serde_path_to_error"
version = "0.1.13" version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8acc4422959dd87a76cb117c191dcbffc20467f06c9100b76721dab370f24d3a" checksum = "4beec8bce849d58d06238cb50db2e1c417cfeafa4c63f692b15c82b7c80f8335"
dependencies = [ dependencies = [
"itoa", "itoa",
"serde", "serde",
@ -1832,9 +1789,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.25" version = "2.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15e3fc8c0c74267e2df136e5e5fb656a464158aa57624053375eb9c8c6e25ae2" checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1843,15 +1800,14 @@ dependencies = [
[[package]] [[package]]
name = "tempfile" name = "tempfile"
version = "3.6.0" version = "3.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" checksum = "5486094ee78b2e5038a6382ed7645bc084dc2ec433426ca4c3cb61e2007b8998"
dependencies = [ dependencies = [
"autocfg",
"cfg-if", "cfg-if",
"fastrand", "fastrand",
"redox_syscall", "redox_syscall",
"rustix 0.37.23", "rustix",
"windows-sys", "windows-sys",
] ]
@ -1877,22 +1833,22 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.43" version = "1.0.44"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.43" version = "1.0.44"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.25", "syn 2.0.27",
] ]
[[package]] [[package]]
@ -1949,7 +1905,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.25", "syn 2.0.27",
] ]
[[package]] [[package]]
@ -1985,9 +1941,9 @@ dependencies = [
[[package]] [[package]]
name = "tokio-tungstenite" name = "tokio-tungstenite"
version = "0.19.0" version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec509ac96e9a0c43427c74f003127d953a265737636129424288d27cb5c4b12c" checksum = "2b2dbec703c26b00d74844519606ef15d09a7d6857860f84ad223dec002ddea2"
dependencies = [ dependencies = [
"futures-util", "futures-util",
"log", "log",
@ -2045,9 +2001,9 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
[[package]] [[package]]
name = "tungstenite" name = "tungstenite"
version = "0.19.0" version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15fba1a6d6bb030745759a9a2a588bfe8490fc8b4751a277db3a0be1c9ebbf67" checksum = "e862a1c4128df0112ab625f55cd5c934bcb4312ba80b39ae4b4835a3fd58e649"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"bytes", "bytes",
@ -2086,9 +2042,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.10" version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
[[package]] [[package]]
name = "unicode-normalization" name = "unicode-normalization"
@ -2141,9 +2097,9 @@ dependencies = [
[[package]] [[package]]
name = "urlencoding" name = "urlencoding"
version = "2.1.2" version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8db7427f936968176eaa7cdf81b7f98b980b18495ec28f1b5791ac3bfe3eea9" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
[[package]] [[package]]
name = "utf-8" name = "utf-8"
@ -2221,7 +2177,7 @@ dependencies = [
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.25", "syn 2.0.27",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -2255,7 +2211,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.25", "syn 2.0.27",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]

View file

@ -13,17 +13,23 @@ use url_open::UrlOpen;
pub(super) async fn format_status( pub(super) async fn format_status(
client: &Box<dyn Megalodon + Send + Sync>, client: &Box<dyn Megalodon + Send + Sync>,
depth: usize,
account: &Account, account: &Account,
status: &Status, status: &Status,
) -> Result<String> { ) -> Result<String> {
let time_prefix = quote_prefix(0);
let ancestor_prefix = quote_prefix(depth);
let ancestor = format!( let ancestor = format!(
"{} "{time_prefix}{timestamp}
> {}{}", {ancestor_prefix}{status}{attachments}",
status.created_at.with_timezone(&Local).format("%H:%M"), time_prefix = time_prefix,
apply_block_quote(1, (&status.content).trim()), timestamp = status.created_at.with_timezone(&Local).format("%H:%M"),
format_attachments(1, &status.media_attachments) ancestor_prefix = ancestor_prefix,
status = apply_block_quote(depth, (&status.content).trim()),
attachments = format_attachments(depth, &status.media_attachments)
); );
let Response { json, .. } = client.get_status_context(status.id.clone(), None).await?; let Response { json, .. } = client.get_status_context(status.id.clone(), None).await?;
let descendant_prefix = quote_prefix(depth + 1);
let thread = json let thread = json
.descendants .descendants
.into_iter() .into_iter()
@ -32,12 +38,14 @@ pub(super) async fn format_status(
}) })
.map(|status| { .map(|status| {
format!( format!(
"> "{ancestor_prefix}
> {} {ancestor_prefix}{timestamp}
>> {}{}", {descendant_prefix}{status}{attachments}",
status.created_at.with_timezone(&Local).format("%H:%M"), ancestor_prefix = ancestor_prefix,
apply_block_quote(2, parse_html(&status.content).trim()), timestamp = status.created_at.with_timezone(&Local).format("%H:%M"),
format_attachments(2, &status.media_attachments) descendant_prefix = descendant_prefix,
status = apply_block_quote(depth + 1, parse_html(&status.content).trim()),
attachments = format_attachments(depth + 1, &status.media_attachments)
) )
}) })
.collect::<Vec<String>>() .collect::<Vec<String>>()
@ -54,7 +62,11 @@ pub(super) async fn format_status(
} }
fn quote_prefix(depth: usize) -> String { fn quote_prefix(depth: usize) -> String {
vec![">"; depth].join("") if depth == 0 {
String::default()
} else {
format!("{} ", vec![">"; depth].join(""))
}
} }
fn format_attachments(depth: usize, attachments: &[Attachment]) -> String { fn format_attachments(depth: usize, attachments: &[Attachment]) -> String {
@ -94,7 +106,7 @@ fn apply_block_quote<S: AsRef<str>>(depth: usize, content: S) -> String {
let content = content.replace("<p>", ""); let content = content.replace("<p>", "");
let content = content.replace("</p>", ""); let content = content.replace("</p>", "");
// replace separately to avoid trailing spaces when replacing empty lines with the prefix // replace separately to avoid trailing spaces when replacing empty lines with the prefix
let content = empty.replace_all(content.as_ref(), format!("\n{}\n", prefix)); let content = empty.replace_all(content.as_ref(), format!("\n{}\n", prefix.trim()));
let content = non_empty.replace_all(&content, |c: &Captures| { let content = non_empty.replace_all(&content, |c: &Captures| {
format!("\n{}{}", prefix, c["initial"].to_string()) format!("\n{}{}", prefix, c["initial"].to_string())
}); });

View file

@ -3,9 +3,9 @@ use chrono::{DateTime, Local, Utc};
use clap::{arg, command, Parser}; use clap::{arg, command, Parser};
use log::{debug, trace}; use log::{debug, trace};
use megalodon::{ use megalodon::{
entities::{Account, Status}, entities::{Account, Status, StatusVisibility},
generator, generator,
megalodon::GetLocalTimelineInputOptions, megalodon::{GetAccountStatusesInputOptions, GetLocalTimelineInputOptions},
response::Response, response::Response,
Megalodon, Megalodon,
}; };
@ -80,38 +80,46 @@ async fn main() -> Result<()> {
trace!("Page bounds {:?}", page); trace!("Page bounds {:?}", page);
// this age comparison only applies after the first page is fetched; the rest of the loop let (last_id, next_iter, mut formatted) =
// body handles if the requested date is newer than any statuses on the first page process_page(&client, &account, &statuses, &last_id_on_page, &day, 1).await?;
if last_id_on_page.is_some() && page_start_older_than(&page, &day) { reversed.append(&mut formatted);
if let Some(NextIter::Stop) = next_iter {
break; break;
} }
if let Some(last_id) = last_id {
// fetching returns 20 at a time, in reverse chronological order so may require skipping last_id_on_page.replace(last_id);
// pages after the requested date }
if let Some(oldest_id) = page_newer_than(&page, &day) { if let Some(NextIter::Skip) = next_iter {
last_id_on_page.replace(oldest_id);
continue; continue;
} }
// mapping the vector runs into thorny ownership issues and only produces futures, not
// resolved values; a for in loop works with await but also runs into thorny ownership
// issues; a stream resolves both because the stream takes ownership of the statuses and
// can be iterated in a simple way that allows the use of await in the body
let mut stream = iter(filter_statuses(&account, &day, &statuses));
while let Some(status) = stream.next().await {
reversed.push(format_status(&client, &account, status).await?);
} }
last_id_on_page = None;
if page_end_older_than(&page, &day) { loop {
debug!("No more posts in range."); let statuses = fetch_dm_page(&client, &account, &last_id_on_page).await?;
if statuses.is_empty() {
debug!("No more DMs in range.");
break; break;
} }
let page = bounds_from(&statuses);
if let Some(id) = page.oldest_id { trace!("Page bounds {:?}", page);
last_id_on_page.replace(id.clone());
let (last_id, next_iter, mut formatted) =
process_page(&client, &account, &statuses, &last_id_on_page, &day, 0).await?;
reversed.append(&mut formatted);
if let Some(NextIter::Stop) = next_iter {
break;
}
if let Some(last_id) = last_id {
last_id_on_page.replace(last_id);
}
if let Some(NextIter::Skip) = next_iter {
continue;
} }
} }
reversed.reverse(); reversed.reverse();
if let Some(output_dir) = output_dir { if let Some(output_dir) = output_dir {
let output = format!("{}{}.md", output_dir, date); let output = format!("{}{}.md", output_dir, date);
let mut f = File::options().append(true).open(&output)?; let mut f = File::options().append(true).open(&output)?;
@ -123,6 +131,57 @@ async fn main() -> Result<()> {
Ok(()) Ok(())
} }
enum NextIter {
Skip,
Stop,
}
async fn process_page(
client: &Box<dyn Megalodon + Send + Sync + 'static>,
account: &Account,
statuses: &Vec<Status>,
last_id_on_page: &Option<String>,
day: &Range,
depth: usize,
) -> Result<(Option<String>, Option<NextIter>, Vec<String>)> {
let page = bounds_from(&statuses);
trace!("Page bounds {:?}", page);
// this age comparison only applies after the first page is fetched; the rest of the loop
// body handles if the requested date is newer than any statuses on the first page
if last_id_on_page.is_some() && page_start_older_than(&page, day) {
return Ok((None, Some(NextIter::Stop), Vec::new()));
}
// fetching returns 20 at a time, in reverse chronological order so may require skipping
// pages after the requested date
if let Some(oldest_id) = page_newer_than(&page, &day) {
return Ok((Some(oldest_id), Some(NextIter::Skip), Vec::new()));
}
// mapping the vector runs into thorny ownership issues and only produces futures, not
// resolved values; a for in loop works with await but also runs into thorny ownership
// issues; a stream resolves both because the stream takes ownership of the statuses and
// can be iterated in a simple way that allows the use of await in the body
let mut stream = iter(filter_statuses(account, &day, &statuses));
let mut formatted = Vec::new();
while let Some(status) = stream.next().await {
formatted.push(format_status(client, depth, &account, status).await?);
}
if page_end_older_than(&page, &day) {
debug!("No more posts in range.");
return Ok((None, Some(NextIter::Stop), formatted));
}
if let Some(id) = page.oldest_id {
return Ok((Some(id.clone()), None, formatted));
} else {
return Ok((None, None, formatted));
}
}
// Only ones authored by the user, on the date requested, that aren't a reply to any other status // Only ones authored by the user, on the date requested, that aren't a reply to any other status
fn filter_statuses<'a>(account: &Account, day: &Range, json: &'a Vec<Status>) -> Vec<&'a Status> { fn filter_statuses<'a>(account: &Account, day: &Range, json: &'a Vec<Status>) -> Vec<&'a Status> {
json.iter() json.iter()
@ -143,8 +202,9 @@ async fn fetch_page(
client: &Box<dyn Megalodon + Send + Sync>, client: &Box<dyn Megalodon + Send + Sync>,
last_id_on_page: &Option<String>, last_id_on_page: &Option<String>,
) -> Result<Vec<Status>> { ) -> Result<Vec<Status>> {
trace!("Fetching page of local timeline");
let Response { json, .. } = if let Some(max_id) = last_id_on_page.as_ref() { let Response { json, .. } = if let Some(max_id) = last_id_on_page.as_ref() {
debug!("Fetching next page"); trace!("Fetching next page");
client client
.get_local_timeline(Some(&GetLocalTimelineInputOptions { .get_local_timeline(Some(&GetLocalTimelineInputOptions {
max_id: Some(max_id.clone()), max_id: Some(max_id.clone()),
@ -152,12 +212,53 @@ async fn fetch_page(
})) }))
.await? .await?
} else { } else {
debug!("Fetching first page"); trace!("Fetching first page");
client.get_local_timeline(None).await? client.get_local_timeline(None).await?
}; };
Ok(json) Ok(json)
} }
async fn fetch_dm_page(
client: &Box<dyn Megalodon + Send + Sync>,
account: &Account,
last_id_on_page: &Option<String>,
) -> Result<Vec<Status>> {
trace!("Fetching page of DMs");
let Response { json, .. } = if let Some(max_id) = last_id_on_page.as_ref() {
trace!("Fetching next page");
client
.get_account_statuses(
account.id.clone(),
Some(&GetAccountStatusesInputOptions {
max_id: Some(max_id.clone()),
..GetAccountStatusesInputOptions::default()
}),
)
.await?
} else {
trace!("Fetching first page");
client
.get_account_statuses(account.id.clone(), None)
.await?
};
let json: Vec<Status> = json
.into_iter()
.filter(|s| {
if let StatusVisibility::Direct = s.visibility {
(s.in_reply_to_account_id.is_none()
|| s.in_reply_to_account_id
.as_ref()
.map(|r| r == &account.id)
.unwrap_or_default())
&& s.mentions.is_empty()
} else {
false
}
})
.collect();
Ok(json)
}
fn page_newer_than(page: &Page, range: &Range) -> Option<String> { fn page_newer_than(page: &Page, range: &Range) -> Option<String> {
page.oldest page.oldest
.filter(|oldest| *oldest > &range.end) .filter(|oldest| *oldest > &range.end)