aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFChannel <>2022-05-02 12:44:41 -0700
committerFChannel <>2022-06-19 12:53:29 -0700
commit1ee6552559141dd5dba91abec7c81d68c56abda0 (patch)
tree4ac21571a27980e8ebf83a065c270b36cc3ecfd6
parent733f911fadc872933481bcbe087d519ce00372df (diff)
removed all unneeded .go files from root directory
-rw-r--r--activitypub/actor.go30
-rw-r--r--client.go210
-rw-r--r--db/follow.go32
-rw-r--r--main.go8
-rw-r--r--outboxGet.go46
-rw-r--r--outboxPost.go245
-rw-r--r--post/util.go179
-rw-r--r--routes/actor.go177
-rw-r--r--util/proxy.go17
-rw-r--r--webfinger/webfinger.go25
10 files changed, 461 insertions, 508 deletions
diff --git a/activitypub/actor.go b/activitypub/actor.go
index e837df5..3fbcb75 100644
--- a/activitypub/actor.go
+++ b/activitypub/actor.go
@@ -863,3 +863,33 @@ func WriteActorObjectToCache(obj ObjectBase) (ObjectBase, error) {
return obj, nil
}
+
+func GetActorOutbox(ctx *fiber.Ctx, actor Actor) error {
+
+ var collection Collection
+
+ c, err := GetActorObjectCollectionFromDB(actor.Id)
+ if err != nil {
+ return err
+ }
+ collection.OrderedItems = c.OrderedItems
+
+ collection.AtContext.Context = "https://www.w3.org/ns/activitystreams"
+ collection.Actor = &actor
+
+ collection.TotalItems, err = GetObjectPostsTotalDB(actor)
+ if err != nil {
+ return err
+ }
+
+ collection.TotalImgs, err = GetObjectImgsTotalDB(actor)
+ if err != nil {
+ return err
+ }
+
+ enc, _ := json.Marshal(collection)
+
+ ctx.Response().Header.Set("Content-Type", config.ActivityStreams)
+ _, err = ctx.Write(enc)
+ return err
+}
diff --git a/client.go b/client.go
deleted file mode 100644
index f4094ba..0000000
--- a/client.go
+++ /dev/null
@@ -1,210 +0,0 @@
-package main
-
-import (
- "html/template"
- "regexp"
- "strings"
-
- "github.com/FChannel0/FChannel-Server/activitypub"
- "github.com/FChannel0/FChannel-Server/config"
- "github.com/FChannel0/FChannel-Server/db"
- "github.com/FChannel0/FChannel-Server/post"
- "github.com/FChannel0/FChannel-Server/util"
- "github.com/FChannel0/FChannel-Server/webfinger"
- _ "github.com/lib/pq"
-)
-
-func MediaProxy(url string) string {
- re := regexp.MustCompile("(.+)?" + config.Domain + "(.+)?")
-
- if re.MatchString(url) {
- return url
- }
-
- re = regexp.MustCompile("(.+)?\\.onion(.+)?")
-
- if re.MatchString(url) {
- return url
- }
-
- config.MediaHashs[util.HashMedia(url)] = url
- return "/api/media?hash=" + util.HashMedia(url)
-}
-
-func ParseAttachment(obj activitypub.ObjectBase, catalog bool) template.HTML {
- // TODO: convert all of these to Sprintf statements, or use strings.Builder or something, anything but this really
- // string concatenation is highly inefficient _especially_ when being used like this
-
- if len(obj.Attachment) < 1 {
- return ""
- }
-
- var media string
- if regexp.MustCompile(`image\/`).MatchString(obj.Attachment[0].MediaType) {
- media = "<img "
- media += "id=\"img\" "
- media += "main=\"1\" "
- media += "enlarge=\"0\" "
- media += "attachment=\"" + obj.Attachment[0].Href + "\""
- if catalog {
- media += "style=\"max-width: 180px; max-height: 180px;\" "
- } else {
- media += "style=\"float: left; margin-right: 10px; margin-bottom: 10px; max-width: 250px; max-height: 250px;\""
- }
- if obj.Preview.Id != "" {
- media += "src=\"" + MediaProxy(obj.Preview.Href) + "\""
- media += "preview=\"" + MediaProxy(obj.Preview.Href) + "\""
- } else {
- media += "src=\"" + MediaProxy(obj.Attachment[0].Href) + "\""
- media += "preview=\"" + MediaProxy(obj.Attachment[0].Href) + "\""
- }
-
- media += ">"
-
- return template.HTML(media)
- }
-
- if regexp.MustCompile(`audio\/`).MatchString(obj.Attachment[0].MediaType) {
- media = "<audio "
- media += "controls=\"controls\" "
- media += "preload=\"metadta\" "
- if catalog {
- media += "style=\"margin-right: 10px; margin-bottom: 10px; max-width: 180px; max-height: 180px;\" "
- } else {
- media += "style=\"float: left; margin-right: 10px; margin-bottom: 10px; max-width: 250px; max-height: 250px;\" "
- }
- media += ">"
- media += "<source "
- media += "src=\"" + MediaProxy(obj.Attachment[0].Href) + "\" "
- media += "type=\"" + obj.Attachment[0].MediaType + "\" "
- media += ">"
- media += "Audio is not supported."
- media += "</audio>"
-
- return template.HTML(media)
- }
-
- if regexp.MustCompile(`video\/`).MatchString(obj.Attachment[0].MediaType) {
- media = "<video "
- media += "controls=\"controls\" "
- media += "preload=\"metadta\" "
- media += "muted=\"muted\" "
- if catalog {
- media += "style=\"margin-right: 10px; margin-bottom: 10px; max-width: 180px; max-height: 180px;\" "
- } else {
- media += "style=\"float: left; margin-right: 10px; margin-bottom: 10px; max-width: 250px; max-height: 250px;\" "
- }
- media += ">"
- media += "<source "
- media += "src=\"" + MediaProxy(obj.Attachment[0].Href) + "\" "
- media += "type=\"" + obj.Attachment[0].MediaType + "\" "
- media += ">"
- media += "Video is not supported."
- media += "</video>"
-
- return template.HTML(media)
- }
-
- return template.HTML(media)
-}
-
-func ParseContent(board activitypub.Actor, op string, content string, thread activitypub.ObjectBase) (template.HTML, error) {
- // TODO: should escape more than just < and >, should also escape &, ", and '
- nContent := strings.ReplaceAll(content, `<`, "&lt;")
-
- nContent, err := ParseLinkComments(board, op, nContent, thread)
- if err != nil {
- return "", err
- }
-
- nContent = ParseCommentQuotes(nContent)
-
- nContent = strings.ReplaceAll(nContent, `/\&lt;`, ">")
-
- return template.HTML(nContent), nil
-}
-
-func ParseLinkComments(board activitypub.Actor, op string, content string, thread activitypub.ObjectBase) (string, error) {
- re := regexp.MustCompile(`(>>(https?://[A-Za-z0-9_.:\-~]+\/[A-Za-z0-9_.\-~]+\/)(f[A-Za-z0-9_.\-~]+-)?([A-Za-z0-9_.\-~]+)?#?([A-Za-z0-9_.\-~]+)?)`)
- match := re.FindAllStringSubmatch(content, -1)
-
- //add url to each matched reply
- for i, _ := range match {
- link := strings.Replace(match[i][0], ">>", "", 1)
- isOP := ""
-
- domain := match[i][2]
-
- if link == op {
- isOP = " (OP)"
- }
-
- parsedLink := post.ConvertHashLink(domain, link)
-
- //formate the hover title text
- var quoteTitle string
-
- // if the quoted content is local get it
- // else get it from the database
- if thread.Id == link {
- quoteTitle = post.ParseLinkTitle(board.Outbox, op, thread.Content)
- } else {
- for _, e := range thread.Replies.OrderedItems {
- if e.Id == parsedLink {
- quoteTitle = post.ParseLinkTitle(board.Outbox, op, e.Content)
- break
- }
- }
-
- if quoteTitle == "" {
- obj, err := activitypub.GetObjectFromDBFromID(parsedLink)
- if err != nil {
- return "", err
- }
-
- if len(obj.OrderedItems) > 0 {
- quoteTitle = post.ParseLinkTitle(board.Outbox, op, obj.OrderedItems[0].Content)
- } else {
- quoteTitle = post.ParseLinkTitle(board.Outbox, op, parsedLink)
- }
- }
- }
-
- if replyID, isReply, err := db.IsReplyToOP(op, parsedLink); err == nil || !isReply {
- id := util.ShortURL(board.Outbox, replyID)
-
- content = strings.Replace(content, match[i][0], "<a class=\"reply\" title=\""+quoteTitle+"\" href=\"/"+board.Name+"/"+util.ShortURL(board.Outbox, op)+"#"+id+"\">&gt;&gt;"+id+""+isOP+"</a>", -1)
- } else {
- //this is a cross post
-
- parsedOP, err := db.GetReplyOP(parsedLink)
- if err == nil {
- link = parsedOP + "#" + util.ShortURL(parsedOP, parsedLink)
- }
-
- actor, err := webfinger.FingerActor(parsedLink)
- if err == nil && actor.Id != "" {
- content = strings.Replace(content, match[i][0], "<a class=\"reply\" title=\""+quoteTitle+"\" href=\""+link+"\">&gt;&gt;"+util.ShortURL(board.Outbox, parsedLink)+isOP+" →</a>", -1)
- }
- }
- }
-
- return content, nil
-}
-
-func ParseCommentQuotes(content string) string {
- // replace quotes
- re := regexp.MustCompile(`((\r\n|\r|\n|^)>(.+)?[^\r\n])`)
- match := re.FindAllStringSubmatch(content, -1)
-
- for i, _ := range match {
- quote := strings.Replace(match[i][0], ">", "&gt;", 1)
- line := re.ReplaceAllString(match[i][0], "<span class=\"quote\">"+quote+"</span>")
- content = strings.Replace(content, match[i][0], line, 1)
- }
-
- //replace isolated greater than symboles
- re = regexp.MustCompile(`(\r\n|\n|\r)>`)
-
- return re.ReplaceAllString(content, "\r\n<span class=\"quote\">&gt;</span>")
-}
diff --git a/db/follow.go b/db/follow.go
index 1aa9965..3f7868d 100644
--- a/db/follow.go
+++ b/db/follow.go
@@ -270,3 +270,35 @@ func MakeActivityRequest(activity activitypub.Activity) error {
return nil
}
+
+func SendToFollowers(actor string, activity activitypub.Activity) error {
+ nActor, err := activitypub.GetActorFromDB(actor)
+ if err != nil {
+ return err
+ }
+
+ activity.Actor = &nActor
+
+ followers, err := activitypub.GetActorFollowDB(actor)
+ if err != nil {
+ return err
+ }
+
+ var to []string
+
+ for _, e := range followers {
+ for _, k := range activity.To {
+ if e.Id != k {
+ to = append(to, e.Id)
+ }
+ }
+ }
+
+ activity.To = to
+
+ if len(activity.Object.InReplyTo) > 0 {
+ err = MakeActivityRequest(activity)
+ }
+
+ return err
+}
diff --git a/main.go b/main.go
index 363a88f..c83ba10 100644
--- a/main.go
+++ b/main.go
@@ -84,7 +84,7 @@ func main() {
app.Post("/:actor", routes.ActorPost)
app.Get("/:actor/catalog", routes.CatalogGet)
app.Get("/:actor/:post", routes.PostGet)
- app.Get("/:actor/inbox", routes.ActorInbox)
+ app.Post("/:actor/inbox", routes.ActorInbox)
app.Post("/:actor/outbox", routes.ActorOutbox)
app.Get("/:actor/following", routes.ActorFollowing)
app.Get("/:actor/followers", routes.ActorFollowers)
@@ -183,14 +183,14 @@ func TemplateFunctions(engine *html.Engine) {
return fmt.Sprint(t.Unix())
})
- engine.AddFunc("proxy", MediaProxy)
+ engine.AddFunc("proxy", util.MediaProxy)
// previously short
engine.AddFunc("shortURL", util.ShortURL)
- engine.AddFunc("parseAttachment", ParseAttachment)
+ engine.AddFunc("parseAttachment", post.ParseAttachment)
- engine.AddFunc("parseContent", ParseContent)
+ engine.AddFunc("parseContent", post.ParseContent)
engine.AddFunc("shortImg", util.ShortImg)
diff --git a/outboxGet.go b/outboxGet.go
deleted file mode 100644
index 27e9cc4..0000000
--- a/outboxGet.go
+++ /dev/null
@@ -1,46 +0,0 @@
-package main
-
-import (
- "net/http"
-
- "encoding/json"
-
- "github.com/FChannel0/FChannel-Server/activitypub"
- "github.com/FChannel0/FChannel-Server/config"
- "github.com/FChannel0/FChannel-Server/webfinger"
- _ "github.com/lib/pq"
-)
-
-func GetActorOutbox(w http.ResponseWriter, r *http.Request) error {
- actor, err := webfinger.GetActorFromPath(r.URL.Path, "/")
- if err != nil {
- return err
- }
-
- var collection activitypub.Collection
-
- c, err := activitypub.GetActorObjectCollectionFromDB(actor.Id)
- if err != nil {
- return err
- }
- collection.OrderedItems = c.OrderedItems
-
- collection.AtContext.Context = "https://www.w3.org/ns/activitystreams"
- collection.Actor = &actor
-
- collection.TotalItems, err = activitypub.GetObjectPostsTotalDB(actor)
- if err != nil {
- return err
- }
-
- collection.TotalImgs, err = activitypub.GetObjectImgsTotalDB(actor)
- if err != nil {
- return err
- }
-
- enc, _ := json.Marshal(collection)
-
- w.Header().Set("Content-Type", config.ActivityStreams)
- _, err = w.Write(enc)
- return err
-}
diff --git a/outboxPost.go b/outboxPost.go
deleted file mode 100644
index 677fa79..0000000
--- a/outboxPost.go
+++ /dev/null
@@ -1,245 +0,0 @@
-package main
-
-import (
- "encoding/json"
- "fmt"
- "io/ioutil"
- "net/http"
-
- "github.com/FChannel0/FChannel-Server/activitypub"
- "github.com/FChannel0/FChannel-Server/config"
- "github.com/FChannel0/FChannel-Server/db"
- "github.com/FChannel0/FChannel-Server/util"
- "github.com/FChannel0/FChannel-Server/webfinger"
- "github.com/gofiber/fiber/v2"
- _ "github.com/lib/pq"
-)
-
-func ParseInboxRequest(ctx *fiber.Ctx) error {
- activity, err := activitypub.GetActivityFromJson(ctx)
- if err != nil {
- return err
- }
-
- if activity.Actor.PublicKey.Id == "" {
- nActor, err := webfinger.FingerActor(activity.Actor.Id)
- if err != nil {
- return err
- }
-
- activity.Actor = &nActor
- }
-
- if !db.VerifyHeaderSignature(ctx, *activity.Actor) {
- response := activitypub.RejectActivity(activity)
-
- return db.MakeActivityRequest(response)
- }
-
- switch activity.Type {
- case "Create":
-
- for _, e := range activity.To {
- if res, err := activitypub.IsActorLocal(e); err == nil && res {
- if res, err := activitypub.IsActorLocal(activity.Actor.Id); err == nil && res {
- col, err := activitypub.GetCollectionFromID(activity.Object.Id)
- if err != nil {
- return err
- }
-
- if len(col.OrderedItems) < 1 {
- break
- }
-
- if _, err := activitypub.WriteObjectToCache(*activity.Object); err != nil {
- return err
- }
-
- actor, err := activitypub.GetActorFromDB(e)
- if err != nil {
- return err
- }
-
- if err := db.ArchivePosts(actor); err != nil {
- return err
- }
-
- //SendToFollowers(e, activity)
- } else if err != nil {
- return err
- }
- } else if err != nil {
- return err
- }
- }
-
- break
-
- case "Delete":
- for _, e := range activity.To {
- actor, err := activitypub.GetActorFromDB(e)
- if err != nil {
- return err
- }
-
- if actor.Id != "" && actor.Id != config.Domain {
- if activity.Object.Replies != nil {
- for _, k := range activity.Object.Replies.OrderedItems {
- if err := activitypub.TombstoneObject(k.Id); err != nil {
- return err
- }
- }
- }
-
- if err := activitypub.TombstoneObject(activity.Object.Id); err != nil {
- return err
- }
- if err := db.UnArchiveLast(actor.Id); err != nil {
- return err
- }
- break
- }
- }
- break
-
- case "Follow":
- for _, e := range activity.To {
- if res, err := activitypub.GetActorFromDB(e); err == nil && res.Id != "" {
- response := db.AcceptFollow(activity)
- response, err := activitypub.SetActorFollowerDB(response)
- if err != nil {
- return err
- }
-
- if err := db.MakeActivityRequest(response); err != nil {
- return err
- }
-
- alreadyFollow := false
- alreadyFollowing := false
- autoSub, err := activitypub.GetActorAutoSubscribeDB(response.Actor.Id)
- if err != nil {
- return err
- }
-
- following, err := activitypub.GetActorFollowingDB(response.Actor.Id)
- if err != nil {
- return err
- }
-
- for _, e := range following {
- if e.Id == response.Object.Id {
- alreadyFollow = true
- }
- }
-
- actor, err := webfinger.FingerActor(response.Object.Actor)
- if err != nil {
- return err
- }
-
- remoteActorFollowingCol, err := webfinger.GetCollectionFromReq(actor.Following)
- if err != nil {
- return err
- }
-
- for _, e := range remoteActorFollowingCol.Items {
- if e.Id == response.Actor.Id {
- alreadyFollowing = true
- }
- }
-
- if autoSub && !alreadyFollow && alreadyFollowing {
- followActivity, err := db.MakeFollowActivity(response.Actor.Id, response.Object.Actor)
- if err != nil {
- return err
- }
-
- if res, err := webfinger.FingerActor(response.Object.Actor); err == nil && res.Id != "" {
- if err := db.MakeActivityRequestOutbox(followActivity); err != nil {
- return err
- }
- } else if err != nil {
- return err
- }
- }
- } else if err != nil {
- return err
- } else {
- fmt.Println("follow request for rejected")
- response := activitypub.RejectActivity(activity)
-
- return db.MakeActivityRequest(response)
- }
- }
- break
-
- case "Reject":
- if activity.Object.Object.Type == "Follow" {
- fmt.Println("follow rejected")
- if _, err := db.SetActorFollowingDB(activity); err != nil {
- return err
- }
- }
- break
- }
-
- return nil
-}
-
-func MakeActivityFollowingReq(w http.ResponseWriter, r *http.Request, activity activitypub.Activity) (bool, error) {
- actor, err := webfinger.GetActor(activity.Object.Id)
- if err != nil {
- return false, err
- }
-
- req, err := http.NewRequest("POST", actor.Inbox, nil)
- if err != nil {
- return false, err
- }
-
- resp, err := util.RouteProxy(req)
- if err != nil {
- return false, err
- }
- defer resp.Body.Close()
-
- body, _ := ioutil.ReadAll(resp.Body)
-
- var respActivity activitypub.Activity
-
- err = json.Unmarshal(body, &respActivity)
- return respActivity.Type == "Accept", err
-}
-
-func SendToFollowers(actor string, activity activitypub.Activity) error {
- nActor, err := activitypub.GetActorFromDB(actor)
- if err != nil {
- return err
- }
-
- activity.Actor = &nActor
-
- followers, err := activitypub.GetActorFollowDB(actor)
- if err != nil {
- return err
- }
-
- var to []string
-
- for _, e := range followers {
- for _, k := range activity.To {
- if e.Id != k {
- to = append(to, e.Id)
- }
- }
- }
-
- activity.To = to
-
- if len(activity.Object.InReplyTo) > 0 {
- err = db.MakeActivityRequest(activity)
- }
-
- return err
-}
diff --git a/post/util.go b/post/util.go
index c653276..b9d9b80 100644
--- a/post/util.go
+++ b/post/util.go
@@ -2,6 +2,7 @@ package post
import (
"fmt"
+ "html/template"
"io/ioutil"
"mime/multipart"
"os"
@@ -382,3 +383,181 @@ func ResizeAttachmentToPreview() error {
return nil
})
}
+
+func ParseAttachment(obj activitypub.ObjectBase, catalog bool) template.HTML {
+ // TODO: convert all of these to Sprintf statements, or use strings.Builder or something, anything but this really
+ // string concatenation is highly inefficient _especially_ when being used like this
+
+ if len(obj.Attachment) < 1 {
+ return ""
+ }
+
+ var media string
+ if regexp.MustCompile(`image\/`).MatchString(obj.Attachment[0].MediaType) {
+ media = "<img "
+ media += "id=\"img\" "
+ media += "main=\"1\" "
+ media += "enlarge=\"0\" "
+ media += "attachment=\"" + obj.Attachment[0].Href + "\""
+ if catalog {
+ media += "style=\"max-width: 180px; max-height: 180px;\" "
+ } else {
+ media += "style=\"float: left; margin-right: 10px; margin-bottom: 10px; max-width: 250px; max-height: 250px;\""
+ }
+ if obj.Preview.Id != "" {
+ media += "src=\"" + util.MediaProxy(obj.Preview.Href) + "\""
+ media += "preview=\"" + util.MediaProxy(obj.Preview.Href) + "\""
+ } else {
+ media += "src=\"" + util.MediaProxy(obj.Attachment[0].Href) + "\""
+ media += "preview=\"" + util.MediaProxy(obj.Attachment[0].Href) + "\""
+ }
+
+ media += ">"
+
+ return template.HTML(media)
+ }
+
+ if regexp.MustCompile(`audio\/`).MatchString(obj.Attachment[0].MediaType) {
+ media = "<audio "
+ media += "controls=\"controls\" "
+ media += "preload=\"metadta\" "
+ if catalog {
+ media += "style=\"margin-right: 10px; margin-bottom: 10px; max-width: 180px; max-height: 180px;\" "
+ } else {
+ media += "style=\"float: left; margin-right: 10px; margin-bottom: 10px; max-width: 250px; max-height: 250px;\" "
+ }
+ media += ">"
+ media += "<source "
+ media += "src=\"" + util.MediaProxy(obj.Attachment[0].Href) + "\" "
+ media += "type=\"" + obj.Attachment[0].MediaType + "\" "
+ media += ">"
+ media += "Audio is not supported."
+ media += "</audio>"
+
+ return template.HTML(media)
+ }
+
+ if regexp.MustCompile(`video\/`).MatchString(obj.Attachment[0].MediaType) {
+ media = "<video "
+ media += "controls=\"controls\" "
+ media += "preload=\"metadta\" "
+ media += "muted=\"muted\" "
+ if catalog {
+ media += "style=\"margin-right: 10px; margin-bottom: 10px; max-width: 180px; max-height: 180px;\" "
+ } else {
+ media += "style=\"float: left; margin-right: 10px; margin-bottom: 10px; max-width: 250px; max-height: 250px;\" "
+ }
+ media += ">"
+ media += "<source "
+ media += "src=\"" + util.MediaProxy(obj.Attachment[0].Href) + "\" "
+ media += "type=\"" + obj.Attachment[0].MediaType + "\" "
+ media += ">"
+ media += "Video is not supported."
+ media += "</video>"
+
+ return template.HTML(media)
+ }
+
+ return template.HTML(media)
+}
+
+func ParseContent(board activitypub.Actor, op string, content string, thread activitypub.ObjectBase) (template.HTML, error) {
+ // TODO: should escape more than just < and >, should also escape &, ", and '
+ nContent := strings.ReplaceAll(content, `<`, "&lt;")
+
+ nContent, err := ParseLinkComments(board, op, nContent, thread)
+ if err != nil {
+ return "", err
+ }
+
+ nContent = ParseCommentQuotes(nContent)
+
+ nContent = strings.ReplaceAll(nContent, `/\&lt;`, ">")
+
+ return template.HTML(nContent), nil
+}
+
+func ParseLinkComments(board activitypub.Actor, op string, content string, thread activitypub.ObjectBase) (string, error) {
+ re := regexp.MustCompile(`(>>(https?://[A-Za-z0-9_.:\-~]+\/[A-Za-z0-9_.\-~]+\/)(f[A-Za-z0-9_.\-~]+-)?([A-Za-z0-9_.\-~]+)?#?([A-Za-z0-9_.\-~]+)?)`)
+ match := re.FindAllStringSubmatch(content, -1)
+
+ //add url to each matched reply
+ for i, _ := range match {
+ link := strings.Replace(match[i][0], ">>", "", 1)
+ isOP := ""
+
+ domain := match[i][2]
+
+ if link == op {
+ isOP = " (OP)"
+ }
+
+ parsedLink := ConvertHashLink(domain, link)
+
+ //formate the hover title text
+ var quoteTitle string
+
+ // if the quoted content is local get it
+ // else get it from the database
+ if thread.Id == link {
+ quoteTitle = ParseLinkTitle(board.Outbox, op, thread.Content)
+ } else {
+ for _, e := range thread.Replies.OrderedItems {
+ if e.Id == parsedLink {
+ quoteTitle = ParseLinkTitle(board.Outbox, op, e.Content)
+ break
+ }
+ }
+
+ if quoteTitle == "" {
+ obj, err := activitypub.GetObjectFromDBFromID(parsedLink)
+ if err != nil {
+ return "", err
+ }
+
+ if len(obj.OrderedItems) > 0 {
+ quoteTitle = ParseLinkTitle(board.Outbox, op, obj.OrderedItems[0].Content)
+ } else {
+ quoteTitle = ParseLinkTitle(board.Outbox, op, parsedLink)
+ }
+ }
+ }
+
+ if replyID, isReply, err := db.IsReplyToOP(op, parsedLink); err == nil || !isReply {
+ id := util.ShortURL(board.Outbox, replyID)
+
+ content = strings.Replace(content, match[i][0], "<a class=\"reply\" title=\""+quoteTitle+"\" href=\"/"+board.Name+"/"+util.ShortURL(board.Outbox, op)+"#"+id+"\">&gt;&gt;"+id+""+isOP+"</a>", -1)
+ } else {
+ //this is a cross post
+
+ parsedOP, err := db.GetReplyOP(parsedLink)
+ if err == nil {
+ link = parsedOP + "#" + util.ShortURL(parsedOP, parsedLink)
+ }
+
+ actor, err := webfinger.FingerActor(parsedLink)
+ if err == nil && actor.Id != "" {
+ content = strings.Replace(content, match[i][0], "<a class=\"reply\" title=\""+quoteTitle+"\" href=\""+link+"\">&gt;&gt;"+util.ShortURL(board.Outbox, parsedLink)+isOP+" →</a>", -1)
+ }
+ }
+ }
+
+ return content, nil
+}
+
+func ParseCommentQuotes(content string) string {
+ // replace quotes
+ re := regexp.MustCompile(`((\r\n|\r|\n|^)>(.+)?[^\r\n])`)
+ match := re.FindAllStringSubmatch(content, -1)
+
+ for i, _ := range match {
+ quote := strings.Replace(match[i][0], ">", "&gt;", 1)
+ line := re.ReplaceAllString(match[i][0], "<span class=\"quote\">"+quote+"</span>")
+ content = strings.Replace(content, match[i][0], line, 1)
+ }
+
+ //replace isolated greater than symboles
+ re = regexp.MustCompile(`(\r\n|\n|\r)>`)
+
+ return re.ReplaceAllString(content, "\r\n<span class=\"quote\">&gt;</span>")
+}
diff --git a/routes/actor.go b/routes/actor.go
index 7b57309..d8b6631 100644
--- a/routes/actor.go
+++ b/routes/actor.go
@@ -18,10 +18,176 @@ import (
"github.com/gofiber/fiber/v2"
)
-func ActorInbox(c *fiber.Ctx) error {
- // STUB
+func ActorInbox(ctx *fiber.Ctx) error {
+ activity, err := activitypub.GetActivityFromJson(ctx)
+ if err != nil {
+ return err
+ }
+
+ if activity.Actor.PublicKey.Id == "" {
+ nActor, err := webfinger.FingerActor(activity.Actor.Id)
+ if err != nil {
+ return err
+ }
+
+ activity.Actor = &nActor
+ }
+
+ if !db.VerifyHeaderSignature(ctx, *activity.Actor) {
+ response := activitypub.RejectActivity(activity)
+
+ return db.MakeActivityRequest(response)
+ }
+
+ switch activity.Type {
+ case "Create":
+
+ for _, e := range activity.To {
+ if res, err := activitypub.IsActorLocal(e); err == nil && res {
+ if res, err := activitypub.IsActorLocal(activity.Actor.Id); err == nil && res {
+ col, err := activitypub.GetCollectionFromID(activity.Object.Id)
+ if err != nil {
+ return err
+ }
+
+ if len(col.OrderedItems) < 1 {
+ break
+ }
+
+ if _, err := activitypub.WriteObjectToCache(*activity.Object); err != nil {
+ return err
+ }
+
+ actor, err := activitypub.GetActorFromDB(e)
+ if err != nil {
+ return err
+ }
+
+ if err := db.ArchivePosts(actor); err != nil {
+ return err
+ }
+
+ //SendToFollowers(e, activity)
+ } else if err != nil {
+ return err
+ }
+ } else if err != nil {
+ return err
+ }
+ }
+
+ break
+
+ case "Delete":
+ for _, e := range activity.To {
+ actor, err := activitypub.GetActorFromDB(e)
+ if err != nil {
+ return err
+ }
+
+ if actor.Id != "" && actor.Id != config.Domain {
+ if activity.Object.Replies != nil {
+ for _, k := range activity.Object.Replies.OrderedItems {
+ if err := activitypub.TombstoneObject(k.Id); err != nil {
+ return err
+ }
+ }
+ }
+
+ if err := activitypub.TombstoneObject(activity.Object.Id); err != nil {
+ return err
+ }
+ if err := db.UnArchiveLast(actor.Id); err != nil {
+ return err
+ }
+ break
+ }
+ }
+ break
+
+ case "Follow":
+ for _, e := range activity.To {
+ if res, err := activitypub.GetActorFromDB(e); err == nil && res.Id != "" {
+ response := db.AcceptFollow(activity)
+ response, err := activitypub.SetActorFollowerDB(response)
+ if err != nil {
+ return err
+ }
+
+ if err := db.MakeActivityRequest(response); err != nil {
+ return err
+ }
+
+ alreadyFollow := false
+ alreadyFollowing := false
+ autoSub, err := activitypub.GetActorAutoSubscribeDB(response.Actor.Id)
+ if err != nil {
+ return err
+ }
+
+ following, err := activitypub.GetActorFollowingDB(response.Actor.Id)
+ if err != nil {
+ return err
+ }
+
+ for _, e := range following {
+ if e.Id == response.Object.Id {
+ alreadyFollow = true
+ }
+ }
+
+ actor, err := webfinger.FingerActor(response.Object.Actor)
+ if err != nil {
+ return err
+ }
+
+ remoteActorFollowingCol, err := webfinger.GetCollectionFromReq(actor.Following)
+ if err != nil {
+ return err
+ }
+
+ for _, e := range remoteActorFollowingCol.Items {
+ if e.Id == response.Actor.Id {
+ alreadyFollowing = true
+ }
+ }
+
+ if autoSub && !alreadyFollow && alreadyFollowing {
+ followActivity, err := db.MakeFollowActivity(response.Actor.Id, response.Object.Actor)
+ if err != nil {
+ return err
+ }
+
+ if res, err := webfinger.FingerActor(response.Object.Actor); err == nil && res.Id != "" {
+ if err := db.MakeActivityRequestOutbox(followActivity); err != nil {
+ return err
+ }
+ } else if err != nil {
+ return err
+ }
+ }
+ } else if err != nil {
+ return err
+ } else {
+ fmt.Println("follow request for rejected")
+ response := activitypub.RejectActivity(activity)
- return c.SendString("actor inbox")
+ return db.MakeActivityRequest(response)
+ }
+ }
+ break
+
+ case "Reject":
+ if activity.Object.Object.Type == "Follow" {
+ fmt.Println("follow rejected")
+ if _, err := db.SetActorFollowingDB(activity); err != nil {
+ return err
+ }
+ }
+ break
+ }
+
+ return nil
}
func ActorOutbox(ctx *fiber.Ctx) error {
@@ -31,6 +197,11 @@ func ActorOutbox(ctx *fiber.Ctx) error {
return err
}
+ if activitypub.AcceptActivity(ctx.Get("Accept")) {
+ activitypub.GetActorOutbox(ctx, actor)
+ return nil
+ }
+
contentType := util.GetContentType(ctx.Get("content-type"))
if contentType == "multipart/form-data" || contentType == "application/x-www-form-urlencoded" {
diff --git a/util/proxy.go b/util/proxy.go
index 1fc9b03..0f4a648 100644
--- a/util/proxy.go
+++ b/util/proxy.go
@@ -37,3 +37,20 @@ func GetPathProxyType(path string) string {
return "clearnet"
}
+
+func MediaProxy(url string) string {
+ re := regexp.MustCompile("(.+)?" + config.Domain + "(.+)?")
+
+ if re.MatchString(url) {
+ return url
+ }
+
+ re = regexp.MustCompile("(.+)?\\.onion(.+)?")
+
+ if re.MatchString(url) {
+ return url
+ }
+
+ config.MediaHashs[HashMedia(url)] = url
+ return "/api/media?hash=" + HashMedia(url)
+}
diff --git a/webfinger/webfinger.go b/webfinger/webfinger.go
index a58c9ab..5b96d62 100644
--- a/webfinger/webfinger.go
+++ b/webfinger/webfinger.go
@@ -283,3 +283,28 @@ func AddInstanceToIndexDB(actor string) error {
return nil
}
+
+func MakeActivityFollowingReq(w http.ResponseWriter, r *http.Request, activity activitypub.Activity) (bool, error) {
+ actor, err := GetActor(activity.Object.Id)
+ if err != nil {
+ return false, err
+ }
+
+ req, err := http.NewRequest("POST", actor.Inbox, nil)
+ if err != nil {
+ return false, err
+ }
+
+ resp, err := util.RouteProxy(req)
+ if err != nil {
+ return false, err
+ }
+ defer resp.Body.Close()
+
+ body, _ := ioutil.ReadAll(resp.Body)
+
+ var respActivity activitypub.Activity
+
+ err = json.Unmarshal(body, &respActivity)
+ return respActivity.Type == "Accept", err
+}