Server tools to backfill, tail, mirror, and verify PLC logs
0
fork

Configure Feed

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

fjall: use ServiceEndpoint for service and Handle for handle in legacy create op

dawn 3624c03b 9d82e094

+54 -12
+54 -12
src/plc_fjall.rs
··· 357 357 } 358 358 } 359 359 360 + // STABILITY: never reorder variants, only append. 361 + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, bitcode::Encode, bitcode::Decode)] 362 + enum Handle { 363 + Other(String), // 0 364 + BskySocial(String), // 1 365 + } 366 + 367 + impl Handle { 368 + fn from_str(s: &str) -> Self { 369 + if let Some(handle) = s.strip_suffix(".bsky.social") { 370 + Self::BskySocial(handle.to_string()) 371 + } else { 372 + Self::Other(s.to_string()) 373 + } 374 + } 375 + 376 + fn as_string(&self) -> String { 377 + match self { 378 + Self::BskySocial(h) => format!("{h}.bsky.social"), 379 + Self::Other(s) => s.clone(), 380 + } 381 + } 382 + } 383 + 360 384 #[derive(Debug, Clone, Serialize, Deserialize, bitcode::Encode, bitcode::Decode)] 361 385 struct StoredService { 362 386 r#type: ServiceType, ··· 377 401 // legacy create fields 378 402 signing_key: Option<DidKey>, 379 403 recovery_key: Option<DidKey>, 380 - handle: Option<String>, 381 - service: Option<String>, 404 + handle: Option<Handle>, 405 + service: Option<ServiceEndpoint>, 382 406 383 407 // msgpack-encoded BTreeMap<String, serde_json::Value>. 384 408 // Vec<u8> is used because bitcode cannot handle serde_json::Value directly. ··· 705 729 }; 706 730 707 731 let handle = match obj.remove(&*StoredOpField::Handle) { 708 - Some(serde_json::Value::String(s)) => Some(s), 732 + Some(serde_json::Value::String(s)) => Some(Handle::from_str(&s)), 709 733 Some(v) => { 710 734 errors.push(StoredOpError::TypeMismatch(StoredOpField::Handle, "string")); 711 735 unknown.insert(StoredOpField::Handle.to_string(), v); ··· 715 739 }; 716 740 717 741 let service = match obj.remove(&*StoredOpField::Service) { 718 - Some(serde_json::Value::String(s)) => Some(s), 742 + Some(serde_json::Value::String(s)) => Some(ServiceEndpoint::from_str(&s)), 719 743 Some(v) => { 720 744 errors.push(StoredOpError::TypeMismatch( 721 745 StoredOpField::Service, ··· 820 844 map.insert((*StoredOpField::RecoveryKey).into(), key.to_string().into()); 821 845 } 822 846 if let Some(handle) = &self.handle { 823 - map.insert((*StoredOpField::Handle).into(), handle.clone().into()); 847 + map.insert((*StoredOpField::Handle).into(), handle.as_string().into()); 824 848 } 825 849 if let Some(service) = &self.service { 826 - map.insert((*StoredOpField::Service).into(), service.clone().into()); 850 + map.insert((*StoredOpField::Service).into(), service.as_string().into()); 827 851 } 828 852 829 853 for (k, v) in self.unknown() { ··· 1640 1664 } 1641 1665 1642 1666 #[test] 1643 - fn bsky_handle_roundtrip() { 1667 + fn bsky_aka_roundtrip() { 1644 1668 let h = Aka::from_str("at://alice.bsky.social"); 1645 1669 assert_eq!(h, Aka::Bluesky("alice".to_string())); 1646 1670 assert_eq!(h.to_string(), "at://alice.bsky.social"); 1647 1671 } 1648 1672 1649 1673 #[test] 1650 - fn atproto_handle_roundtrip() { 1674 + fn atproto_aka_roundtrip() { 1651 1675 let h = Aka::from_str("at://alice.example.com"); 1652 1676 assert_eq!(h, Aka::Atproto("alice.example.com".to_string())); 1653 1677 assert_eq!(h.to_string(), "at://alice.example.com"); 1654 1678 } 1655 1679 1656 1680 #[test] 1657 - fn other_handle_roundtrip() { 1681 + fn other_aka_roundtrip() { 1658 1682 let h = Aka::from_str("https://something.else"); 1659 1683 assert_eq!(h, Aka::Other("https://something.else".to_string())); 1660 1684 assert_eq!(h.to_string(), "https://something.else"); 1661 1685 } 1662 1686 1663 1687 #[test] 1688 + fn handle_bsky_social_roundtrip() { 1689 + let h = Handle::from_str("alice.bsky.social"); 1690 + assert_eq!(h, Handle::BskySocial("alice".to_string())); 1691 + assert_eq!(h.as_string(), "alice.bsky.social"); 1692 + } 1693 + 1694 + #[test] 1695 + fn handle_other_roundtrip() { 1696 + let h = Handle::from_str("user.example.com"); 1697 + assert_eq!(h, Handle::Other("user.example.com".to_string())); 1698 + assert_eq!(h.as_string(), "user.example.com"); 1699 + } 1700 + 1701 + #[test] 1664 1702 fn verification_method_key_roundtrip() { 1665 1703 let k1 = VerificationMethodKey::from_str("atproto"); 1666 1704 assert_eq!(k1, VerificationMethodKey::Atproto); ··· 1699 1737 assert_eq!(e1, ServiceEndpoint::BlueskyPds("example".to_string())); 1700 1738 assert_eq!(e1.as_string(), "https://example.host.bsky.network"); 1701 1739 1702 - let e2 = ServiceEndpoint::from_str("https://other.endpoint.com"); 1740 + let e2 = ServiceEndpoint::from_str("https://bsky.social"); 1741 + assert_eq!(e2, ServiceEndpoint::BlueskySocial); 1742 + assert_eq!(e2.as_string(), "https://bsky.social"); 1743 + 1744 + let e3 = ServiceEndpoint::from_str("https://other.endpoint.com"); 1703 1745 assert_eq!( 1704 - e2, 1746 + e3, 1705 1747 ServiceEndpoint::Other("https://other.endpoint.com".to_string()) 1706 1748 ); 1707 - assert_eq!(e2.as_string(), "https://other.endpoint.com"); 1749 + assert_eq!(e3.as_string(), "https://other.endpoint.com"); 1708 1750 } 1709 1751 1710 1752 #[test]