secure-scuttlebot classic
at main 3.9 kB view raw
1var pull = require('pull-stream') 2var many = require('pull-many') 3var mfr = require('map-filter-reduce') 4 5function all(stream, cb) { 6 pull(stream, pull.collect(cb)) 7} 8 9//var plugs = require('../plugs') 10//var sbot_links2 = plugs.first(exports.sbot_links2 = []) 11//var sbot_query = plugs.first(exports.sbot_query = []) 12// 13exports.needs = { 14 sbot_links2: 'first', 15 sbot_query: 'first' 16} 17 18exports.gives = { 19 connection_status: true, 20 signifier: true, 21 signified: true, 22} 23 24/* 25 filter(rel: ['mentions', prefix('@')]) | reduce(name: rel[1], value: count()) 26*/ 27 28var filter = { 29 $filter: { 30 rel: ["mentions", {$prefix: "@"}] 31 } 32} 33var map = { 34 $map: { 35 name: ['rel', 1], 36 id: 'dest', 37 ts: 'ts', 38 } 39} 40 41var reduce = { 42 $reduce: { 43 name: 'name', 44 id: 'id', 45 rank: {$count: true}, 46 ts: {$max: 'ts'} 47 } 48} 49 50var filter2 = { 51 $filter: { 52 value: { 53 content: { 54 type: "about", 55 name: {"$prefix": ""}, 56 about: {"$prefix": ""} 57 } 58 } 59 } 60} 61 62var map2 = { 63 $map: { 64 name: ["value", "content", "name"], 65 id: ['value', 'content', 'about'], 66 ts: "timestamp" 67 } 68} 69 70//union with this query... 71 72var names = NAMES = [] 73function update(name) { 74 var n = names.find(function (e) { 75 return e.id == name.id && e.name == e.name 76 }) 77 if(!n) { 78 name.rank = 1 79 //this should be inserted at the right place... 80 names.push(name) 81 } 82 else 83 n.rank = n.rank += (name.rank || 1) 84} 85 86var ready = false, waiting = [] 87 88var merge = { 89 $reduce: { 90 name: 'name', 91 id: 'id', 92 rank: {$sum: 'rank'}, 93 ts: {$max: 'ts'} 94 } 95} 96 97function add_sigil(stream) { 98 return pull(stream, pull.map(function (e) { 99 if (e && e.id && e.name && e.id[0] !== e.name[0]) 100 e.name = e.id[0] + e.name 101 return e 102 }) 103 ) 104} 105 106var queryNamedGitRepos = [ 107 {$filter: { 108 value: { 109 content: { 110 type: "git-repo", 111 name: {"$prefix": ""} 112 } 113 } 114 }}, 115 {$map: { 116 name: ["value", "content", "name"], 117 id: ['key'], 118 ts: "timestamp" 119 }}, 120 reduce 121] 122exports.create = function (api) { 123 124 var exports = {} 125 exports.connection_status = function (err) { 126 if(!err) { 127 pull( 128 many([ 129 api.sbot_links2({query: [filter, map, reduce]}), 130 add_sigil(api.sbot_query({query: [filter2, map2, reduce]})), 131 add_sigil(api.sbot_query({query: queryNamedGitRepos})) 132 ]), 133 //reducing also ensures order by the lookup properties 134 //in this case: [name, id] 135 mfr.reduce(merge), 136 pull.collect(function (err, ary) { 137 if(!err) { 138 NAMES = names = ary 139 ready = true 140 while(waiting.length) waiting.shift()() 141 } 142 }) 143 ) 144 145 pull(many([ 146 api.sbot_links2({query: [filter, map], old: false}), 147 add_sigil(api.sbot_query({query: [filter2, map2], old: false})), 148 add_sigil(api.sbot_query({query: queryNamedGitRepos, old: false})) 149 ]), 150 pull.drain(update)) 151 } 152 } 153 154 function async(fn) { 155 return function (value, cb) { 156 function go () { cb(null, fn(value)) } 157 if(ready) go() 158 else waiting.push(go) 159 } 160 } 161 162 function rank(ary) { 163 //sort by most used, or most recently used 164 return ary.sort(function (a, b) { return b.rank - a.rank || b.ts - a.ts }) 165 } 166 167 //we are just iterating over the entire array. 168 //if this becomes a problem, maintain two arrays 169 //one of each sort order, but do not duplicate the objects. 170 //that should mean the space required is just 2x object references, 171 //not 2x objects, and we can use binary search to find matches. 172 173 exports.signifier = async(function (id) { 174 return rank(names.filter(function (e) { return e.id == id})) 175 }) 176 177 exports.signified = async(function (name) { 178 var rx = new RegExp('^'+name) 179 return rank(names.filter(function (e) { return rx.test(e.name) })) 180 }) 181 182 return exports 183}