forked from ssbc/go-ssb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsbot.go
169 lines (132 loc) · 4.07 KB
/
sbot.go
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
// SPDX-FileCopyrightText: 2021 The Go-SSB Authors
//
// SPDX-License-Identifier: MIT
package ssb
import (
"fmt"
refs "github.com/ssbc/go-ssb-refs"
"github.com/ssbc/go-ssb-refs/tfk"
"github.com/ssbc/go-ssb/internal/storedrefs"
"github.com/ssbc/margaret"
librarian "github.com/ssbc/margaret/indexes"
"github.com/ssbc/margaret/multilog"
)
type Publisher interface {
margaret.Log
// Publish is a utility wrapper around append which returns the new message reference key
Publish(content interface{}) (refs.Message, error)
}
type Getter interface {
Get(refs.MessageRef) (refs.Message, error)
}
type MultiLogGetter interface {
GetMultiLog(name string) (multilog.MultiLog, bool)
}
type SimpleIndexGetter interface {
GetSimpleIndex(name string) (librarian.Index, bool)
}
type Indexer interface {
MultiLogGetter
SimpleIndexGetter
GetIndexNamesSimple() []string
GetIndexNamesMultiLog() []string
}
// Replicator is used to tell the bot which feeds to copy from other peers and which ones to block
type Replicator interface {
// Replicate mark a feed for replication and connection acceptance
Replicate(refs.FeedRef)
// DontReplicate stops replicating a feed
DontReplicate(refs.FeedRef)
Block(refs.FeedRef)
Unblock(refs.FeedRef)
Lister() ReplicationLister
}
// ReplicationLister is used by the executing part to get the lists
// TODO: maybe only pass read-only/copies or slices down
type ReplicationLister interface {
Authorizer
ReplicationList() *StrFeedSet
BlockList() *StrFeedSet
}
// Statuser returns status information about the bot, like how many open connections it has (see type Status for more)
type Statuser interface {
Status() (Status, error)
}
type PeerStatus struct {
Addr string
Since string
}
type Status struct {
PID int // process id of the bot
Peers []PeerStatus
Blobs []BlobWant
Root int64
Indicies IndexStates
}
type IndexStates []IndexState
type IndexState struct {
Name string
State string
}
type ContentNuller interface {
NullContent(feed refs.FeedRef, seq uint) error
}
// this is one message of replicate.upto
// also handy to talk about the (latest) state of a single feed
type ReplicateUpToResponse struct {
ID refs.FeedRef `json:"id"`
Sequence int64 `json:"sequence"`
}
var _ margaret.Seqer = ReplicateUpToResponse{}
func (upto ReplicateUpToResponse) Seq() int64 {
return upto.Sequence
}
type ReplicateUpToResponseSet map[string]ReplicateUpToResponse
// FeedsWithSeqs returns a source that emits one ReplicateUpToResponse per stored feed in feedIndex
// TODO: make cancelable and with no RAM overhead when only partially used (iterate on demand)
func FeedsWithSeqs(feedIndex multilog.MultiLog) (ReplicateUpToResponseSet, error) {
storedFeeds, err := feedIndex.List()
if err != nil {
return nil, fmt.Errorf("feedSrc: did not get user list: %w", err)
}
allTheFeeds := make([]refs.FeedRef, len(storedFeeds))
for i, author := range storedFeeds {
var sr tfk.Feed
err := sr.UnmarshalBinary([]byte(author))
if err != nil {
return nil, fmt.Errorf("feedSrc(%d): invalid storage ref: %w", i, err)
}
allTheFeeds[i], err = sr.Feed()
if err != nil {
return nil, fmt.Errorf("feedSrc(%d): failed to get feed: %w", i, err)
}
}
return WantedFeedsWithSeqs(feedIndex, allTheFeeds)
}
// WantedFeedsWithSeqs is like FeedsWithSeqs but omits feeds that are not in the wanted list.
func WantedFeedsWithSeqs(feedIndex multilog.MultiLog, wanted []refs.FeedRef) (ReplicateUpToResponseSet, error) {
var feedsWithSeqs = make(ReplicateUpToResponseSet, len(wanted))
for i, author := range wanted {
idxAddr := storedrefs.Feed(author)
isStored, err := multilog.Has(feedIndex, idxAddr)
if err != nil {
return nil, err
}
if !isStored {
feedsWithSeqs[author.String()] = ReplicateUpToResponse{
ID: author,
Sequence: 0,
}
continue
}
subLog, err := feedIndex.Get(idxAddr)
if err != nil {
return nil, fmt.Errorf("feedSrc(%d): did not load sublog: %w", i, err)
}
feedsWithSeqs[author.String()] = ReplicateUpToResponse{
ID: author,
Sequence: subLog.Seq() + 1,
}
}
return feedsWithSeqs, nil
}