git ssb

4+

Dominic / scuttlebot



Commit 765a31b854726f3c3f4e39689b4e4d4b8f86bcf8

Merge branch 'friends2' into flume

Dominic Tarr committed on 5/28/2017, 10:48:09 AM
Parent: d347cecf5f54a7f0f690fd6c780b3bb092875388
Parent: 3c54223e55ec3292754f1ff70a4176dd7e0d7083

Files changed

package.jsonchanged
plugins/block.jschanged
plugins/friends.jschanged
test/block.jschanged
test/block2.jschanged
test/block3.jschanged
package.jsonView
@@ -55,8 +55,9 @@
5555 "ssb-blobs": "^1.0.1",
5656 "ssb-client": "^4.4.1",
5757 "ssb-config": "^2.0.0",
5858 "ssb-ebt": "0.0.7",
59+ "ssb-friends": "^1.0.0",
5960 "ssb-keys": "^7.0.0",
6061 "ssb-links": "^3.0.0",
6162 "ssb-msgs": "~5.2.0",
6263 "ssb-query": "^1.0.0",
plugins/block.jsView
@@ -12,30 +12,21 @@
1212 //TODO: move other blocking code in here,
1313 // i think we'll need a hook system for this.
1414
1515 //if a currently connected peer is blocked, disconnect them immediately.
16- pull(
17- sbot.friends.createFriendStream({graph: 'flag', live: true}),
18- pull.drain(function (blocked) {
19- if(sbot.peers[blocked]) {
20- sbot.peers[blocked].forEach(function (b) {
21- b.close(true, function () {})
22- })
23- }
24- })
25- )
2616
17+ var g = {}
18+
19+ sbot.friends.post(function (_g) {
20+ g = _g
21+ })
22+
2723 function isBlocked (_opts) {
2824 var opts
29-
25+ if(!g) return //only possible briefly at startup
3026 if('string' === typeof _opts)
31- opts = {
32- source: sbot.id, dest: _opts, graph:'flag'
33- }
34- else opts = {
35- source: _opts.source, dest: _opts.dest, graph: 'flag'
36- }
37- return sbot.friends.get(opts)
27+ return g[sbot.id] ? g[sbot.id][_opts] === false : false
28+ return g[_opts.source] ? g[_opts.source][_opts.dest] === false : false
3829 }
3930
4031 sbot.createHistoryStream.hook(function (fn, args) {
4132 var opts = args[0], id = this.id
@@ -51,9 +42,9 @@
5142 if(!msg.content && msg.value.content)
5243 msg = msg.value
5344 if(msg.content.type !== 'contact') return true
5445 return !(
55- msg.content.flagged &&
46+ (msg.content.flagged || msg.content.blocking) &&
5647 msg.content.contact === id
5748 )
5849 })
5950 )
plugins/friends.jsView
@@ -7,9 +7,13 @@
77 var mdm = require('mdmanifest')
88 var valid = require('../lib/validators')
99 var apidoc = require('../lib/apidocs').friends
1010 var ref = require('ssb-ref')
11+var Obv = require('obv')
1112
13+var F = require('ssb-friends')
14+var block = require('ssb-friends/block')
15+
1216 // friends plugin
1317 // methods to analyze the social graph
1418 // maintains a 'follow' and 'flag' graph
1519
@@ -29,26 +33,38 @@
2933 exports.version = '1.0.0'
3034 exports.manifest = mdm.manifest(apidoc)
3135
3236 exports.init = function (sbot, config) {
33- var g = {}
34- var index = sbot._flumeUse('friends', Reduce(1, function (_, rel) {
35- //if(!g) g = {}
36- if(!ref.isFeed(rel.from)) throw new Error('FROM is not id')
37+ var post = Obv()
38+ post.set({})
39+ var index = sbot._flumeUse('friends', Reduce(2, function (g, rel) {
40+ if(!g) g = {}
3741 G.addEdge(g, rel.from, rel.to, rel.value)
3842 return g
3943 }, function (data) {
4044 if(data.value.content.type === 'contact' && ref.isFeed(data.value.content.contact)) {
45+ var tristate = (
46+ data.value.content.following ? true
47+ : data.value.content.flagged || data.value.content.blocking ? false
48+ : null
49+ )
4150 return {
4251 from: data.value.author,
4352 to: data.value.content.contact,
44- value: data.value.content.following
53+ value: tristate
4554 }
4655 }
4756 }))
4857
58+ index.since(function () {
59+ //it looks async but this will always be sync after loading
60+ index.get(null, function (_, v) {
61+ post.set(v)
62+ })
63+ })
64+
4965 return {
50-
66+ post: post,
5167 get: function (opts, cb) {
5268 index.get(opts, cb)
5369 },
5470
@@ -56,12 +72,9 @@
5672 opts = opts || {}
5773 var live = opts.live === true
5874 var meta = opts.meta === true
5975 var start = opts.start || sbot.id
60- var first = true
6176 var reachable
62- if(!g) throw new Error('not initialized')
63- //g = g || {}
6477 return pull(
6578 index.stream(opts),
6679 FlatMap(function (v) {
6780 if(!v) return []
@@ -69,44 +82,28 @@
6982 //this code handles real time streaming of the hops map.
7083 function push (to, hops) {
7184 out.push(meta ? {id: to, hops: hops} : to)
7285 }
73- var out = []
74- if(v.from && v.to) {
75- if(!reachable) {
76- //this is is hack...
77- reachable = {}
78- reachable[sbot.id] = 0
79- push(sbot.id, 0)
80- }
81- //recalculate the portion of the graph, reachable in opts.hops
82- //(but only the portion not already reachable)
83- var _reachable = G.hops(g, v.from, reachable[v.from], opts.hops || 3, reachable)
8486
85- for(var k in _reachable) {
86- //check if it has _become_ reachable just now.
87- //if so add to the set
88- if(reachable[k] == null)
89- push(k, reachable[k] = _reachable[k])
90- //if this has shortened the path, then update.
91- else if(reachable[k] > _reachable[k])
92- reachable[k] = _reachable[k]
93- //else, we where already able to reach this node.
94- }
95- }
96- else {
97- var _g = v
98- reachable = G.hops(_g, start, 0, opts.hops || 3)
87+ var out = [], g = post.value
88+
89+ //the edge has already been added to g
90+ if(!reachable) {
91+ reachable = F.reachable(g, start, block)
9992 for(var k in reachable)
100- push(k, reachable[k])
101- }
102- if(first) {
103- first = false
104- if(live) {
105- out.push({sync: true})
93+ if(block.isWanted(reachable[k]))
94+ push(k, reachable[k][0])
95+ } else {
96+ var _reachable = F.reachable(g, start, block)
97+ var patch = F.diff(reachable, _reachable)
98+ for(var k in patch) {
99+ if(patch[k] == null)
100+ push(k, -1)
101+ else if(block.isWanted(patch[k]))
102+ push(k, patch[k][0])
106103 }
104+ reachable = _reachable
107105 }
108-
109106 return out
110107 })
111108
112109 )
@@ -126,4 +123,7 @@
126123 }
127124 }
128125
129126
127+
128+
129+
test/block.jsView
@@ -10,8 +10,16 @@
1010 .use(require('../plugins/replicate'))
1111
1212 var toAddress = require('../lib/util').toAddress
1313
14+function once (fn) {
15+ var called = 0
16+ return function () {
17+ if(called++) throw new Error('called :'+called+' times!')
18+ return fn.apply(this, arguments)
19+ }
20+}
21+
1422 // alice, bob, and carol all follow each other,
1523 // but then bob offends alice, and she blocks him.
1624 // this means that:
1725 //
@@ -35,16 +43,21 @@
3543 })
3644
3745 tape('alice blocks bob, and bob cannot connect to alice', function (t) {
3846
47+ console.log({
48+ alice: alice.id,
49+ bob: bob.id,
50+ carol: carol.id
51+ })
52+
3953 //in the beginning alice and bob follow each other
4054 cont.para([
4155 cont(alice.publish)(u.follow(bob.id)),
4256 cont(bob .publish)(u.follow(alice.id)),
4357 cont(carol.publish)(u.follow(alice.id))
4458 ]) (function (err) {
4559 if(err) throw err
46-
4760 var n = 3, rpc
4861
4962 bob.connect(alice.getAddress(), function (err, _rpc) {
5063 if(err) throw err
@@ -54,24 +67,23 @@
5467 })
5568
5669 //get the next messages that are replicated to alice and bob,
5770 //and check that these are the correct follow messages.
58- var bobCancel = bob.post(function (op) {
71+ var bobCancel = bob.post(once(function (op) {
5972 console.log('BOB_POST', op)
6073 //should be the alice's follow(bob) message.
61- t.equal(op.value.author, alice.id)
62- t.equal(op.value.content.contact, bob.id)
74+ t.equal(op.value.author, alice.id, 'bob expected message from alice')
75+ t.equal(op.value.content.contact, bob.id, 'bob expected message to be about bob')
6376 next()
64- })
77+ }), false)
6578
66- var aliceCancel = alice.post(function (op) {
79+ var aliceCancel = alice.post(once(function (op) {
6780 console.log('ALICE_POST', op)
6881 //should be the bob's follow(alice) message.
69- t.equal(op.value.author, bob.id)
70- t.equal(op.value.content.contact, alice.id)
82+ t.equal(op.value.author, bob.id, 'alice expected to receive a message from bob')
83+ t.equal(op.value.content.contact, alice.id, 'alice expected received message to be about alice')
7184 next()
72- })
73-
85+ }), false)
7486 function next () {
7587 if(--n) return
7688
7789 rpc.close(true, function () {
@@ -82,68 +94,61 @@
8294 alice.publish(u.block(bob.id))
8395 (function (err) {
8496 if(err) throw err
8597
86- t.ok(alice.friends.get({source: alice.id, dest: bob.id, graph: 'flag'}))
98+ alice.friends.get(null, function (err, g) {
99+ if(err) throw err
100+ t.equal(g[alice.id][bob.id], false)
87101
88- pull(
89- alice.links({
90- source: alice.id,
91- dest: bob.id,
92- rel: 'contact',
93- values: true
94- }),
95- pull.filter(function (op) {
96- return op.value.content.flagged != null
97- }),
98- pull.collect(function (err, ary) {
99- if(err) throw err
100- console.log(ary)
101- t.ok(flagged = ary.pop().value.content.flagged, 'alice did block bob')
102+ pull(
103+ alice.links({
104+ source: alice.id,
105+ dest: bob.id,
106+ rel: 'contact',
107+ values: true
108+ }),
109+ pull.filter(function (op) {
110+ return op.value.content.flagged != null
111+ }),
112+ pull.collect(function (err, ary) {
113+ if(err) throw err
114+ console.log(ary)
115+ t.ok(flagged = ary.pop().value.content.flagged, 'alice did block bob')
102116
103- //since bob is blocked, he should not be able to connect
104- bob.connect(alice.getAddress(), function (err, rpc) {
105- t.ok(err, 'bob is blocked, should fail to connect to alice')
117+ //since bob is blocked, he should not be able to connect
118+ bob.connect(alice.getAddress(), function (err, rpc) {
119+ t.ok(err, 'bob is blocked, should fail to connect to alice')
106120
107121
108- carol.post(function (msg) {
109- console.log('CAROL RECV', msg, alice.id)
110- if(msg.author === alice.id) {
111- if(msg.sequence == 2)
112- t.end()
113- }
114- })
122+ carol.post(function (msg) {
123+ console.log('CAROL RECV', msg, alice.id)
124+ if(msg.author === alice.id) {
125+ if(msg.sequence == 2)
126+ t.end()
127+ }
128+ })
115129
116- //but carol, should, because she is not blocked.
117- carol.connect(alice.getAddress(), function (err, rpc) {
118- if(err) throw err
119- console.log('CAROL CONNECTED TO ALICE', carol.id, alice.id)
120-// pull(
121-// alice.createHistoryStream({id: alice.id, seq: 0}),
122-// pull.collect(console.log)
123-// )
130+ //but carol, should, because she is not blocked.
131+ carol.connect(alice.getAddress(), function (err, rpc) {
132+ if(err) throw err
133+ console.log('CAROL CONNECTED TO ALICE', carol.id, alice.id)
134+ rpc.on('closed', function () {
135+ pull(
136+ carol.createHistoryStream({id: alice.id, seq: 0, live: false}),
137+ pull.collect(function (err, ary) {
138+ if(err) throw err
124139
125- rpc.on('closed', function () {
126- pull(
127- carol.createHistoryStream({id: alice.id, seq: 0, live: false}),
128- pull.collect(function (err, ary) {
129- if(err) throw err
130-
131- t.ok(ary.length, 'carol replicated data from alice')
132- console.log(alice.id, carol.id, err, ary)
133- t.end()
134- })
135- )
140+ t.ok(ary.length, 'carol replicated data from alice')
141+ console.log(alice.id, carol.id, err, ary)
142+ t.end()
143+ })
144+ )
145+ })
136146 })
137147 })
138-// carol.once('replicate:finish', function (vclock) {
139-// t.equal(vclock[alice.id], 2)
140-// //in next test, bob connects to carol...
141-// t.end()
142-// })
143148 })
144- })
145- )
149+ )
150+ })
146151 })
147152 })
148153 }
149154 })
@@ -177,7 +182,4 @@
177182
178183
179184
180185
181-
182-
183-
test/block2.jsView
@@ -52,9 +52,9 @@
5252
5353 t.equal(op.value.content.contact, bob.id)
5454 alice.publish(u.block(bob.id))
5555 (function (err) { if(err) throw err })
56- })
56+ }, false)
5757
5858 })
5959 })
6060
test/block3.jsView
@@ -77,11 +77,8 @@
7777 t.equal(op.value.author, alice.id)
7878 t.equal(op.value.content.contact, bob.id)
7979 alice.publish(u.block(bob.id))
8080 (function (err) { if(err) throw err })
81- })
81+ }, false)
8282 })
8383 })
8484
85-
86-
87-

Built with git-ssb-web