A personal app view to see Bsky posts of your followers (for when their app view goes down)
1use axum::{
2 Json, Router,
3 extract::State,
4 response::{IntoResponse, Response},
5 routing::get,
6};
7use serde_json::json;
8use std::net::SocketAddr;
9
10#[derive(Clone)]
11pub struct ServerConfig {
12 pub appview_did: String,
13 pub appview_endpoint: String,
14}
15
16pub async fn run_server() {
17 let host = std::env::var("APPVIEW_HOST").unwrap_or("0.0.0.0".to_string());
18 let port: u16 = std::env::var("APPVIEW_PORT")
19 .ok()
20 .and_then(|s| s.parse().ok())
21 .unwrap_or(3000);
22
23 let appview_did = std::env::var("APPVIEW_DID").unwrap();
24 let appview_endpoint = std::env::var("APPVIEW_HOSTNAME").unwrap();
25
26 let server_config = ServerConfig {
27 appview_did: appview_did,
28 appview_endpoint: appview_endpoint,
29 };
30
31 let app = Router::new()
32 .route("/", get(say_hello_text))
33 .route("/.well-known/did.json", get(well_known_did_json))
34 .with_state(server_config);
35
36 let addr: SocketAddr = format!("{host}:{port}")
37 .parse()
38 .expect("valid socket address");
39
40 println!("listening on {addr}");
41
42 let listener = tokio::net::TcpListener::bind(addr.to_string())
43 .await
44 .unwrap();
45
46 axum::serve(listener, app).await.unwrap();
47}
48
49async fn say_hello_text() -> &'static str {
50 return "This is an appview. Work in progress. This is my appview. There are many like it, but this one is mine";
51}
52
53async fn well_known_did_json(State(server_config): State<ServerConfig>) -> Response {
54 Json(json!({
55 "@context": [
56 "https://www.w3.org/ns/did/v1",
57 "https://w3id.org/security/multikey/v1"],
58 "id": server_config.appview_did,
59 "verificationMethod": [
60 {
61 "id": "did:web:api.bsky.app#atproto",
62 "type": "Multikey",
63 "controller": "did:web:api.bsky.app",
64 "publicKeyMultibase": "zQ3shpRzb2NDriwCSSsce6EqGxG23kVktHZc57C3NEcuNy1jg"
65 }
66 ],
67 "service": [
68 {
69 "id": "#bsky_notif",
70 "type": "BskyNotificationService",
71 "serviceEndpoint": server_config.appview_endpoint
72 },
73 {
74 "id": "#bsky_appview",
75 "type": "BskyAppView",
76 "serviceEndpoint": server_config.appview_endpoint
77 }
78 ]
79 }))
80 .into_response()
81}