a digital entity named phi that roams bsky
at 339289ba3e7a7da64b6798f8a185b4e21e86d04f 101 lines 2.8 kB view raw
1#!/usr/bin/env python3 2"""View phi's recent posts without authentication.""" 3 4import httpx 5from datetime import datetime 6from rich.console import Console 7from rich.panel import Panel 8from rich.text import Text 9 10console = Console() 11 12PHI_HANDLE = "phi.zzstoatzz.io" 13 14 15def fetch_phi_posts(limit: int = 10): 16 """Fetch phi's recent posts using public API.""" 17 # Resolve handle to DID 18 response = httpx.get( 19 "https://public.api.bsky.app/xrpc/com.atproto.identity.resolveHandle", 20 params={"handle": PHI_HANDLE} 21 ) 22 did = response.json()["did"] 23 24 # Get author feed (public posts) 25 response = httpx.get( 26 "https://public.api.bsky.app/xrpc/app.bsky.feed.getAuthorFeed", 27 params={"actor": did, "limit": limit} 28 ) 29 30 return response.json()["feed"] 31 32 33def format_timestamp(iso_time: str) -> str: 34 """Format ISO timestamp to readable format.""" 35 dt = datetime.fromisoformat(iso_time.replace("Z", "+00:00")) 36 now = datetime.now(dt.tzinfo) 37 delta = now - dt 38 39 if delta.seconds < 60: 40 return f"{delta.seconds}s ago" 41 elif delta.seconds < 3600: 42 return f"{delta.seconds // 60}m ago" 43 elif delta.seconds < 86400: 44 return f"{delta.seconds // 3600}h ago" 45 else: 46 return f"{delta.days}d ago" 47 48 49def display_posts(feed_items): 50 """Display posts in a readable format.""" 51 for item in feed_items: 52 post = item["post"] 53 record = post["record"] 54 55 # Check if this is a reply 56 is_reply = "reply" in record 57 reply_indicator = "↳ REPLY" if is_reply else "✓ POST" 58 59 # Format header 60 timestamp = format_timestamp(post["indexedAt"]) 61 header = f"[cyan]{reply_indicator}[/cyan] [dim]{timestamp}[/dim]" 62 63 # Get post text 64 text = record.get("text", "[no text]") 65 66 # Show parent if it's a reply 67 parent_text = "" 68 if is_reply: 69 parent_uri = record["reply"]["parent"]["uri"] 70 parent_text = f"[dim]replying to: {parent_uri}[/dim]\n\n" 71 72 # Format post 73 content = Text() 74 if parent_text: 75 content.append(parent_text, style="dim") 76 content.append(text) 77 78 # Display 79 panel = Panel( 80 content, 81 title=header, 82 border_style="blue" if is_reply else "green", 83 width=80 84 ) 85 console.print(panel) 86 console.print() 87 88 89def main(): 90 console.print("[bold]Fetching phi's recent posts...[/bold]\n") 91 92 try: 93 feed = fetch_phi_posts(limit=10) 94 display_posts(feed) 95 console.print(f"[dim]Showing {len(feed)} most recent posts[/dim]") 96 except Exception as e: 97 console.print(f"[red]Error: {e}[/red]") 98 99 100if __name__ == "__main__": 101 main()