package main import ( "encoding/json" "fmt" "io/ioutil" "log" "net/http" "os" "strings" ) // CreateObject - Used by post web receiver type CreateObject struct { ID string `json:"id"` Actor string `json:"actor"` Cc []string `json:"cc"` Content string `json:"content"` To []string `json:"to"` Type string `json:"type"` } // CreateObject - Used by post web receiver type AnnounceObject struct { ID string `json:"id"` Actor string `json:"actor"` To []string `json:"to"` Type string `json:"type"` Object string `json:"object"` } // RelayBase - The base object used by web receiver type RelayBase struct { Actor string `json:"actor"` Cc []string `json:"cc"` Object json.RawMessage `json:"Object"` ID string `json:"id"` Published string `json:"published"` To []string `json:"to"` Type string `json:"type"` } func hostmeta(w http.ResponseWriter, r *http.Request) { fmt.Println("PATH --> ", r.URL.Path) host := r.Host xml := "" w.Header().Set("Content-Type", "application/xrd+xml") fmt.Fprintf(w, xml) } func webfinger(w http.ResponseWriter, r *http.Request) { fmt.Println("PATH --> ", r.URL.Path) host := r.Host webfingermap := make(map[string]interface{}) webfingermap["subject"] = "acct:fedilogue@" + host webfingermap["aliases"] = []string{"https://" + host + "/users/fedilogue"} link0 := make(map[string]string) link0["rel"] = "http://webfinger.net/rel/profile-page" link0["type"] = "text/html" link0["href"] = "https://" + host + "/users/fedilogue" link1 := make(map[string]string) link1["rel"] = "self" link1["type"] = "application/activity+json" link1["href"] = "https://" + host + "/users/fedilogue" link2 := make(map[string]string) link2["rel"] = "self" link2["type"] = "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"" link2["href"] = "https://" + host + "/users/fedilogue" link3 := make(map[string]string) link3["rel"] = "http://ostatus.org/schema/1.0/subscribe" link3["template"] = "https://" + host + "/ostatus_subscribe?acct={uri}" links := []map[string]string{link0, link1, link2, link3} webfingermap["links"] = links webfingerbin, err := json.Marshal(webfingermap) if err != nil { fmt.Println(err.Error()) return } webfingerstr := string(webfingerbin) query := r.URL.Query() resourceRaw, exists := query["resource"] if exists { resource := resourceRaw[0] if resource != "acct:fedilogue@"+host { fmt.Println("Writes properly but wrong acct") w.Header().Set("Content-Type", "application/json; charset=utf-8") fmt.Fprintf(w, webfingerstr) return } w.Header().Set("Content-Type", "application/json; charset=utf-8") fmt.Fprintf(w, webfingerstr) } else { fmt.Println(query) w.WriteHeader(http.StatusNotFound) return } } func inboxHandler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { body, err := ioutil.ReadAll(r.Body) if err != nil { fmt.Println(err) return } defer r.Body.Close() var findtype RelayBase err = json.Unmarshal(body, &findtype) if err != nil { logWarn("Unable to unmarshal here, exiting...") return } switch findtype.Type { case "Create": var createobject CreateObject err = json.Unmarshal(body, &createobject) if err != nil { return } go check_activity(createobject.ID) slashend := strings.Index(createobject.ID[8:], "/") newinstance := createobject.ID[8 : 8+slashend] go CheckInstance(newinstance, "") case "Update": case "Reject": case "Add": case "Remove": case "Follow": case "Accept": case "Like": case "Announce": var announceobject AnnounceObject err = json.Unmarshal(body, &announceobject) if err != nil { fmt.Println(err.Error()) return } check_activity(announceobject.Object) matchset := re.FindStringSubmatch(announceobject.Object) if matchset != nil { newinstance := matchset[1] go CheckInstance(newinstance, "") } case "Delete": case "Undo": default: logWarn("Unknown ActivityPub request:", findtype.Type) } w.Header().Set("Content-Type", "application/json") fmt.Fprintf(w, "{}") } } func internalFetch(w http.ResponseWriter, r *http.Request) { publicKeyBytes, err := ioutil.ReadFile("keys/public.pem") publicKeyString := string(publicKeyBytes) publicKeyString = strings.Replace(publicKeyString, "\n", "\\n", -11) if err != nil { log.Fatal(err) } staticjson := fmt.Sprintf(`{"@context":["https://www.w3.org/ns/activitystreams","https://%[1]s/schemas/litepub-0.1.jsonld",{"@language":"und"}],"endpoints":{"oauthAuthorizationEndpoint":"https://%[1]s/oauth/authorize","oauthRegistrationEndpoint":"https://%[1]s/api/v1/apps","oauthTokenEndpoint":"https://%[1]s/oauth/token","sharedInbox":"https://%[1]s/inbox","uploadMedia":"https://%[1]s/api/ap/upload_media"},"followers":"https://%[1]s/internal/fetch/followers","following":"https://%[1]s/internal/fetch/following","id":"https://%[1]s/internal/fetch","inbox":"https://%[1]s/internal/fetch/inbox","invisible":true,"manuallyApprovesFollowers":false,"name":"Pleroma","preferredUsername":"fedilogue","publicKey":{"id":"https://%[1]s/internal/fetch#main-key","owner":"https://%[1]s/internal/fetch","publicKeyPem":"%[2]s"},"summary":"Fedilogue Key or something.","type":"Application","url":"https://%[1]s/internal/fetch"}`, r.Host, publicKeyString) fmt.Fprintf(w, staticjson) } func relay(w http.ResponseWriter, r *http.Request) { fmt.Println("Someone out there requested /relay") publicKeyBytes, err := ioutil.ReadFile("keys/public.pem") publicKeyString := string(publicKeyBytes) publicKeyString = strings.Replace(publicKeyString, "\n", "\\n", -11) if err != nil { log.Fatal(err) } staticjson := fmt.Sprintf(`{"@context":["https://www.w3.org/ns/activitystreams","https://%[1]s/schemas/litepub-0.1.jsonld",{"@language":"und"}],"alsoKnownAs":[],"attachment":[],"capabilities":{},"discoverable":false,"endpoints":{"oauthAuthorizationEndpoint":"https://%[1]s/oauth/authorize","oauthRegistrationEndpoint":"https://%[1]s/api/v1/apps","oauthTokenEndpoint":"https://%[1]s/oauth/token","sharedInbox":"https://%[1]s/inbox","uploadMedia":"https://%[1]s/api/ap/upload_media"},"featured":"https://%[1]s/relay/collections/featured","followers":"https://%[1]s/relay/followers","following":"https://%[1]s/relay/following","id":"https://%[1]s/relay","inbox":"https://%[1]s/relay/inbox","manuallyApprovesFollowers":false,"name":null,"outbox":"https://%[1]s/relay/outbox","preferredUsername":"relay","publicKey":{"id":"https://%[1]s/relay#main-key","owner":"https://%[1]s/relay","publicKeyPem":"%[2]s"},"summary":"","tag":[],"type":"Person","url":"https://%[1]s/relay"}`, r.Host, publicKeyString) fmt.Fprintf(w, staticjson) } func usersFedilogueFollowers(w http.ResponseWriter, r *http.Request) { fmt.Println("PATH --> ", r.URL.Path) host := r.Host contextlist := map[string]string{"@language": "und"} context := []interface{}{"https://www.w3.org/ns/activitystreams", "https://" + host + "/schemas/litepub-0.1.jsonld", contextlist} followersmap := make(map[string]interface{}) followersmap["@context"] = context staticjson := "{\"@context\":[\"https://www.w3.org/ns/activitystreams\",\"https://" + host + "/schemas/litepub-0.1.jsonld\",{\"@language\":\"und\"}],\"first\":{\"id\":\"https://" + host + "/users/fedilogue/followers?page=1\",\"next\":\"https://" + host + "/users/fedilogue/followers?page=2\",\"orderedItems\":[\"https://mastodon.host/users/federationbot\"],\"partOf\":\"https://" + host + "/users/fedilogue/followers\",\"totalItems\":1,\"type\":\"OrderedCollectionPage\"},\"id\":\"https://" + host + "/users/fedilogue/followers\",\"totalItems\":1,\"type\":\"OrderedCollection\"}" w.Header().Set("Content-Type", "application/activity+json; charset=utf-8") fmt.Fprintf(w, staticjson) } func usersFedilogueFollowing(w http.ResponseWriter, r *http.Request) { host := r.Host fmt.Println("PATH --> ", r.URL.Path) staticjson := "{\"@context\": [\"https://www.w3.org/ns/activitystreams\", \"https://" + host + "/schemas/litepub-0.1.jsonld\", {\"@language\": \"und\"}], \"first\": {\"id\": \"https://" + host + "/users/fedilogue/following?page=1\", \"orderedItems\": [], \"partOf\": \"https://" + host + "/users/fedilogue/following\", \"totalItems\": 0, \"type\": \"OrderedCollectionPage\"}, \"id\": \"https://" + host + "/users/fedilogue/following\", \"totalItems\": 0, \"type\": \"OrderedCollection\"}" w.Header().Set("Content-Type", "application/activity+json; charset=utf-8") fmt.Fprintf(w, staticjson) } func usersFedilogue(w http.ResponseWriter, r *http.Request) { fmt.Println("PATH --> ", r.URL.Path) host := r.Host fmt.Println(r.Host) fmt.Println(r.Header["Accept"]) publickeybin, err := ioutil.ReadFile("keys/public.pem") if err != nil { fmt.Println(err) os.Exit(1) } publickeypemstr := string(publickeybin) publicKey := map[string]string{"id": "https://" + host + "/users/fedilogue#main-key", "owner": "https://" + host + "/users/fedilogue", "publicKeyPem": publickeypemstr} capabilities := map[string]bool{} tag := []string{} contextlist := map[string]string{"@language": "und"} attachment := []string{} endpoints := map[string]string{"oauthAuthorizationEndpoint": "https://" + host + "/oauth/authorize", "oauthRegistrationEndpoint": "https://" + host + "/api/v1/apps", "oauthTokenEndpoint": "https://" + host + "/oauth/token", "sharedInbox": "https://" + host + "/inbox", "uploadMedia": "https://" + host + "/api/ap/upload_media"} context := []interface{}{"https://www.w3.org/ns/activitystreams", "https://" + host + "/schemas/litepub-0.1.jsonld", contextlist} actorjsonmap := make(map[string]interface{}) actorjsonmap["@context"] = context actorjsonmap["attachment"] = attachment actorjsonmap["capabilities"] = capabilities actorjsonmap["discoverable"] = false actorjsonmap["endpoints"] = endpoints actorjsonmap["followers"] = "https://" + host + "/users/fedilogue/followers" actorjsonmap["following"] = "https://" + host + "/users/fedilogue/following" actorjsonmap["id"] = "https://" + host + "/users/fedilogue" actorjsonmap["inbox"] = "https://" + host + "/users/fedilogue/inbox" actorjsonmap["manuallyApprovesFollowers"] = false actorjsonmap["name"] = "Fedilogue Mass Follower" actorjsonmap["outbox"] = "https://" + host + "/users/fedilogue/outbox" actorjsonmap["preferredUsername"] = "fedilogue" actorjsonmap["publicKey"] = publicKey actorjsonmap["summary"] = "" actorjsonmap["tag"] = tag actorjsonmap["type"] = "Application" actorjsonmap["uri"] = "https://" + host + "/users/fedilogue" actorjsonbin, err := json.Marshal(actorjsonmap) if err != nil { fmt.Println(err.Error()) return } actorjsonstr := string(actorjsonbin) w.Header().Set("Content-Type", "application/activity+json; charset=utf-8") fmt.Fprintf(w, actorjsonstr) } func errorHandler(w http.ResponseWriter, r *http.Request) { for name, headers := range r.Header { fmt.Println("ROW: ", name, " ", headers) for _, h := range headers { fmt.Fprintf(w, "%v: %v\n", name, h) } } reqBody, err := ioutil.ReadAll(r.Body) if err != nil { log.Fatal(err) } fmt.Printf("POST DATA: %s\n", reqBody) } func webmain() { webreceiver := http.NewServeMux() webreceiver.HandleFunc("/.well-known/webfinger", webfinger) webreceiver.HandleFunc("/.well-known/host-meta", hostmeta) webreceiver.HandleFunc("/inbox", inboxHandler()) webreceiver.HandleFunc("/internal/fetch", internalFetch) webreceiver.HandleFunc("/relay", relay) webreceiver.HandleFunc("/users/fedilogue", usersFedilogue) webreceiver.HandleFunc("/users/fedilogue/followers", usersFedilogueFollowers) webreceiver.HandleFunc("/users/fedilogue/following", usersFedilogueFollowing) webreceiver.HandleFunc("/", errorHandler) log.Print("Starting HTTP inbox on port 127.0.0.1:8042") log.Fatal(http.ListenAndServe("127.0.0.1:8042", webreceiver)) }