gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

inbox.go (5628B)


      1 // GoToSocial
      2 // Copyright (C) GoToSocial Authors admin@gotosocial.org
      3 // SPDX-License-Identifier: AGPL-3.0-or-later
      4 //
      5 // This program is free software: you can redistribute it and/or modify
      6 // it under the terms of the GNU Affero General Public License as published by
      7 // the Free Software Foundation, either version 3 of the License, or
      8 // (at your option) any later version.
      9 //
     10 // This program is distributed in the hope that it will be useful,
     11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 // GNU Affero General Public License for more details.
     14 //
     15 // You should have received a copy of the GNU Affero General Public License
     16 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17 
     18 package federatingdb
     19 
     20 import (
     21 	"context"
     22 	"fmt"
     23 	"net/url"
     24 
     25 	"github.com/superseriousbusiness/activity/streams"
     26 	"github.com/superseriousbusiness/activity/streams/vocab"
     27 	"github.com/superseriousbusiness/gotosocial/internal/config"
     28 	"github.com/superseriousbusiness/gotosocial/internal/db"
     29 	"github.com/superseriousbusiness/gotosocial/internal/uris"
     30 )
     31 
     32 // InboxContains returns true if the OrderedCollection at 'inbox'
     33 // contains the specified 'id'.
     34 //
     35 // The library makes this call only after acquiring a lock first.
     36 //
     37 // Implementation note: we have our own logic for inboxes so always return false here.
     38 func (f *federatingDB) InboxContains(c context.Context, inbox, id *url.URL) (contains bool, err error) {
     39 	return false, nil
     40 }
     41 
     42 // GetInbox returns the first ordered collection page of the outbox at
     43 // the specified IRI, for prepending new items.
     44 //
     45 // The library makes this call only after acquiring a lock first.
     46 //
     47 // Implementation note: we don't (yet) serve inboxes, so just return empty and nil here.
     48 func (f *federatingDB) GetInbox(c context.Context, inboxIRI *url.URL) (inbox vocab.ActivityStreamsOrderedCollectionPage, err error) {
     49 	return streams.NewActivityStreamsOrderedCollectionPage(), nil
     50 }
     51 
     52 // SetInbox saves the inbox value given from GetInbox, with new items
     53 // prepended. Note that the new items must not be added as independent
     54 // database entries. Separate calls to Create will do that.
     55 //
     56 // The library makes this call only after acquiring a lock first.
     57 //
     58 // Implementation note: we don't allow inbox setting so just return nil here.
     59 func (f *federatingDB) SetInbox(c context.Context, inbox vocab.ActivityStreamsOrderedCollectionPage) error {
     60 	return nil
     61 }
     62 
     63 // InboxesForIRI fetches inboxes corresponding to the given iri.
     64 // This allows your server to skip remote dereferencing of iris
     65 // in order to speed up message delivery, if desired.
     66 //
     67 // It is acceptable to just return nil or an empty slice for the inboxIRIs,
     68 // if you don't know the inbox iri, or you don't wish to use this feature.
     69 // In this case, the library will attempt to resolve inboxes of the iri
     70 // by remote dereferencing instead.
     71 //
     72 // If the input iri is the iri of an Actor, then the inbox for the actor
     73 // should be returned as a single-entry slice.
     74 //
     75 // If the input iri is a Collection (such as a Collection of followers),
     76 // then each follower inbox IRI should be returned in the inboxIRIs slice.
     77 //
     78 // The library makes this call only after acquiring a lock first.
     79 func (f *federatingDB) InboxesForIRI(c context.Context, iri *url.URL) (inboxIRIs []*url.URL, err error) {
     80 	// check if this is a followers collection iri for a local account...
     81 	if iri.Host == config.GetHost() && uris.IsFollowersPath(iri) {
     82 		localAccountUsername, err := uris.ParseFollowersPath(iri)
     83 		if err != nil {
     84 			return nil, fmt.Errorf("couldn't extract local account username from uri %s: %s", iri, err)
     85 		}
     86 
     87 		account, err := f.state.DB.GetAccountByUsernameDomain(c, localAccountUsername, "")
     88 		if err != nil {
     89 			return nil, fmt.Errorf("couldn't find local account with username %s: %s", localAccountUsername, err)
     90 		}
     91 
     92 		follows, err := f.state.DB.GetAccountFollowers(c, account.ID)
     93 		if err != nil {
     94 			return nil, fmt.Errorf("couldn't get followers of local account %s: %s", localAccountUsername, err)
     95 		}
     96 
     97 		for _, follow := range follows {
     98 			if follow.Account == nil {
     99 				// No account exists for this follow,
    100 				// for some reason. Just skip it.
    101 				continue
    102 			}
    103 
    104 			// deliver to a shared inbox if we have that option
    105 			var inbox string
    106 			if config.GetInstanceDeliverToSharedInboxes() && follow.Account.SharedInboxURI != nil && *follow.Account.SharedInboxURI != "" {
    107 				inbox = *follow.Account.SharedInboxURI
    108 			} else {
    109 				inbox = follow.Account.InboxURI
    110 			}
    111 
    112 			inboxIRI, err := url.Parse(inbox)
    113 			if err != nil {
    114 				return nil, fmt.Errorf("error parsing inbox uri of following account %s: %s", follow.Account.InboxURI, err)
    115 			}
    116 			inboxIRIs = append(inboxIRIs, inboxIRI)
    117 		}
    118 		return inboxIRIs, nil
    119 	}
    120 
    121 	// check if this is just an account IRI...
    122 	if account, err := f.state.DB.GetAccountByURI(c, iri.String()); err == nil {
    123 		// deliver to a shared inbox if we have that option
    124 		var inbox string
    125 		if config.GetInstanceDeliverToSharedInboxes() && account.SharedInboxURI != nil && *account.SharedInboxURI != "" {
    126 			inbox = *account.SharedInboxURI
    127 		} else {
    128 			inbox = account.InboxURI
    129 		}
    130 
    131 		inboxIRI, err := url.Parse(inbox)
    132 		if err != nil {
    133 			return nil, fmt.Errorf("error parsing account inbox uri %s: %s", account.InboxURI, account.InboxURI)
    134 		}
    135 		// we've got it
    136 		inboxIRIs = append(inboxIRIs, inboxIRI)
    137 		return inboxIRIs, nil
    138 	} else if err != db.ErrNoEntries {
    139 		// there's been a real error
    140 		return nil, err
    141 	}
    142 
    143 	// no error, we just didn't find anything so let the library handle the rest
    144 	return nil, nil
    145 }