aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFChannel <=>2021-01-19 16:41:31 -0800
committerFChannel <=>2021-01-19 16:41:31 -0800
commitcecfc9b08bbce20b14c367577ba728f27d51fb55 (patch)
tree97e1eacd16ac51c5f23419b30b61f37659b48576
parent328eff4285c94d3840659c04921d7c8048ea1f55 (diff)
cache system and follow/follower connections
-rw-r--r--CacheDatabase.go431
-rw-r--r--Database.go75
-rw-r--r--Follow.go168
-rw-r--r--OutboxPost.go124
-rw-r--r--databaseschema.psql72
-rw-r--r--main.go56
-rw-r--r--outboxGet.go9
7 files changed, 737 insertions, 198 deletions
diff --git a/CacheDatabase.go b/CacheDatabase.go
new file mode 100644
index 0000000..ebb84df
--- /dev/null
+++ b/CacheDatabase.go
@@ -0,0 +1,431 @@
+package main
+
+import "fmt"
+import "database/sql"
+import _ "github.com/lib/pq"
+
+func WriteObjectToCache(db *sql.DB, obj ObjectBase) ObjectBase {
+ if len(obj.Attachment) > 0 {
+ if obj.Preview.Href != "" {
+ WritePreviewToCache(db, *obj.Preview)
+ }
+
+ for i, _ := range obj.Attachment {
+ WriteAttachmentToCache(db, obj.Attachment[i])
+ WriteActivitytoCacheWithAttachment(db, obj, obj.Attachment[i], *obj.Preview)
+ }
+
+ } else {
+ WriteActivitytoCache(db, obj)
+ }
+
+ WriteObjectReplyToCache(db, obj)
+
+ return obj
+}
+
+func WriteActivitytoCache(db *sql.DB, obj ObjectBase) {
+
+ obj.Name = EscapeString(obj.Name)
+ obj.Content = EscapeString(obj.Content)
+ obj.AttributedTo = EscapeString(obj.AttributedTo)
+
+ query := `select id from cacheactivitystream where id=$1`
+
+ rows, err := db.Query(query, obj.Id)
+
+ CheckError(err, "error selecting obj id from cache")
+
+ var id string
+ defer rows.Close()
+ rows.Next()
+ rows.Scan(&id)
+
+ if id != "" {
+ return
+ }
+
+ query = `insert into cacheactivitystream (id, type, name, content, published, updated, attributedto, actor) values ($1, $2, $3, $4, $5, $6, $7, $8)`
+
+ _, e := db.Exec(query, obj.Id ,obj.Type, obj.Name, obj.Content, obj.Published, obj.Published, obj.AttributedTo, obj.Actor.Id)
+
+ if e != nil{
+ fmt.Println("error inserting new activity cache")
+ panic(e)
+ }
+}
+
+func WriteActivitytoCacheWithAttachment(db *sql.DB, obj ObjectBase, attachment ObjectBase, preview NestedObjectBase) {
+
+ obj.Name = EscapeString(obj.Name)
+ obj.Content = EscapeString(obj.Content)
+ obj.AttributedTo = EscapeString(obj.AttributedTo)
+
+ query := `select id from cacheactivitystream where id=$1`
+
+ rows, err := db.Query(query, obj.Id)
+
+ CheckError(err, "error selecting activity with attachment obj id cache")
+
+ var id string
+ defer rows.Close()
+ rows.Next()
+ rows.Scan(&id)
+
+ if id != "" {
+ return
+ }
+
+ query = `insert into cacheactivitystream (id, type, name, content, attachment, preview, published, updated, attributedto, actor) values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`
+
+ _, e := db.Exec(query, obj.Id ,obj.Type, obj.Name, obj.Content, attachment.Id, preview.Id, obj.Published, obj.Published, obj.AttributedTo, obj.Actor.Id)
+
+ if e != nil{
+ fmt.Println("error inserting new activity with attachment cache")
+ panic(e)
+ }
+}
+
+func WriteAttachmentToCache(db *sql.DB, obj ObjectBase) {
+
+ query := `select id from cacheactivitystream where id=$1`
+
+ rows, err := db.Query(query, obj.Id)
+
+ CheckError(err, "error selecting attachment obj id cache")
+
+ var id string
+ defer rows.Close()
+ rows.Next()
+ rows.Scan(&id)
+
+ if id != "" {
+ return
+ }
+
+ query = `insert into cacheactivitystream (id, type, name, href, published, updated, attributedTo, mediatype, size) values ($1, $2, $3, $4, $5, $6, $7, $8, $9)`
+
+ _, e := db.Exec(query, obj.Id ,obj.Type, obj.Name, obj.Href, obj.Published, obj.Published, obj.AttributedTo, obj.MediaType, obj.Size)
+
+ if e != nil{
+ fmt.Println("error inserting new attachment cache")
+ panic(e)
+ }
+}
+
+func WritePreviewToCache(db *sql.DB, obj NestedObjectBase) {
+
+ query := `select id from cacheactivitystream where id=$1`
+
+ rows, err := db.Query(query, obj.Id)
+
+ CheckError(err, "error selecting preview obj id cache")
+
+ var id string
+ defer rows.Close()
+ rows.Next()
+ rows.Scan(&id)
+
+ if id != "" {
+ return
+ }
+
+ query = `insert into cacheactivitystream (id, type, name, href, published, updated, attributedTo, mediatype, size) values ($1, $2, $3, $4, $5, $6, $7, $8, $9)`
+
+ _, e := db.Exec(query, obj.Id ,obj.Type, obj.Name, obj.Href, obj.Published, obj.Published, obj.AttributedTo, obj.MediaType, obj.Size)
+
+ if e != nil{
+ fmt.Println("error inserting new preview cache")
+ panic(e)
+ }
+}
+
+func GetObjectFromCache(db *sql.DB, id string) Collection {
+ var nColl Collection
+ var result []ObjectBase
+
+ query := `select id, name, content, type, published, updated, attributedto, attachment, preview, actor from cacheactivitystream where id=$1 and type='Note'`
+
+ rows, err := db.Query(query, id)
+
+ CheckError(err, "error query object from db cache")
+
+ defer rows.Close()
+ for rows.Next(){
+ var post ObjectBase
+ var actor Actor
+ var attachID string
+ var previewID string
+
+ err = rows.Scan(&post.Id, &post.Name, &post.Content, &post.Type, &post.Published, &post.Updated, &post.AttributedTo, &attachID, &previewID, &actor.Id)
+
+ CheckError(err, "error scan object into post struct cache")
+
+ post.Actor = &actor
+
+ var postCnt int
+ var imgCnt int
+ post.Replies, postCnt, imgCnt = GetObjectRepliesCache(db, post)
+
+ post.Replies.TotalItems, post.Replies.TotalImgs = GetObjectRepliesCacheCount(db, post)
+
+ post.Replies.TotalItems = post.Replies.TotalItems + postCnt
+ post.Replies.TotalImgs = post.Replies.TotalImgs + imgCnt
+
+ post.Attachment = GetObjectAttachmentCache(db, attachID)
+
+ post.Preview = GetObjectPreviewCache(db, previewID)
+
+ result = append(result, post)
+ }
+
+ nColl.OrderedItems = result
+
+ return nColl
+}
+
+func WriteObjectReplyToCache(db *sql.DB, obj ObjectBase) {
+ for i, e := range obj.InReplyTo {
+ if(i == 0 || IsReplyInThread(db, obj.InReplyTo[0].Id, e.Id)){
+
+ query := `select id from cachereplies where id=$1`
+
+ rows, err := db.Query(query, obj.Id)
+
+ CheckError(err, "error selecting obj id cache reply")
+
+ var id string
+ defer rows.Close()
+ rows.Next()
+ rows.Scan(&id)
+
+ if id != "" {
+ return
+ }
+
+ query = `insert into cachereplies (id, inreplyto) values ($1, $2)`
+
+ _, err = db.Exec(query, obj.Id, e.Id)
+
+ if err != nil{
+ fmt.Println("error inserting replies cache")
+ panic(err)
+ }
+ }
+ }
+}
+
+func GetObjectRepliesCache(db *sql.DB, parent ObjectBase) (*CollectionBase, int, int) {
+
+ var nColl CollectionBase
+ var result []ObjectBase
+
+ query := `select id, name, content, type, published, attributedto, attachment, preview, actor from cacheactivitystream WHERE id in (select id from cachereplies where inreplyto=$1) and type='Note' order by published asc`
+
+ rows, err := db.Query(query, parent.Id)
+
+ CheckError(err, "error with replies db query")
+
+ defer rows.Close()
+ for rows.Next() {
+ var post ObjectBase
+ var actor Actor
+ var attachID string
+ var previewID string
+
+ post.InReplyTo = append(post.InReplyTo, parent)
+
+ err = rows.Scan(&post.Id, &post.Name, &post.Content, &post.Type, &post.Published, &post.AttributedTo, &attachID, &previewID, &actor.Id)
+
+
+ CheckError(err, "error with replies db scan")
+
+ post.Actor = &actor
+
+ var postCnt int
+ var imgCnt int
+ post.Replies, postCnt, imgCnt = GetObjectRepliesRepliesCache(db, post)
+
+ post.Replies.TotalItems, post.Replies.TotalImgs = GetObjectRepliesCacheCount(db, post)
+
+ post.Replies.TotalItems = post.Replies.TotalItems + postCnt
+ post.Replies.TotalImgs = post.Replies.TotalImgs + imgCnt
+
+ post.Attachment = GetObjectAttachmentCache(db, attachID)
+
+ post.Preview = GetObjectPreviewCache(db, previewID)
+
+ result = append(result, post)
+ }
+
+ nColl.OrderedItems = result
+
+ remoteCollection := GetObjectRepliesRemote(db, parent)
+
+ var postc int
+ var imgc int
+ for _, e := range remoteCollection.OrderedItems {
+ nColl.OrderedItems = append(nColl.OrderedItems, e)
+ postc = postc + 1
+ if len(e.Attachment) > 0 {
+ imgc = imgc + 1
+ }
+ }
+
+ return &nColl, postc, imgc
+}
+
+func GetObjectRepliesRepliesCache(db *sql.DB, parent ObjectBase) (*CollectionBase, int, int) {
+
+ var nColl CollectionBase
+ var result []ObjectBase
+
+ query := `select id, name, content, type, published, attributedto, attachment, preview, actor from cacheactivitystream where id in (select id from cachereplies where inreplyto=$1) and type='Note' order by published asc`
+
+ rows, err := db.Query(query, parent.Id)
+
+ CheckError(err, "error with replies replies cache query")
+
+ defer rows.Close()
+ for rows.Next() {
+ var post ObjectBase
+ var actor Actor
+ var attachID string
+ var previewID string
+
+ post.InReplyTo = append(post.InReplyTo, parent)
+
+ err = rows.Scan(&post.Id, &post.Name, &post.Content, &post.Type, &post.Published, &post.AttributedTo, &attachID, &previewID, &actor.Id)
+
+
+ CheckError(err, "error with replies replies cache scan")
+
+ post.Actor = &actor
+
+ post.Attachment = GetObjectAttachmentCache(db, attachID)
+
+ post.Preview = GetObjectPreviewCache(db, previewID)
+
+ result = append(result, post)
+ }
+
+ remoteCollection := GetObjectRepliesRemote(db, parent)
+
+ var postc int
+ var imgc int
+ for _, e := range remoteCollection.OrderedItems {
+
+ nColl.OrderedItems = append(nColl.OrderedItems, e)
+ postc = postc + 1
+ if len(e.Attachment) > 0 {
+ imgc = imgc + 1
+ }
+ }
+
+ nColl.OrderedItems = result
+
+ return &nColl, postc, imgc
+}
+
+func GetObjectRepliesCacheCount(db *sql.DB, parent ObjectBase) (int, int) {
+
+ var countId int
+ var countImg int
+
+ query := `select count(id) from replies where inreplyto=$1 and id in (select id from activitystream where type='Note')`
+
+ rows, err := db.Query(query, parent.Id)
+
+ CheckError(err, "error with replies count db query")
+
+ defer rows.Close()
+ rows.Next()
+ rows.Scan(&countId)
+
+ query = `select count(attachment) from activitystream where id in (select id from replies where inreplyto=$1) and attachment != ''`
+
+ rows, err = db.Query(query, parent.Id)
+
+ CheckError(err, "error with select attachment count db query")
+
+ defer rows.Close()
+ rows.Next()
+ rows.Scan(&countImg)
+
+ return countId, countImg
+}
+
+func GetObjectAttachmentCache(db *sql.DB, id string) []ObjectBase {
+
+ var attachments []ObjectBase
+
+ query := `select id, type, name, href, mediatype, size, published from cacheactivitystream where id=$1`
+
+ rows, err := db.Query(query, id)
+
+ CheckError(err, "could not select object attachment query")
+
+ defer rows.Close()
+ for rows.Next() {
+ var attachment = new(ObjectBase)
+
+ err = rows.Scan(&attachment.Id, &attachment.Type, &attachment.Name, &attachment.Href, &attachment.MediaType, &attachment.Size, &attachment.Published)
+ if err !=nil{
+ fmt.Println("error with attachment db query")
+ panic(err)
+ }
+
+ attachments = append(attachments, *attachment)
+ }
+
+ return attachments
+}
+
+func GetObjectPreviewCache(db *sql.DB, id string) *NestedObjectBase {
+
+ var preview NestedObjectBase
+
+ query := `select id, type, name, href, mediatype, size, published from cacheactivitystream where id=$1`
+
+ rows, err := db.Query(query, id)
+
+ CheckError(err, "could not select object preview query")
+
+ defer rows.Close()
+ for rows.Next() {
+ err = rows.Scan(&preview.Id, &preview.Type, &preview.Name, &preview.Href, &preview.MediaType, &preview.Size, &preview.Published)
+ }
+
+ return &preview
+}
+
+func DeleteObjectFromCache(db *sql.DB, id string) {
+ query := `select attachment, preview from cacheactivitystream where id=$1 `
+
+ rows, err := db.Query(query, id)
+ CheckError(err, "could not select cache activitystream")
+
+ var attachment string
+ var preview string
+
+ defer rows.Close()
+ rows.Next()
+ rows.Scan(&attachment, &preview)
+
+ query = `delete from cacheactivitystream where id=$1`
+ _, err = db.Exec(query, attachment)
+ CheckError(err, "could not delete attachmet cache activitystream")
+
+ query = `delete from cacheactivitystream where id=$1`
+ _, err = db.Exec(query, preview)
+ CheckError(err, "could not delete preview cache activitystream")
+
+ query = `delete from cacheactivitystream where id=$1`
+ _, err = db.Exec(query, id)
+ CheckError(err, "could not delete object cache activitystream")
+
+ query = `delete from cachereplies where id=$1`
+ _, err = db.Exec(query, id)
+ CheckError(err, "could not delete cache replies activitystream")
+}
+
diff --git a/Database.go b/Database.go
index bf6ff82..3b4dfc4 100644
--- a/Database.go
+++ b/Database.go
@@ -72,17 +72,23 @@ func CreateNewBoardDB(db *sql.DB, actor Actor) Actor{
CreateBoardMod(db, nverify)
if actor.Name != "main" {
- var nActivity Activity
var nActor Actor
var nObject ObjectBase
+ var nActivity Activity
- nActor.Id = Domain
- nObject.Id = actor.Id
-
+ nActivity.AtContext.Context = "https://www.w3.org/ns/activitystreams"
+ nActivity.Type = "Follow"
nActivity.Actor = &nActor
nActivity.Object = &nObject
-
- SetActorFollowDB(db, nActivity, Domain)
+ nActivity.Actor.Id = Domain
+ var mActor Actor
+ nActivity.Object.Actor = &mActor
+ nActivity.Object.Actor.Id = actor.Id
+ nActivity.To = append(nActivity.To, actor.Id)
+
+ response := AcceptFollow(nActivity)
+ SetActorFollowingDB(db, response)
+ MakeActivityRequest(nActivity)
}
}
@@ -466,10 +472,17 @@ func GetObjectRepliesRemote(db *sql.DB, parent ObjectBase) CollectionBase {
for rows.Next() {
var id string
rows.Scan(&id)
-
- coll := GetCollectionFromID(id)
- for _, e := range coll.OrderedItems {
+ cacheColl := GetObjectFromCache(db, id)
+
+ if len(cacheColl.OrderedItems) < 1 {
+ cacheColl = GetCollectionFromID(id)
+ for _, e := range cacheColl.OrderedItems {
+ WriteObjectToCache(db, e)
+ }
+ }
+
+ for _, e := range cacheColl.OrderedItems {
result = append(result, e)
}
}
@@ -559,42 +572,6 @@ func GetObjectRepliesDBCount(db *sql.DB, parent ObjectBase) (int, int) {
return countId, countImg
}
-func GetObjectRepliesRemoteCount(db *sql.DB, parent ObjectBase) (int, int) {
- var nColl CollectionBase
- var result []ObjectBase
- query := `select id from replies where id not in (select id from activitystream) and inreplyto=$1`
-
- rows, err := db.Query(query, parent.Id)
-
- CheckError(err, "could not get remote id query")
-
- defer rows.Close()
- for rows.Next() {
- var id string
- rows.Scan(&id)
-
- coll := GetCollectionFromID(id)
-
- for _, e := range coll.OrderedItems {
- result = append(result, e)
- }
- }
-
- nColl.OrderedItems = result
-
- var posts int
- var imgs int
-
- for _, e := range nColl.OrderedItems {
- posts = posts + 1
- if len(e.Attachment) > 0 {
- imgs = imgs + 1
- }
- }
-
- return posts, imgs
-}
-
func GetObjectAttachment(db *sql.DB, id string) []ObjectBase {
var attachments []ObjectBase
@@ -692,9 +669,7 @@ func DeletePreviewFromFile(db *sql.DB, id string) {
var href string
var _type string
err := rows.Scan(&href, &_type)
- fmt.Println(href)
href = strings.Replace(href, Domain + "/", "", 1)
- fmt.Println(href)
CheckError(err, "error scanning delete attachment")
if _type != "Tombstone" {
@@ -852,6 +827,7 @@ func DeleteObject(db *sql.DB, id string) {
DeleteAttachmentFromFile(db, id)
DeletePreviewFromFile(db, id)
DeleteObjectFromDB(db, id)
+ DeleteObjectRequest(db, id)
}
func DeleteObjectAndReplies(db *sql.DB, id string) {
@@ -866,7 +842,8 @@ func DeleteObjectAndReplies(db *sql.DB, id string) {
DeleteObjectRepliesFromDB(db, id)
DeleteAttachmentRepliesFromDB(db, id)
DeletePreviewRepliesFromDB(db, id)
- DeleteObjectFromDB(db, id)
+ DeleteObjectFromDB(db, id)
+ DeleteObjectAndRepliesRequest(db, id)
}
func GetRandomCaptcha(db *sql.DB) string{
@@ -1007,3 +984,5 @@ func GetActorReportedDB(db *sql.DB, id string) []ObjectBase {
return nObj
}
+
+
diff --git a/Follow.go b/Follow.go
index 8fc6200..dd5a321 100644
--- a/Follow.go
+++ b/Follow.go
@@ -11,7 +11,7 @@ func GetActorFollowing(w http.ResponseWriter, db *sql.DB, id string) {
following.AtContext.Context = "https://www.w3.org/ns/activitystreams"
following.Type = "Collection"
following.TotalItems, _ = GetActorFollowTotal(db, id)
- following.Items, _ = GetActorFollowDB(db, id)
+ following.Items = GetActorFollowingDB(db, id)
enc, _ := json.MarshalIndent(following, "", "\t")
w.Header().Set("Content-Type", "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"")
@@ -24,57 +24,16 @@ func GetActorFollowers(w http.ResponseWriter, db *sql.DB, id string) {
following.AtContext.Context = "https://www.w3.org/ns/activitystreams"
following.Type = "Collection"
_, following.TotalItems = GetActorFollowTotal(db, id)
- _, following.Items = GetActorFollowDB(db, id)
+ following.Items = GetActorFollowDB(db, id)
enc, _ := json.MarshalIndent(following, "", "\t")
w.Header().Set("Content-Type", "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"")
w.Write(enc)
}
-func SetActorFollowDB(db *sql.DB, activity Activity, actor string) Activity {
- var query string
- alreadyFollow := false
- following, follower := GetActorFollowDB(db, actor)
-
- if activity.Actor.Id == actor {
- for _, e := range following {
- if e.Id == activity.Object.Id {
- alreadyFollow = true
- }
- }
- if alreadyFollow {
- query = `delete from following where id=$1 and following=$2`
- activity.Summary = activity.Actor.Id + " Unfollow " + activity.Object.Id
- } else {
- query = `insert into following (id, following) values ($1, $2)`
- activity.Summary = activity.Actor.Id + " Follow " + activity.Object.Id
- }
- } else {
- for _, e := range follower {
- if e.Id == activity.Actor.Id {
- alreadyFollow = true
- }
- }
- if alreadyFollow {
- query = `delete from follower where id=$1 and follower=$2`
- activity.Summary = activity.Actor.Id + " Unfollow " + activity.Object.Id
- } else {
- query = `insert into follower (id, follower) values ($1, $2)`
- activity.Summary = activity.Actor.Id + " Follow " + activity.Object.Id
- }
- }
-
- _, err := db.Exec(query, activity.Actor.Id, activity.Object.Id)
- CheckError(err, "error with follow db insert/delete")
-
- return activity
-}
-
-func GetActorFollowDB(db *sql.DB, id string) ([]ObjectBase, []ObjectBase) {
+func GetActorFollowingDB(db *sql.DB, id string) []ObjectBase {
var followingCollection []ObjectBase
- var followerCollection []ObjectBase
-
query := `select following from following where id=$1`
rows, err := db.Query(query, id)
@@ -93,11 +52,17 @@ func GetActorFollowDB(db *sql.DB, id string) ([]ObjectBase, []ObjectBase) {
followingCollection = append(followingCollection, obj)
}
- query = `select follower from follower where id=$1`
+ return followingCollection
+}
- rows, err = db.Query(query, id)
+func GetActorFollowDB(db *sql.DB, id string) []ObjectBase {
+ var followerCollection []ObjectBase
- CheckError(err, "error with followers db query")
+ query := `select follower from follower where id=$1`
+
+ rows, err := db.Query(query, id)
+
+ CheckError(err, "error with follower db query")
defer rows.Close()
@@ -111,7 +76,7 @@ func GetActorFollowDB(db *sql.DB, id string) ([]ObjectBase, []ObjectBase) {
followerCollection = append(followerCollection, obj)
}
- return followingCollection, followerCollection
+ return followerCollection
}
func GetActorFollowTotal(db *sql.DB, id string) (int, int) {
@@ -149,69 +114,100 @@ func GetActorFollowTotal(db *sql.DB, id string) (int, int) {
return following, followers
}
-func AcceptFollow(activity Activity, actor Actor) Activity {
+func AcceptFollow(activity Activity) Activity {
var accept Activity
- var obj ObjectBase
-
- obj.Type = activity.Type
- obj.Actor = activity.Actor
-
- var nobj NestedObjectBase
- obj.Object = &nobj
- obj.Object.Id = activity.Object.Id
-
accept.AtContext.Context = activity.AtContext.Context
accept.Type = "Accept"
-
- var nactor Actor
- accept.Actor = &nactor
- accept.Actor.Id = actor.Id
- accept.Object = &obj
- accept.To = append(accept.To, activity.Object.Id)
+ accept.Actor = activity.Object.Actor
+ var nObj ObjectBase
+ var nActor Actor
+ accept.Object = &nObj
+ accept.Object.Actor = &nActor
+ accept.Object.Actor = activity.Actor
+ var nNested NestedObjectBase
+ var mActor Actor
+ accept.Object.Object = &nNested
+ accept.Object.Object.Actor = &mActor
+ accept.Object.Object.Actor = activity.Object.Actor
+ accept.Object.Object.Type = "Follow"
+ accept.To = append(accept.To, activity.Object.Actor.Id)
return accept
}
-func RejectFollow(activity Activity, actor Actor) Activity {
+func RejectFollow(activity Activity) Activity {
var accept Activity
- var obj ObjectBase
-
- obj.Type = activity.Type
- obj.Actor = activity.Actor
- obj.Object = new(NestedObjectBase)
- obj.Object.Id = activity.Object.Id
-
accept.AtContext.Context = activity.AtContext.Context
accept.Type = "Reject"
- accept.Actor = &actor
- accept.Object = &obj
+ var nObj ObjectBase
+ var nActor Actor
+ accept.Object = &nObj
+ accept.Object.Actor = &nActor
+ accept.Actor = activity.Object.Actor
+ accept.Object.Actor = activity.Actor
+ var nNested NestedObjectBase
+ var mActor Actor
+ accept.Object.Object = &nNested
+ accept.Object.Object.Actor = &mActor
+ accept.Object.Object.Actor = activity.Object.Actor
+ accept.Object.Object.Type = "Follow"
+ accept.To = append(accept.To, activity.Actor.Id)
+
+ return accept
+}
- return accept
+func SetActorFollowerDB(db *sql.DB, activity Activity) Activity {
+ var query string
+ alreadyFollow := false
+ followers := GetActorFollowDB(db, activity.Actor.Id)
+
+ for _, e := range followers {
+ if e.Id == activity.Object.Actor.Id {
+ alreadyFollow = true
+ }
+ }
+ if alreadyFollow {
+ query = `delete from follower where id=$1 and follower=$2`
+ activity.Summary = activity.Object.Actor.Id + " Unfollow " + activity.Actor.Id
+ } else {
+ query = `insert into follower (id, follower) values ($1, $2)`
+ activity.Summary = activity.Object.Actor.Id + " Follow " + activity.Actor.Id
+ }
+
+ _, err := db.Exec(query, activity.Actor.Id, activity.Object.Actor.Id)
+
+ if CheckError(err, "error with follower db insert/delete") != nil {
+ activity.Type = "Reject"
+ return activity
+ }
+
+ activity.Type = "Accept"
+ return activity
}
-func SetActorFollowingDB(db *sql.DB, activity Activity) Activity{
+func SetActorFollowingDB(db *sql.DB, activity Activity) Activity {
var query string
alreadyFollow := false
- _, follower := GetActorFollowDB(db, activity.Object.Id)
+ following := GetActorFollowingDB(db, activity.Object.Actor.Id)
- for _, e := range follower {
- if e.Id == activity.Object.Id {
+
+ for _, e := range following {
+ if e.Id == activity.Actor.Id {
alreadyFollow = true
}
}
if alreadyFollow {
- query = `delete from follower where id=$1 and follower=$2`
- activity.Summary = activity.Actor.Id + " Unfollow " + activity.Object.Id
+ query = `delete from following where id=$1 and following=$2`
+ activity.Summary = activity.Object.Actor.Id + " Unfollowing " + activity.Actor.Id
} else {
- query = `insert into follower (id, follower) values ($1, $2)`
- activity.Summary = activity.Actor.Id + " Follow " + activity.Object.Id
+ query = `insert into following (id, following) values ($1, $2)`
+ activity.Summary = activity.Object.Actor.Id + " Following " + activity.Actor.Id
}
- _, err := db.Exec(query, activity.Object.Id, activity.Actor.Id)
+ _, err := db.Exec(query, activity.Object.Actor.Id, activity.Actor.Id)
- if err != nil {
- CheckError(err, "error with follow db insert/delete")
+ if CheckError(err, "error with following db insert/delete") != nil {
activity.Type = "Reject"
return activity
}
diff --git a/OutboxPost.go b/OutboxPost.go
index dacf77e..84810c9 100644
--- a/OutboxPost.go
+++ b/OutboxPost.go
@@ -38,36 +38,18 @@ func ParseOutboxRequest(w http.ResponseWriter, r *http.Request, db *sql.DB) {
w.Write([]byte("file type not supported"))
return
}
-
}
var nObj = CreateObject("Note")
nObj = ObjectFromForm(r, db, nObj)
-
+
var act Actor
nObj.Actor = &act
nObj.Actor.Id = Domain + "/" + actor.Name
- delete := regexp.MustCompile("delete:.+")
- for _, e := range nObj.Option {
- if delete.MatchString(e) {
- verification := strings.Replace(e, "delete:", "", 1)
- if HasAuth(db, verification, Domain + "/" + actor.Name) {
- for _, e := range nObj.InReplyTo {
- if IsObjectLocal(db, e.Id) && e.Id != nObj.InReplyTo[len(nObj.InReplyTo) - 1].Id {
- DeleteObject(db, e.Id)
- nObj.Type = "Delete"
- }
- }
- }
- }
- }
-
- if nObj.Type != "Delete" {
- nObj = writeObjectToDB(db, nObj)
- activity := CreateActivity("Create", nObj)
- MakeActivityRequest(activity)
- }
+ nObj = writeObjectToDB(db, nObj)
+ activity := CreateActivity("Create", nObj)
+ MakeActivityRequest(activity)
var id string
re := regexp.MustCompile("\\w+$")
@@ -82,9 +64,14 @@ func ParseOutboxRequest(w http.ResponseWriter, r *http.Request, db *sql.DB) {
w.WriteHeader(http.StatusOK)
w.Write([]byte(id))
+ return
}
+
+ w.WriteHeader(http.StatusForbidden)
+ w.Write([]byte("could not authenticate"))
} else {
activity = GetActivityFromJson(r, db)
+
if IsActivityLocal(db, activity) {
switch activity.Type {
case "Create":
@@ -102,46 +89,56 @@ func ParseOutboxRequest(w http.ResponseWriter, r *http.Request, db *sql.DB) {
var validActor bool
var validLocalActor bool
- _, validActor = IsValidActor(activity.Object.Id)
- validLocalActor = (activity.Actor.Id == actor.Id) || (activity.Object.Id == actor.Id)
- verification := GetVerificationByCode(db, activity.Auth)
+ header := r.Header.Get("Authorization")
- var rActivity Activity
- fmt.Println("ok")
- if validActor && validLocalActor && verification.Board == activity.Actor.Id || verification.Board == Domain {
- fmt.Println("yes")
- rActivity = AcceptFollow(activity, actor)
- } else {
- fmt.Println("no")
- rActivity = RejectFollow(activity, actor)
- rActivity.Summary = "No valid actor or Actor is not located here"
- }
+ auth := strings.Split(header, " ")
- if rActivity.Type == "Accept" {
- rActivity.Summary = SetActorFollowDB(db, activity, actor.Id).Summary
+ if len(auth) < 2 {
+ w.WriteHeader(http.StatusBadRequest)
+ w.Write([]byte(""))
+ return
}
+
+ _, validActor = IsValidActor(activity.Object.Actor.Id)
+ validLocalActor = (activity.Actor.Id == actor.Id)
+ verification := GetVerificationByCode(db, auth[1])
- enc, _ := json.MarshalIndent(rActivity, "", "\t")
-
- if rActivity.Type == "Reject" {
- w.WriteHeader(http.StatusBadRequest)
+ var rActivity Activity
+ if validActor && validLocalActor && verification.Board == activity.Actor.Id || verification.Board == Domain {
+ rActivity = AcceptFollow(activity)
+ SetActorFollowingDB(db, rActivity)
+ MakeActivityRequest(activity)
}
-
- w.Header().Set("Content-Type", "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"")
- w.Write(enc)
-
+ w.Write([]byte(""))
case "Delete":
fmt.Println("This is a delete")
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("could not process activity"))
case "Note":
- fmt.Println("This is a note")
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("could not process activity"))
case "New":
- fmt.Println("Added new Board")
+
+ header := r.Header.Get("Authorization")
+
+ auth := strings.Split(header, " ")
+
+ if len(auth) < 2 {
+ w.WriteHeader(http.StatusBadRequest)
+ w.Write([]byte(""))
+ return
+ }
+
+ verification := GetVerificationByCode(db, auth[1])
+
+ if verification.Board != Domain {
+ w.WriteHeader(http.StatusBadRequest)
+ w.Write([]byte(""))
+ return
+ }
+
name := activity.Object.Actor.Name
prefname := activity.Object.Actor.PreferredUsername
summary := activity.Object.Actor.Summary
@@ -163,6 +160,7 @@ func ParseOutboxRequest(w http.ResponseWriter, r *http.Request, db *sql.DB) {
w.Write([]byte("could not process activity"))
}
} else {
+
fmt.Println("is NOT activity")
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("could not process activity"))
@@ -319,7 +317,7 @@ func HasContextFromJson(context []byte) bool {
err = json.Unmarshal(context, &arrContext.Context)
CheckError(err, "error with string")
if arrContext.Context == "https://www.w3.org/ns/activitystreams" {
- hasContext = true
+ hasContext = true
}
}
@@ -517,15 +515,37 @@ func ParseInboxRequest(w http.ResponseWriter, r *http.Request, db *sql.DB) {
}
break
+ case "Delete":
+ for _, e := range activity.To {
+ actor := GetActorFromDB(db, e)
+ if actor.Id != "" {
+ DeleteObjectFromCache(db, activity.Object.Id)
+ return
+ }
+ }
+ break
+
+
case "Follow":
for _, e := range activity.To {
- if IsObjectLocal(db, e) {
- nActivity := SetActorFollowingDB(db, activity)
- j, _ := json.Marshal(&nActivity)
- w.Write([]byte(j))
+ if GetActorFromDB(db, e).Id != "" {
+ response := AcceptFollow(activity)
+ response = SetActorFollowerDB(db, response)
+ MakeActivityRequest(response)
+ } else {
+ fmt.Println("follow request for rejected")
+ response := RejectFollow(activity)
+ MakeActivityRequest(response)
}
}
break
+
+ case "Reject":
+ if activity.Object.Object.Type == "Follow" {
+ fmt.Println("follow rejected")
+ SetActorFollowingDB(db, activity)
+ }
+ break
}
}
diff --git a/databaseschema.psql b/databaseschema.psql
index e4c3fe1..d2544cc 100644
--- a/databaseschema.psql
+++ b/databaseschema.psql
@@ -132,4 +132,76 @@ formerType varchar(100) default '',
size int default NULL,
public boolean default false,
CONSTRAINT fk_object FOREIGN KEY (object) REFERENCES activitystream(id)
+);
+
+CREATE TABLE IF NOT EXISTS cachereplies(
+id varchar(100),
+inreplyto varchar(100)
+);
+
+CREATE TABLE IF NOT EXISTS cacheactivitystream(
+actor varchar(100) default '',
+attachment varchar(100) default '',
+attributedTo varchar(100) default '',
+audience varchar(100) default '',
+bcc varchar(100) default '',
+bto varchar(100) default '',
+cc varchar(100) default '',
+context varchar(100) default '',
+current varchar(100) default '',
+first varchar(100) default '',
+generator varchar(100) default '',
+icon varchar(100) default '',
+id varchar(100) UNIQUE PRIMARY KEY,
+image varchar(100) default '',
+instrument varchar(100) default '',
+last varchar(100) default '',
+location varchar(100) default '',
+items varchar(100) default '',
+oneOf varchar(100) default '',
+anyOf varchar(100) default '',
+closed varchar(100) default '',
+origin varchar(100) default '',
+next varchar(100) default '',
+object varchar(100),
+prev varchar(100) default '',
+preview varchar(100) default '',
+result varchar(100) default '',
+tag varchar(100) default '',
+target varchar(100) default '',
+type varchar(100) default '',
+to_ varchar(100) default '',
+url varchar(100) default '',
+accuracy varchar(100) default '',
+altitude varchar(100) default '',
+content varchar(2000) default '',
+name varchar(100) default '',
+alias varchar(100) default '',
+duration varchar(100) default '',
+height varchar(100) default '',
+href varchar(100) default '',
+hreflang varchar(100) default '',
+partOf varchar(100) default '',
+latitude varchar(100) default '',
+longitude varchar(100) default '',
+mediaType varchar(100) default '',
+endTime varchar(100) default '',
+published TIMESTAMP default NOW(),
+startTime varchar(100) default '',
+radius varchar(100) default '',
+rel varchar(100) default '',
+startIndex varchar(100) default '',
+summary varchar(100) default '',
+totalItems varchar(100) default '',
+units varchar(100) default '',
+updated TIMESTAMP default NOW(),
+deleted TIMESTAMP default NULL,
+width varchar(100) default '',
+subject varchar(100) default '',
+relationship varchar(100) default '',
+describes varchar(100) default '',
+formerType varchar(100) default '',
+size int default NULL,
+public boolean default false,
+CONSTRAINT fk_object FOREIGN KEY (object) REFERENCES cacheactivitystream(id)
); \ No newline at end of file
diff --git a/main.go b/main.go
index bf714e8..e7af54b 100644
--- a/main.go
+++ b/main.go
@@ -701,7 +701,7 @@ func CheckValidActivity(id string) (Collection, bool) {
func GetActor(id string) Actor {
- var respActor Actor
+ var respActor Actor
req, err := http.NewRequest("GET", id, nil)
@@ -747,7 +747,6 @@ func GetActorCollection(collection string) Collection {
return nCollection
}
-
func IsValidActor(id string) (Actor, bool) {
var respCollection Actor
req, err := http.NewRequest("GET", id, nil)
@@ -969,7 +968,7 @@ func MakeActivityRequest(activity Activity) {
j, _ := json.MarshalIndent(activity, "", "\t")
for _, e := range activity.To {
actor := GetActor(e)
-
+
req, err := http.NewRequest("POST", actor.Inbox, bytes.NewBuffer(j))
CheckError(err, "error with sending activity req to")
@@ -994,13 +993,16 @@ func GetCollectionFromID(id string) Collection {
return nColl
}
- defer resp.Body.Close()
-
- body, _ := ioutil.ReadAll(resp.Body)
+ if resp.StatusCode == 200 {
+ defer resp.Body.Close()
+
+ body, _ := ioutil.ReadAll(resp.Body)
- err = json.Unmarshal(body, &nColl)
+ err = json.Unmarshal(body, &nColl)
- CheckError(err, "error getting collection resp from json body")
+ CheckError(err, "error getting collection resp from json body")
+
+ }
return nColl
}
@@ -1088,3 +1090,41 @@ func GetUniqueFilename(_type string) string {
return ""
}
+
+func DeleteObjectRequest(db *sql.DB, id string) {
+ var nObj ObjectBase
+ nObj.Id = id
+
+ activity := CreateActivity("Delete", nObj)
+
+ obj := GetObjectFromPath(db, id)
+ followers := GetActorFollowDB(db, obj.Actor.Id)
+ for _, e := range followers {
+ activity.To = append(activity.To, e.Id)
+ }
+
+ following := GetActorFollowingDB(db, obj.Actor.Id)
+ for _, e := range following {
+ activity.To = append(activity.To, e.Id)
+ }
+
+ MakeActivityRequest(activity)
+}
+
+func DeleteObjectAndRepliesRequest(db *sql.DB, id string) {
+ var nObj ObjectBase
+ nObj.Id = id
+
+ activity := CreateActivity("Delete", nObj)
+
+ obj := GetObjectFromPath(db, id)
+
+ followers := GetActorFollowDB(db, obj.Actor.Id)
+ for _, e := range followers {
+ activity.To = append(activity.To, e.Id)
+ }
+
+ MakeActivityRequest(activity)
+}
+
+
diff --git a/outboxGet.go b/outboxGet.go
index 1065ad9..7aaf70f 100644
--- a/outboxGet.go
+++ b/outboxGet.go
@@ -23,8 +23,6 @@ func GetActorOutbox(w http.ResponseWriter, r *http.Request, db *sql.DB) {
w.Write(enc)
}
-
-
func GetObjectsFromFollow(actor Actor) []ObjectBase {
var followingCol Collection
var followObj []ObjectBase
@@ -107,9 +105,12 @@ func GetObjectFromPath(db *sql.DB, path string) ObjectBase{
for rows.Next(){
var post ObjectBase
var attachID string
- var previewID string
+ var previewID string
+
+ var nActor Actor
+ post.Actor = &nActor
- err = rows.Scan(&post.Id, &post.Name, &post.Content, &post.Type, &post.Published, &post.AttributedTo, &attachID, &previewID, &post.Actor)
+ err = rows.Scan(&post.Id, &post.Name, &post.Content, &post.Type, &post.Published, &post.AttributedTo, &attachID, &previewID, &post.Actor.Id)
CheckError(err, "error scan object into post struct from path")