From b2e771c20827a41192f481ff41ad659cc02c9b26 Mon Sep 17 00:00:00 2001 From: Balazs Horvath Date: Mon, 25 Nov 2024 12:22:36 +0100 Subject: [PATCH] fix links on bluesky --- Cargo.lock | 39 +++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/social/bluesky.rs | 43 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 82 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 0c0d956..9d5f12c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,15 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -864,6 +873,7 @@ dependencies = [ "clap", "dirs", "oauth1", + "regex", "reqwest", "serde", "serde_json", @@ -965,6 +975,35 @@ dependencies = [ "thiserror", ] +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + [[package]] name = "reqwest" version = "0.12.9" diff --git a/Cargo.toml b/Cargo.toml index be40628..ce5d07a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,3 +14,4 @@ async-trait = "0.1.83" toml = "0.8.19" dirs = "5.0.1" chrono = { version = "0.4.38", features = ["serde"] } +regex = "1.11.1" diff --git a/src/social/bluesky.rs b/src/social/bluesky.rs index feb3599..3e32c3e 100644 --- a/src/social/bluesky.rs +++ b/src/social/bluesky.rs @@ -2,6 +2,7 @@ use reqwest::Client; use serde_json::json; use crate::config::Config; use super::SocialClient; +use regex::Regex; pub struct BlueskyClient { identifier: String, @@ -10,6 +11,30 @@ pub struct BlueskyClient { client: Client, } +#[derive(Debug)] +struct UrlFacet { + start: usize, + end: usize, + url: String, +} + +impl BlueskyClient { + fn detect_urls(text: &str) -> Vec { + let url_regex = Regex::new(r"https?://[^\s]+").unwrap(); + let mut facets = Vec::new(); + + for mat in url_regex.find_iter(text) { + facets.push(UrlFacet { + start: mat.start(), + end: mat.end(), + url: mat.as_str().to_string(), + }); + } + + facets + } +} + #[async_trait::async_trait] impl SocialClient for BlueskyClient { fn new() -> Result> { @@ -39,6 +64,21 @@ impl SocialClient for BlueskyClient { let access_jwt = auth_response["accessJwt"].as_str() .ok_or("Failed to get access token")?; + // Detect URLs and create facets + let url_facets = Self::detect_urls(message); + let facets = url_facets.iter().map(|f| { + json!({ + "index": { + "byteStart": f.start, + "byteEnd": f.end + }, + "features": [{ + "$type": "app.bsky.richtext.facet#link", + "uri": f.url + }] + }) + }).collect::>(); + // Create the post let response = self.client .post(format!("{}/xrpc/com.atproto.repo.createRecord", self.instance_url)) @@ -49,7 +89,8 @@ impl SocialClient for BlueskyClient { "record": { "$type": "app.bsky.feed.post", "text": message, - "createdAt": chrono::Utc::now().to_rfc3339() + "createdAt": chrono::Utc::now().to_rfc3339(), + "facets": facets } })) .send()