Parakeet is a Rust-based Bluesky AppServer aiming to implement most of the functionality required to support the Bluesky client
appview atproto bluesky rust appserver
66
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: allow non bsky embed types

Mia 332d30d8 cb648ee2

+57 -15
+1 -1
consumer/src/indexer/db.rs
··· 400 400 .execute(conn) 401 401 .await?; 402 402 403 - match rec.embed { 403 + match rec.embed.and_then(|v| v.into_bsky()) { 404 404 Some(AppBskyEmbed::Images(embed)) => insert_post_embed_images(conn, at_uri, embed).await, 405 405 Some(AppBskyEmbed::Video(embed)) => insert_post_embed_video(conn, at_uri, embed).await, 406 406 Some(AppBskyEmbed::External(embed)) => insert_post_embed_ext(conn, at_uri, embed).await,
+15 -6
consumer/src/indexer/mod.rs
··· 519 519 .await; 520 520 } 521 521 RecordTypes::AppBskyFeedPost(record) => { 522 - if let Some(records::AppBskyEmbed::RecordWithMedia(embed)) = &record.embed { 522 + if let Some(records::AppBskyEmbed::RecordWithMedia(embed)) = 523 + &record.embed.as_ref().and_then(|v| v.as_bsky()) 524 + { 523 525 if !embed.media.record_with_media_allowed() { 524 526 return Ok(()); 525 527 } 526 528 } 527 529 528 530 let maybe_reply = record.reply.as_ref().map(|v| v.parent.uri.clone()); 529 - let maybe_embed = record.embed.as_ref().and_then(|v| match v { 530 - records::AppBskyEmbed::Record(r) => Some(r.record.uri.clone()), 531 - records::AppBskyEmbed::RecordWithMedia(r) => Some(r.record.record.uri.clone()), 532 - _ => None, 533 - }); 531 + let maybe_embed = 532 + record 533 + .embed 534 + .as_ref() 535 + .and_then(|v| v.as_bsky()) 536 + .and_then(|v| match v { 537 + records::AppBskyEmbed::Record(r) => Some(r.record.uri.clone()), 538 + records::AppBskyEmbed::RecordWithMedia(r) => { 539 + Some(r.record.record.uri.clone()) 540 + } 541 + _ => None, 542 + }); 534 543 535 544 let labels = record.labels.clone(); 536 545 db::insert_post(conn, repo, cid, at_uri, record).await?;
+41 -8
consumer/src/indexer/records.rs
··· 44 44 } 45 45 46 46 #[derive(Debug, Deserialize, Serialize)] 47 + #[serde(untagged)] 48 + pub enum EmbedOuter { 49 + Bsky(AppBskyEmbed), 50 + Other(serde_json::Value), 51 + } 52 + 53 + impl EmbedOuter { 54 + pub fn into_bsky(self) -> Option<AppBskyEmbed> { 55 + match self { 56 + EmbedOuter::Bsky(inner) => Some(inner), 57 + _ => None, 58 + } 59 + } 60 + 61 + pub fn as_bsky(&self) -> Option<&AppBskyEmbed> { 62 + match self { 63 + EmbedOuter::Bsky(inner) => Some(inner), 64 + _ => None, 65 + } 66 + } 67 + 68 + pub fn as_str(&self) -> &str { 69 + match self { 70 + EmbedOuter::Bsky(inner) => inner.as_str(), 71 + EmbedOuter::Other(inner) => inner 72 + .get("$type") 73 + .and_then(|v| v.as_str()) 74 + .unwrap_or("parakeet-unknown"), 75 + } 76 + } 77 + 78 + pub fn subtype(&self) -> Option<&'static str> { 79 + match self { 80 + EmbedOuter::Bsky(AppBskyEmbed::RecordWithMedia(rwm)) => Some(rwm.media.as_str()), 81 + _ => None, 82 + } 83 + } 84 + } 85 + 86 + #[derive(Debug, Deserialize, Serialize)] 47 87 #[serde(tag = "$type")] 48 88 pub enum AppBskyEmbed { 49 89 #[serde(rename = "app.bsky.embed.images")] ··· 73 113 AppBskyEmbed::External(_) => "app.bsky.embed.external", 74 114 AppBskyEmbed::Record(_) => "app.bsky.embed.record", 75 115 AppBskyEmbed::RecordWithMedia(_) => "app.bsky.embed.recordWithMedia", 76 - } 77 - } 78 - 79 - pub fn subtype(&self) -> Option<&'static str> { 80 - match self { 81 - AppBskyEmbed::RecordWithMedia(rwm) => Some(rwm.media.as_str()), 82 - _ => None, 83 116 } 84 117 } 85 118 } ··· 174 207 #[serde(skip_serializing_if = "Option::is_none")] 175 208 pub reply: Option<ReplyRef>, 176 209 #[serde(skip_serializing_if = "Option::is_none")] 177 - pub embed: Option<AppBskyEmbed>, 210 + pub embed: Option<EmbedOuter>, 178 211 #[serde(skip_serializing_if = "Option::is_none")] 179 212 pub langs: Option<Vec<String>>, 180 213 #[serde(skip_serializing_if = "Option::is_none")]