diff options
| author | Xe Iaso <me@christine.website> | 2022-10-30 14:22:56 -0400 |
|---|---|---|
| committer | Xe Iaso <me@christine.website> | 2022-10-30 14:22:56 -0400 |
| commit | c654d84537a50e164c57852fc89216eec8e55d69 (patch) | |
| tree | 7844201ca37fe998309f81b000dc86477d05e4ca | |
| parent | 79a0a167ee87e925091a55f7de88d02bcea42c92 (diff) | |
| download | xesite-c654d84537a50e164c57852fc89216eec8e55d69.tar.xz xesite-c654d84537a50e164c57852fc89216eec8e55d69.zip | |
start working on a mastodon post embed tag
Signed-off-by: Xe Iaso <me@christine.website>
| -rw-r--r-- | Cargo.lock | 177 | ||||
| -rw-r--r-- | Cargo.toml | 5 | ||||
| -rw-r--r-- | data/toots/8e4f43b38bb5572d8002f73dac7a4fcd9b3573d205ea8d2b8b1b28aab7d03447.json | 44 | ||||
| -rw-r--r-- | data/toots/a83e23736eb81745c08464f913685f6e8479db6096355aa8c217c66c3e120be3.json | 28 | ||||
| -rw-r--r-- | default.nix | 1 | ||||
| -rw-r--r-- | flake.nix | 1 | ||||
| -rw-r--r-- | lib/xesite_templates/Cargo.toml | 4 | ||||
| -rw-r--r-- | lib/xesite_templates/src/lib.rs | 35 | ||||
| -rw-r--r-- | lib/xesite_types/Cargo.toml | 1 | ||||
| -rw-r--r-- | lib/xesite_types/src/mastodon.rs | 118 | ||||
| -rw-r--r-- | src/bin/fetch_mastodon_post.rs | 56 | ||||
| -rw-r--r-- | src/lib.rs | 7 |
12 files changed, 410 insertions, 67 deletions
@@ -554,7 +554,7 @@ dependencies = [ "dtoa-short", "itoa 0.4.8", "matches", - "phf", + "phf 0.8.0", "proc-macro2", "quote", "smallvec", @@ -835,6 +835,16 @@ dependencies = [ ] [[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + +[[package]] name = "futures" version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1085,6 +1095,33 @@ dependencies = [ ] [[package]] +name = "html2text" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2a75f4fdb748c0980b4d04f8edafc749bf4b5bfa738bf6c1565c7e6118d6ca" +dependencies = [ + "html5ever", + "markup5ever", + "tendril", + "unicode-width", + "xml5ever", +] + +[[package]] +name = "html5ever" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7" +dependencies = [ + "log", + "mac", + "markup5ever", + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "http" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1365,12 +1402,32 @@ dependencies = [ ] [[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] name = "maplit" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" [[package]] +name = "markup5ever" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" +dependencies = [ + "log", + "phf 0.10.1", + "phf_codegen 0.10.0", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] name = "matches" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1495,6 +1552,12 @@ dependencies = [ ] [[package]] +name = "new_debug_unreachable" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" + +[[package]] name = "nodrop" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1790,18 +1853,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ "phf_macros", - "phf_shared", + "phf_shared 0.8.0", "proc-macro-hack", ] [[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_shared 0.10.0", +] + +[[package]] name = "phf_codegen" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" dependencies = [ - "phf_generator", - "phf_shared", + "phf_generator 0.8.0", + "phf_shared 0.8.0", +] + +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", ] [[package]] @@ -1810,18 +1892,28 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" dependencies = [ - "phf_shared", + "phf_shared 0.8.0", "rand 0.7.3", ] [[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand 0.8.5", +] + +[[package]] name = "phf_macros" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c" dependencies = [ - "phf_generator", - "phf_shared", + "phf_generator 0.8.0", + "phf_shared 0.8.0", "proc-macro-hack", "proc-macro2", "quote", @@ -1838,6 +1930,15 @@ dependencies = [ ] [[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] name = "pin-project" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2274,8 +2375,8 @@ dependencies = [ "fxhash", "log", "matches", - "phf", - "phf_codegen", + "phf 0.8.0", + "phf_codegen 0.8.0", "precomputed-hash", "servo_arc", "smallvec", @@ -2490,6 +2591,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] +name = "string_cache" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro2", + "quote", +] + +[[package]] name = "strsim" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2550,6 +2677,17 @@ dependencies = [ ] [[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + +[[package]] name = "termcolor" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2961,6 +3099,12 @@ dependencies = [ ] [[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] name = "uuid" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3237,6 +3381,7 @@ dependencies = [ "eyre", "futures", "glob", + "hex", "http", "http-body", "hyper", @@ -3259,6 +3404,7 @@ dependencies = [ "serde_dhall", "serde_json", "serde_yaml", + "sha2", "sitemap", "thiserror", "tokio", @@ -3297,6 +3443,7 @@ name = "xesite_templates" version = "0.1.0" dependencies = [ "maud", + "xesite_types", ] [[package]] @@ -3304,6 +3451,7 @@ name = "xesite_types" version = "0.1.0" dependencies = [ "chrono", + "html2text", "serde", "serde_json", ] @@ -3315,6 +3463,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" [[package]] +name = "xml5ever" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4034e1d05af98b51ad7214527730626f019682d797ba38b51689212118d8e650" +dependencies = [ + "log", + "mac", + "markup5ever", +] + +[[package]] name = "yaml-rust" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -21,6 +21,7 @@ envy = "0.4" estimated_read_time = "1" futures = "0.3" glob = "0.3" +hex = "0.4" http = "0.2" http-body = "0.4" hyper = "0.14" @@ -33,9 +34,11 @@ prometheus = { version = "0.13", default-features = false, features = ["process" rand = "0" regex = "1" reqwest = { version = "0.11", features = ["json"] } -serde_dhall = "0.11.2" serde = { version = "1", features = ["derive"] } +serde_json = "1" +serde_dhall = "0.11.2" serde_yaml = "0.9" +sha2 = "0.9" sitemap = "0.4" thiserror = "1" tokio = { version = "1", features = ["full"] } diff --git a/data/toots/8e4f43b38bb5572d8002f73dac7a4fcd9b3573d205ea8d2b8b1b28aab7d03447.json b/data/toots/8e4f43b38bb5572d8002f73dac7a4fcd9b3573d205ea8d2b8b1b28aab7d03447.json new file mode 100644 index 0000000..fc6b68b --- /dev/null +++ b/data/toots/8e4f43b38bb5572d8002f73dac7a4fcd9b3573d205ea8d2b8b1b28aab7d03447.json @@ -0,0 +1,44 @@ +{ + "id": "https://pony.social/users/cadey/statuses/109258440953407431", + "type": "Note", + "inReplyTo": null, + "published": "2022-10-30T17:38:23Z", + "url": "https://pony.social/@cadey/109258440953407431", + "attributedTo": "https://pony.social/users/cadey", + "to": [ + "https://www.w3.org/ns/activitystreams#Public" + ], + "cc": [ + "https://pony.social/users/cadey/followers" + ], + "sensitive": false, + "atomUri": "https://pony.social/users/cadey/statuses/109258440953407431", + "inReplyToAtomUri": null, + "conversation": "tag:pony.social,2022-10-30:objectId=5763802:objectType=Conversation", + "content": "<p>Testing a video upload for writing something to do with Mastodon</p>", + "contentMap": { + "en": "<p>Testing a video upload for writing something to do with Mastodon</p>" + }, + "attachment": [ + { + "type": "Document", + "mediaType": "video/mp4", + "url": "https://cdn.pony.social/file/tscs37-pony-social/media_attachments/files/109/258/439/779/239/363/original/66210576226643d7.mp4", + "name": null, + "blurhash": "UMAKXFoe4TWWtQkCRQV@jEj[WDjbWVjYoLf+", + "width": 1280, + "height": 720 + } + ], + "tag": [], + "replies": { + "id": "https://pony.social/users/cadey/statuses/109258440953407431/replies", + "type": "Collection", + "first": { + "type": "CollectionPage", + "next": "https://pony.social/users/cadey/statuses/109258440953407431/replies?only_other_accounts=true&page=true", + "partOf": "https://pony.social/users/cadey/statuses/109258440953407431/replies", + "items": [] + } + } +}
\ No newline at end of file diff --git a/data/toots/a83e23736eb81745c08464f913685f6e8479db6096355aa8c217c66c3e120be3.json b/data/toots/a83e23736eb81745c08464f913685f6e8479db6096355aa8c217c66c3e120be3.json new file mode 100644 index 0000000..15e8f2a --- /dev/null +++ b/data/toots/a83e23736eb81745c08464f913685f6e8479db6096355aa8c217c66c3e120be3.json @@ -0,0 +1,28 @@ +{ + "id": "https://pony.social/users/cadey", + "type": "Person", + "following": "https://pony.social/users/cadey/following", + "followers": "https://pony.social/users/cadey/followers", + "inbox": "https://pony.social/users/cadey/inbox", + "outbox": "https://pony.social/users/cadey/outbox", + "featured": "https://pony.social/users/cadey/collections/featured", + "featuredTags": "https://pony.social/users/cadey/collections/tags", + "preferredUsername": "cadey", + "name": "Xe", + "summary": "<p>🔞 Minors, please DNI</p><p>Any statements are my own, not my employer's</p><p>Archmage of Infrastructure at that VPN company that isn't actually a VPN company I guess it's complicated</p><p>ΘΔ</p><p>zi ai-uh-so /zi ai.ə.soʊ/</p>", + "url": "https://pony.social/@cadey", + "manuallyApprovesFollowers": false, + "discoverable": true, + "published": "2021-06-30T00:00:00Z", + "devices": "https://pony.social/users/cadey/collections/devices", + "icon": { + "type": "Image", + "mediaType": "image/png", + "url": "https://cdn.pony.social/file/tscs37-pony-social/accounts/avatars/106/500/315/995/032/015/original/056011b7379c0ecc.png" + }, + "image": { + "type": "Image", + "mediaType": "image/jpeg", + "url": "https://cdn.pony.social/file/tscs37-pony-social/accounts/headers/106/500/315/995/032/015/original/d32327b86f0038ee.jpeg" + } +}
\ No newline at end of file diff --git a/default.nix b/default.nix index 9cdec71..5ce17c1 100644 --- a/default.nix +++ b/default.nix @@ -47,6 +47,7 @@ in pkgs.stdenv.mkDerivation { cp -rf ${config} $out/config.dhall cp -rf $src/blog $out/blog cp -rf $src/css $out/css + cp -rf $src/data $out/data cp -rf $src/gallery $out/gallery cp -rf $src/static $out/static cp -rf $src/talks $out/talks @@ -45,6 +45,7 @@ installPhase = '' mkdir -p $out + cp -vrf $src/data $out cp -vrf $src/static $out cp -vrf $src/css $out ''; diff --git a/lib/xesite_templates/Cargo.toml b/lib/xesite_templates/Cargo.toml index 06ab92d..3d66e59 100644 --- a/lib/xesite_templates/Cargo.toml +++ b/lib/xesite_templates/Cargo.toml @@ -6,4 +6,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -maud = "0.23.0"
\ No newline at end of file +maud = "0.23.0" + +xesite_types = { path = "../xesite_types" }
\ No newline at end of file diff --git a/lib/xesite_templates/src/lib.rs b/lib/xesite_templates/src/lib.rs index a24e239..b3298d9 100644 --- a/lib/xesite_templates/src/lib.rs +++ b/lib/xesite_templates/src/lib.rs @@ -1,4 +1,5 @@ use maud::{html, Markup, PreEscaped}; +use xesite_types::mastodon::{Toot, User}; pub fn talk_warning() -> Markup { html! { @@ -165,3 +166,37 @@ pub fn advertiser_nag() -> Markup { } } } + +pub fn toot_embed(u: User, t: Toot) -> Markup { + html! { + .media { + .media-left { + .avatarholder { + img src=(u.icon.url); + } + } + .media-body { + .media-heading { (u.name) " @" (u.preferred_username) } + .media-content { + (PreEscaped::<String>(t.content)) + + @for att in &t.attachment { + @if att.media_type.starts_with("image/") { + img src=(att.url) alt=(att.name.clone().unwrap_or("no description provided".into())); + } + + @if att.media_type.starts_with("video/") { + video width=(att.width) height=(att.height) controls { + source src=(att.url) type=(att.media_type); + "Your browser does not support the video tag, see this URL: " + a href=(att.url) {(att.url)} + } + } + } + + a href=(t.url) { "Link" } + } + } + } + } +} diff --git a/lib/xesite_types/Cargo.toml b/lib/xesite_types/Cargo.toml index 6d1854d..60f6bbf 100644 --- a/lib/xesite_types/Cargo.toml +++ b/lib/xesite_types/Cargo.toml @@ -9,5 +9,6 @@ license = "zlib" [dependencies] chrono = { version = "0.4", features = [ "serde" ] } +html2text = "0.4" serde = { version = "1.0", features = [ "derive" ] } serde_json = "1"
\ No newline at end of file diff --git a/lib/xesite_types/src/mastodon.rs b/lib/xesite_types/src/mastodon.rs index 3b4eb2a..4cf1e96 100644 --- a/lib/xesite_types/src/mastodon.rs +++ b/lib/xesite_types/src/mastodon.rs @@ -4,193 +4,199 @@ use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] pub struct User { #[serde(rename = "id")] - id: String, + pub id: String, #[serde(rename = "type")] - user_type: String, + pub user_type: String, #[serde(rename = "following")] - following: String, + pub following: String, #[serde(rename = "followers")] - followers: String, + pub followers: String, #[serde(rename = "inbox")] - inbox: String, + pub inbox: String, #[serde(rename = "outbox")] - outbox: String, + pub outbox: String, #[serde(rename = "featured")] - featured: String, + pub featured: String, #[serde(rename = "featuredTags")] - featured_tags: String, + pub featured_tags: String, #[serde(rename = "preferredUsername")] - preferred_username: String, + pub preferred_username: String, #[serde(rename = "name")] - name: String, + pub name: String, #[serde(rename = "summary")] - summary: String, + pub summary: String, #[serde(rename = "url")] - url: String, + pub url: String, #[serde(rename = "manuallyApprovesFollowers")] - manually_approves_followers: bool, + pub manually_approves_followers: bool, #[serde(rename = "discoverable")] - discoverable: bool, + pub discoverable: bool, #[serde(rename = "published")] - published: String, + pub published: String, #[serde(rename = "devices")] - devices: String, + pub devices: String, #[serde(rename = "icon")] - icon: Icon, + pub icon: Icon, #[serde(rename = "image")] - image: Icon, + pub image: Icon, } #[derive(Serialize, Deserialize)] pub struct Icon { #[serde(rename = "type")] - icon_type: String, + pub icon_type: String, #[serde(rename = "mediaType")] - media_type: String, + pub media_type: String, #[serde(rename = "url")] - url: String, + pub url: String, } #[derive(Serialize, Deserialize)] pub struct Toot { #[serde(rename = "id")] - id: String, + pub id: String, #[serde(rename = "type")] - toot_type: String, + pub toot_type: String, #[serde(rename = "inReplyTo")] - in_reply_to: Option<String>, + pub in_reply_to: Option<String>, #[serde(rename = "published")] - published: DateTime<Utc>, + pub published: DateTime<Utc>, #[serde(rename = "url")] - url: String, + pub url: String, #[serde(rename = "attributedTo")] - attributed_to: String, + pub attributed_to: String, #[serde(rename = "to")] - to: Vec<String>, + pub to: Vec<String>, #[serde(rename = "cc")] - cc: Vec<String>, + pub cc: Vec<String>, #[serde(rename = "sensitive")] - sensitive: bool, + pub sensitive: bool, #[serde(rename = "atomUri")] - atom_uri: String, + pub atom_uri: String, #[serde(rename = "inReplyToAtomUri")] - in_reply_to_atom_uri: Option<String>, + pub in_reply_to_atom_uri: Option<String>, #[serde(rename = "conversation")] - conversation: String, + pub conversation: String, #[serde(rename = "content")] - content: String, + pub content: String, #[serde(rename = "contentMap")] - content_map: ContentMap, + pub content_map: ContentMap, #[serde(rename = "attachment")] - attachment: Vec<Attachment>, + pub attachment: Vec<Attachment>, #[serde(rename = "tag")] - tag: Vec<Tag>, + pub tag: Vec<Tag>, #[serde(rename = "replies")] - replies: Replies, + pub replies: Replies, +} + +impl Toot { + pub fn content_text(&self) -> String { + html2text::from_read(std::io::Cursor::new(&self.content), 80) + } } #[derive(Serialize, Deserialize)] pub struct Tag { #[serde(rename = "type")] - tag_type: String, + pub tag_type: String, #[serde(rename = "href")] - href: String, + pub href: String, #[serde(rename = "name")] - name: String, + pub name: String, } #[derive(Serialize, Deserialize)] pub struct Attachment { #[serde(rename = "type")] - attachment_type: String, + pub attachment_type: String, #[serde(rename = "mediaType")] - media_type: String, + pub media_type: String, #[serde(rename = "url")] - url: String, + pub url: String, #[serde(rename = "name")] - name: Option<serde_json::Value>, + pub name: Option<String>, #[serde(rename = "blurhash")] - blurhash: String, + pub blurhash: String, #[serde(rename = "width")] - width: i64, + pub width: i64, #[serde(rename = "height")] - height: i64, + pub height: i64, } #[derive(Serialize, Deserialize)] pub struct ContentMap { #[serde(rename = "en")] - en: String, + pub en: String, } #[derive(Serialize, Deserialize)] pub struct Replies { #[serde(rename = "id")] - id: String, + pub id: String, #[serde(rename = "type")] - replies_type: String, + pub replies_type: String, #[serde(rename = "first")] - first: Page, + pub first: Page, } #[derive(Serialize, Deserialize)] pub struct Page { #[serde(rename = "type")] - first_type: String, + pub first_type: String, #[serde(rename = "next")] - next: String, + pub next: String, #[serde(rename = "partOf")] - part_of: String, + pub part_of: String, #[serde(rename = "items")] - items: Vec<String>, + pub items: Vec<String>, } #[cfg(test)] diff --git a/src/bin/fetch_mastodon_post.rs b/src/bin/fetch_mastodon_post.rs new file mode 100644 index 0000000..06faa57 --- /dev/null +++ b/src/bin/fetch_mastodon_post.rs @@ -0,0 +1,56 @@ +use color_eyre::Result; +use sha2::{Digest, Sha256}; +use std::{env, fs}; +use tracing::debug; +use xesite_types::mastodon::{Toot, User}; + +#[tokio::main] +async fn main() -> Result<()> { + color_eyre::install()?; + tracing_subscriber::fmt::init(); + + let args: Vec<String> = env::args().collect(); + debug!("{args:?}"); + if args.len() != 2 { + eprintln!("Usage: {} <mastodon post URL>", args[0]); + } + + let mut post_url = args[1].clone(); + if !post_url.ends_with(".json") { + post_url = format!("{post_url}.json"); + } + + let toot: Toot = reqwest::get(&post_url) + .await? + .error_for_status()? + .json() + .await?; + + debug!("got post by {}", toot.attributed_to); + + fs::create_dir_all("./data/toots")?; + + let post_hash = xesite::hash_string(post_url); + + let mut fout = fs::File::create(&format!("./data/toots/{post_hash}.json"))?; + serde_json::to_writer_pretty(&mut fout, &toot)?; + + let user_url = format!("{}.json", toot.attributed_to); + + let user: User = reqwest::get(&user_url) + .await? + .error_for_status()? + .json() + .await?; + + fs::create_dir_all("./data/users")?; + + debug!("got user {} ({})", user.name, user.preferred_username); + + let user_hash = xesite::hash_string(user_url); + + let mut fout = fs::File::create(&format!("./data/toots/{user_hash}.json"))?; + serde_json::to_writer_pretty(&mut fout, &user)?; + + Ok(()) +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..1fc1661 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,7 @@ +use sha2::{Digest, Sha256}; + +pub fn hash_string(inp: String) -> String { + let mut h = Sha256::new(); + h.update(&inp.as_bytes()); + hex::encode(h.finalize()) +} |
