git ssb

0+

alanz / patchwork



forked from Matt McKegg / patchwork

Tree: 8397cee5bd7b17b9f2ebf584813ed0c0a035023d

Files: 8397cee5bd7b17b9f2ebf584813ed0c0a035023d / modules / sbot.js

5252 bytesRaw
1var pull = require('pull-stream')
2var ssbKeys = require('ssb-keys')
3var ref = require('ssb-ref')
4var Reconnect = require('pull-reconnect')
5
6function Hash (onHash) {
7 var buffers = []
8 return pull.through(function (data) {
9 buffers.push('string' === typeof data
10 ? new Buffer(data, 'utf8')
11 : data
12 )
13 }, function (err) {
14 if(err && !onHash) throw err
15 var b = buffers.length > 1 ? Buffer.concat(buffers) : buffers[0]
16 var h = '&'+ssbKeys.hash(b)
17 onHash && onHash(err, h)
18 })
19}
20//uncomment this to use from browser...
21//also depends on having ssb-ws installed.
22//var createClient = require('ssb-lite')
23var createClient = require('ssb-client')
24
25var createFeed = require('ssb-feed')
26var keys = require('patchbay/keys')
27
28var cache = CACHE = {}
29
30exports.needs = {
31 connection_status: 'map',
32 config: 'first',
33 cache: {
34 update_from: 'first'
35 }
36}
37
38exports.gives = {
39// connection_status: true,
40 sbot: {
41 blobs_add: true,
42 links: true,
43 links2: true,
44 query: true,
45 fulltext_search: true,
46 get: true,
47 log: true,
48 user_feed: true,
49 gossip_peers: true,
50 gossip_connect: true,
51 progress: true,
52 publish: true,
53 whoami: true,
54
55 // additional
56 get_id: true,
57 feed: true,
58 list_local: true
59 }
60}
61
62exports.create = function (api) {
63
64 var sbot = null
65 var config = api.config()
66
67 var rec = Reconnect(function (isConn) {
68 function notify (value) {
69 isConn(value); api.connection_status(value)
70 }
71
72 createClient(config.keys, config, function (err, _sbot) {
73 if(err)
74 return notify(err)
75
76 sbot = _sbot
77 sbot.on('closed', function () {
78 sbot = null
79 notify(new Error('closed'))
80 })
81
82 notify()
83 })
84 })
85
86 var internal = {
87 getLatest: rec.async(function (id, cb) {
88 sbot.getLatest(id, cb)
89 }),
90 add: rec.async(function (msg, cb) {
91 sbot.add(msg, cb)
92 })
93 }
94
95 var feed = createFeed(internal, keys, {remote: true})
96
97 return {
98 // connection_status,
99 sbot: {
100 blobs_add: rec.sink(function (cb) {
101 return pull(
102 Hash(function (err, id) {
103 if(err) return cb(err)
104 //completely UGLY hack to tell when the blob has been sucessfully written...
105 var start = Date.now(), n = 5
106 ;(function next () {
107 setTimeout(function () {
108 sbot.blobs.has(id, function (err, has) {
109 if(has) return cb(null, id)
110 if(n--) next()
111 else cb(new Error('write failed'))
112 })
113 }, Date.now() - start)
114 })()
115 }),
116 sbot.blobs.add()
117 )
118 }),
119 links: rec.source(function (query) {
120 return sbot.links(query)
121 }),
122 links2: rec.source(function (query) {
123 return sbot.links2.read(query)
124 }),
125 query: rec.source(function (query) {
126 return sbot.query.read(query)
127 }),
128 log: rec.source(function (opts) {
129 return pull(
130 sbot.createLogStream(opts),
131 pull.through(function (e) {
132 CACHE[e.key] = CACHE[e.key] || e.value
133 api.cache.update_from(e)
134 })
135 )
136 }),
137 user_feed: rec.source(function (opts) {
138 return sbot.createUserStream(opts)
139 }),
140 fulltext_search: rec.source(function (opts) {
141 return sbot.fulltext.search(opts)
142 }),
143 get: rec.async(function (key, cb) {
144 if('function' !== typeof cb)
145 throw new Error('cb must be function')
146 if(CACHE[key]) cb(null, CACHE[key])
147 else sbot.get(key, function (err, value) {
148 if(err) return cb(err)
149 cb(null, CACHE[key] = value)
150 })
151 }),
152 gossip_peers: rec.async(function (cb) {
153 sbot.gossip.peers(cb)
154 }),
155 //liteclient won't have permissions for this
156 gossip_connect: rec.async(function (opts, cb) {
157 sbot.gossip.connect(opts, cb)
158 }),
159 progress: rec.source(function () {
160 return sbot.replicate.changes()
161 }),
162 publish: rec.async(function (content, cb) {
163 if(content.recps)
164 content = ssbKeys.box(content, content.recps.map(function (e) {
165 return ref.isFeed(e) ? e : e.link
166 }))
167 else if(content.mentions)
168 content.mentions.forEach(function (mention) {
169 if(ref.isBlob(mention.link)) {
170 sbot.blobs.push(mention.link, function (err) {
171 if(err) console.error(err)
172 })
173 }
174 })
175
176 feed.add(content, function (err, msg) {
177 if(err) console.error(err)
178 else if(!cb) console.log(msg)
179 cb && cb(err, msg)
180 })
181 }),
182 whoami: rec.async(function (cb) {
183 sbot.whoami(cb)
184 }),
185
186 // ADDITIONAL:
187
188 feed: rec.source(function (opts) {
189 return pull(
190 sbot.createFeedStream(opts),
191 pull.through(function (e) {
192 CACHE[e.key] = CACHE[e.key] || e.value
193 api.cache.update_from(e)
194 })
195 )
196 }),
197
198 get_id: function () {
199 return keys.id
200 },
201
202 list_local: rec.async(function (cb) {
203 return sbot.local.list(cb)
204 })
205 }
206 }
207}
208

Built with git-ssb-web