jlelse
/
jsonpub
Archived
1
Fork 0
This repository has been archived on 2020-04-25. You can view files and clone it, but cannot push or open issues or pull requests.
jsonpub/http.go

200 lines
5.9 KiB
Go
Raw Permalink Normal View History

2020-02-04 20:25:57 +00:00
package main
import (
"encoding/json"
"fmt"
2020-02-04 20:25:57 +00:00
"github.com/gorilla/mux"
"log"
"net/http"
"net/url"
2020-02-24 20:51:33 +00:00
"os"
2020-02-04 20:25:57 +00:00
"regexp"
2020-03-10 14:40:04 +00:00
"strings"
"time"
2020-02-04 20:25:57 +00:00
"willnorris.com/go/webmention"
)
func Serve() {
hookHandler := func(w http.ResponseWriter, r *http.Request) {
fmt.Println("Fetch feeds: ", time.Now().Format(time.RFC3339))
2020-04-11 19:33:18 +00:00
go func() {
for _, actor := range actors {
fmt.Println(actor.feed)
articles, err := allFeedItems(actor.feed)
if err != nil {
2020-04-11 19:33:18 +00:00
fmt.Println(actor.feed, err.Error())
continue
}
2020-04-20 21:48:26 +00:00
if len(articles) < 1 {
2020-04-11 19:57:54 +00:00
fmt.Println(actor.feed, "Empty feed")
continue
}
2020-04-20 21:48:26 +00:00
err = actor.PostArticle(articles[0])
2020-04-11 19:57:54 +00:00
if err != nil {
2020-04-20 21:48:26 +00:00
fmt.Println("Posting", articles[0], "failed")
}
}
2020-04-11 19:33:18 +00:00
}()
}
2020-02-04 20:25:57 +00:00
webfingerHandler := func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("content-type", "application/jrd+json; charset=utf-8")
name := r.URL.Query().Get("resource") // should be something like acct:user@example.com
urlBaseUrl, _ := url.Parse(baseURL)
re := regexp.MustCompile(`^acct:(.*)@` + regexp.QuoteMeta(urlBaseUrl.Host) + `$`)
name = re.ReplaceAllString(name, "$1")
actor := actors[name]
if actor == nil && len(defaultActor) > 0 {
// return default actor
actor = actors[defaultActor]
} else if actor == nil {
// error out if this actor does not exist
2020-02-04 20:25:57 +00:00
w.WriteHeader(http.StatusNotFound)
return
}
responseMap := make(map[string]interface{})
responseMap["subject"] = "acct:" + actor.Name + "@" + urlBaseUrl.Host
// links is a json array with a single element
var links [1]map[string]string
link1 := make(map[string]string)
link1["rel"] = "self"
link1["type"] = ContentTypeAs2
link1["href"] = actor.iri
links[0] = link1
responseMap["links"] = links
2020-03-26 18:04:05 +00:00
_ = json.NewEncoder(w).Encode(responseMap)
2020-02-04 20:25:57 +00:00
}
inboxHandler := func(w http.ResponseWriter, r *http.Request) {
activity := make(map[string]interface{})
2020-03-26 18:04:05 +00:00
err := json.NewDecoder(r.Body).Decode(&activity)
2020-04-20 21:48:26 +00:00
_ = r.Body.Close()
2020-02-04 20:25:57 +00:00
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
2020-02-24 20:51:33 +00:00
actor := actors[mux.Vars(r)["actor"]]
if actor == nil {
// actor doesn't exist
w.WriteHeader(http.StatusNotFound)
return
}
switch activity["type"] {
case "Follow":
2020-04-20 21:48:26 +00:00
actor.Accept(activity)
case "Undo":
{
if object, ok := activity["object"].(map[string]interface{}); ok {
if objectType, ok := object["type"].(string); ok && objectType == "Follow" {
if iri, ok := object["actor"].(string); ok && iri == activity["actor"] {
_ = actor.RemoveFollower(iri)
fmt.Println(iri, "unfollowed")
if telegramBot != nil {
_ = telegramBot.Post(iri + " unfollowed")
}
}
2020-02-04 20:25:57 +00:00
}
}
}
case "Create":
{
if object, ok := activity["object"].(map[string]interface{}); ok {
2020-03-10 14:40:04 +00:00
inReplyTo, hasReplyToString := object["inReplyTo"].(string)
id, hasId := object["id"].(string)
2020-04-02 20:45:06 +00:00
if hasReplyToString && hasId && len(inReplyTo) > 0 && len(id) > 0 && strings.Contains(inReplyTo, actor.iri) {
2020-03-10 14:40:04 +00:00
// It's an ActivityPub reply
fmt.Println("Received reply to:", inReplyTo)
webmentionClient := webmention.New(nil)
2020-03-10 14:40:04 +00:00
sendWebmention(webmentionClient, actor, id, inReplyTo)
} else if hasId && len(id) > 0 {
// May be a mention
webmentionClient := webmention.New(nil)
dl, err := webmentionClient.DiscoverLinks(id, "")
if err != nil {
return
}
2020-03-10 14:40:04 +00:00
// Send Webmentions
2020-04-20 21:48:26 +00:00
sent := map[string]bool{}
2020-03-10 14:40:04 +00:00
for _, link := range dl {
2020-04-20 21:48:26 +00:00
if !sent[link] {
sendWebmention(webmentionClient, actor, id, link)
sent[link] = true
}
}
2020-02-04 20:25:57 +00:00
}
}
}
case "Delete":
{
if object, ok := activity["object"].(string); ok && len(object) > 0 && activity["actor"] == object {
_ = actor.RemoveFollower(object)
}
}
case "Like":
{
likeActor, likeActorOk := activity["actor"].(string)
likeObject, likeObjectOk := activity["object"].(string)
if likeActorOk && likeObjectOk && len(likeActor) > 0 && len(likeObject) > 0 && strings.Contains(likeObject, actor.iri) {
fmt.Println(likeActor, "liked", likeObject)
if telegramBot != nil {
_ = telegramBot.Post(likeActor + " liked " + likeObject)
}
}
}
case "Announce":
{
announceActor, announceActorOk := activity["actor"].(string)
announceObject, announceObjectOk := activity["object"].(string)
if announceActorOk && announceObjectOk && len(announceActor) > 0 && len(announceObject) > 0 && strings.Contains(announceObject, actor.iri) {
fmt.Println(announceActor, "announced", announceObject)
if telegramBot != nil {
_ = telegramBot.Post(announceActor + " announced " + announceObject)
}
}
}
2020-03-10 14:40:04 +00:00
default:
// Log inbox request
2020-04-20 21:48:26 +00:00
logInbox(actor, activity)
2020-02-04 20:25:57 +00:00
}
2020-02-24 21:10:36 +00:00
// Return 201
w.WriteHeader(http.StatusCreated)
2020-02-04 20:25:57 +00:00
}
// Add the handlers to a HTTP server
gorilla := mux.NewRouter()
gorilla.HandleFunc("/hook", hookHandler).Methods(http.MethodPost)
2020-02-04 20:25:57 +00:00
gorilla.HandleFunc("/.well-known/webfinger", webfingerHandler)
gorilla.PathPrefix("/{actor}/inbox").HandlerFunc(inboxHandler).Methods(http.MethodPost)
2020-02-04 20:25:57 +00:00
http.Handle("/", gorilla)
log.Fatal(http.ListenAndServe(":8081", nil))
}
2020-03-10 14:40:04 +00:00
2020-04-20 21:48:26 +00:00
func logInbox(actor *Actor, activity map[string]interface{}) {
2020-03-10 14:40:04 +00:00
f, err := os.OpenFile(storage+slash+"actors"+slash+actor.Name+slash+"inbox", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
2020-04-20 21:48:26 +00:00
defer func() { _ = f.Close() }()
2020-03-10 14:40:04 +00:00
if err != nil {
return
}
2020-03-26 18:04:05 +00:00
_ = json.NewEncoder(f).Encode(activity)
2020-03-10 14:40:04 +00:00
_, _ = f.WriteString("\n---\n")
}
func sendWebmention(client *webmention.Client, actor *Actor, mentioningLink, mentionedLink string) {
if !strings.Contains(mentionedLink, actor.iri) {
// Not mention of blog
return
}
endpoint, err := client.DiscoverEndpoint(mentionedLink)
if err != nil || len(endpoint) < 1 {
return
}
_, err = client.SendWebmention(endpoint, mentioningLink, mentionedLink)
if err != nil {
log.Println("Sending webmention to " + mentionedLink + " failed")
return
}
log.Println("Sent webmention to " + mentionedLink)
}