@ -1,5 +1,5 @@
/ *
* Copyright © 2018 - 2019 A Bunch Tell LLC .
* Copyright © 2018 - 2020 A Bunch Tell LLC .
*
* This file is part of WriteFreely .
*
@ -46,6 +46,7 @@ type RemoteUser struct {
ActorID string
Inbox string
SharedInbox string
Handle string
}
func ( ru * RemoteUser ) AsPerson ( ) * activitystreams . Person {
@ -151,7 +152,7 @@ func handleFetchCollectionOutbox(app *App, w http.ResponseWriter, r *http.Reques
posts , err := app . db . GetPosts ( app . cfg , c , p , false , true , false )
for _ , pp := range * posts {
pp . Collection = res
o := pp . ActivityObject ( app . cfg )
o := pp . ActivityObject ( app )
a := activitystreams . NewCreateActivity ( o )
ocp . OrderedItems = append ( ocp . OrderedItems , * a )
}
@ -570,7 +571,7 @@ func deleteFederatedPost(app *App, p *PublicPost, collID int64) error {
}
p . Collection . hostName = app . cfg . App . Host
actor := p . Collection . PersonObject ( collID )
na := p . ActivityObject ( app . cfg )
na := p . ActivityObject ( app )
// Add followers
p . Collection . ID = collID
@ -616,7 +617,7 @@ func federatePost(app *App, p *PublicPost, collID int64, isUpdate bool) error {
}
}
actor := p . Collection . PersonObject ( collID )
na := p . ActivityObject ( app . cfg )
na := p . ActivityObject ( app )
// Add followers
p . Collection . ID = collID
@ -634,18 +635,25 @@ func federatePost(app *App, p *PublicPost, collID int64, isUpdate bool) error {
inbox = f . Inbox
}
if _ , ok := inboxes [ inbox ] ; ok {
// check if we're already sending to this shared inbox
inboxes [ inbox ] = append ( inboxes [ inbox ] , f . ActorID )
} else {
// add the new shared inbox to the list
inboxes [ inbox ] = [ ] string { f . ActorID }
}
}
var activity * activitystreams . Activity
// for each one of the shared inboxes
for si , instFolls := range inboxes {
// add all followers from that instance
// to the CC field
na . CC = [ ] string { }
for _ , f := range instFolls {
na . CC = append ( na . CC , f )
}
var activity * activitystreams . Activity
// create a new "Create" activity
// with our article as object
if isUpdate {
activity = activitystreams . NewUpdateActivity ( na )
} else {
@ -653,17 +661,42 @@ func federatePost(app *App, p *PublicPost, collID int64, isUpdate bool) error {
activity . To = na . To
activity . CC = na . CC
}
// and post it to that sharedInbox
err = makeActivityPost ( app . cfg . App . Host , actor , si , activity )
if err != nil {
log . Error ( "Couldn't post! %v" , err )
}
}
// re-create the object so that the CC list gets reset and has
// the mentioned users. This might seem wasteful but the code is
// cleaner than adding the mentioned users to CC here instead of
// in p.ActivityObject()
na = p . ActivityObject ( app )
for _ , tag := range na . Tag {
if tag . Type == "Mention" {
activity = activitystreams . NewCreateActivity ( na )
activity . To = na . To
activity . CC = na . CC
// This here might be redundant in some cases as we might have already
// sent this to the sharedInbox of this instance above, but we need too
// much logic to catch this at the expense of the odd extra request.
// I don't believe we'd ever have too many mentions in a single post that this
// could become a burden.
remoteUser , err := getRemoteUser ( app , tag . HRef )
err = makeActivityPost ( app . cfg . App . Host , actor , remoteUser . Inbox , activity )
if err != nil {
log . Error ( "Couldn't post! %v" , err )
}
}
}
return nil
}
func getRemoteUser ( app * App , actorID string ) ( * RemoteUser , error ) {
u := RemoteUser { ActorID : actorID }
err := app . db . QueryRow ( "SELECT id, inbox, shared_inbox FROM remoteusers WHERE actor_id = ?" , actorID ) . Scan ( & u . ID , & u . Inbox , & u . SharedInbox )
err := app . db . QueryRow ( "SELECT id, inbox, shared_inbox, handle FROM remoteusers WHERE actor_id = ?" , actorID ) . Scan ( & u . ID , & u . Inbox , & u . SharedInbox , & u . Handle )
switch {
case err == sql . ErrNoRows :
return nil , impart . HTTPError { http . StatusNotFound , "No remote user with that ID." }
@ -675,6 +708,21 @@ func getRemoteUser(app *App, actorID string) (*RemoteUser, error) {
return & u , nil
}
// getRemoteUserFromHandle retrieves the profile page of a remote user
// from the @user@server.tld handle
func getRemoteUserFromHandle ( app * App , handle string ) ( * RemoteUser , error ) {
u := RemoteUser { Handle : handle }
err := app . db . QueryRow ( "SELECT id, actor_id, inbox, shared_inbox FROM remoteusers WHERE handle = ?" , handle ) . Scan ( & u . ID , & u . ActorID , & u . Inbox , & u . SharedInbox )
switch {
case err == sql . ErrNoRows :
return nil , ErrRemoteUserNotFound
case err != nil :
log . Error ( "Couldn't get remote user %s: %v" , handle , err )
return nil , err
}
return & u , nil
}
func getActor ( app * App , actorIRI string ) ( * activitystreams . Person , * RemoteUser , error ) {
log . Info ( "Fetching actor %s locally" , actorIRI )
actor := & activitystreams . Person { }