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