Files: 55fc93a9190c25f467ead205ab8d676b5191dbd4 / lib / plugins / search.js
2469 bytesRaw
1 | const pull = require('pull-stream') |
2 | const pullCat = require('pull-cat') |
3 | |
4 | module.exports = function (ssb) { |
5 | return { |
6 | linear: function ({ lt, gt, reverse, limit, query, old, live }) { |
7 | // handle markers passed in to lt / gt |
8 | const opts = { reverse, old, live, private: true } |
9 | if (lt && typeof lt.timestamp === 'number') lt = lt.timestamp |
10 | if (gt && typeof gt.timestamp === 'number') gt = gt.timestamp |
11 | if (typeof lt === 'number') opts.lt = lt |
12 | if (typeof gt === 'number') opts.gt = gt |
13 | |
14 | const matchesQuery = searchFilter(query) |
15 | const marker = { marker: true, timestamp: null } |
16 | |
17 | const stream = pull( |
18 | ssb.createLogStream(opts), |
19 | pull.through(msg => { |
20 | marker.timestamp = msg.timestamp |
21 | }), |
22 | pull.filter(matchesQuery) |
23 | ) |
24 | |
25 | // TRUNCATE |
26 | if (typeof limit === 'number') { |
27 | let count = 0 |
28 | return pullCat([ |
29 | pull( |
30 | stream, |
31 | pull.take(limit), |
32 | pull.through(() => { |
33 | count += 1 |
34 | }) |
35 | ), |
36 | |
37 | // send truncated marker for resuming search |
38 | pull( |
39 | pull.values([marker]), |
40 | pull.filter(() => count === limit) |
41 | ) |
42 | ]) |
43 | } else { |
44 | return stream |
45 | } |
46 | }, |
47 | privateLinear: function ({ reverse, query, old, live, author }) { |
48 | // handle markers passed in to lt / gt |
49 | const opts = { reverse, old, live, private: true } |
50 | const filter = { |
51 | timestamp: { $gt: 0 } |
52 | } |
53 | |
54 | if (author) { |
55 | filter.value = { |
56 | author |
57 | } |
58 | } |
59 | |
60 | opts.query = [ |
61 | { $filter: filter } |
62 | ] |
63 | |
64 | const matchesQuery = searchFilter(query) |
65 | |
66 | return pull( |
67 | ssb.private.read(opts), |
68 | pull.filter(matchesQuery) |
69 | ) |
70 | } |
71 | } |
72 | } |
73 | |
74 | function searchFilter (terms) { |
75 | return function (msg) { |
76 | if (msg.sync) return true |
77 | const c = msg && msg.value && msg.value.content |
78 | return c && ( |
79 | msg.key === terms[0] || andSearch(terms.map(function (term) { |
80 | return new RegExp('\\b' + term + '\\b', 'i') |
81 | }), [c.text, c.name, c.title]) |
82 | ) |
83 | } |
84 | } |
85 | |
86 | function andSearch (terms, inputs) { |
87 | for (let i = 0; i < terms.length; i++) { |
88 | let match = false |
89 | for (let j = 0; j < inputs.length; j++) { |
90 | if (terms[i].test(inputs[j])) match = true |
91 | } |
92 | // if a term was not matched by anything, filter this one |
93 | if (!match) return false |
94 | } |
95 | return true |
96 | } |
97 |
Built with git-ssb-web