Files: 55fc93a9190c25f467ead205ab8d676b5191dbd4 / lib / plugins / gatherings.js
4685 bytesRaw
1 | |
2 | const pull = require('pull-stream') |
3 | const extend = require('xtend') |
4 | const pullResume = require('../pull-resume') |
5 | const threadSummary = require('../thread-summary') |
6 | const ResolveAbouts = require('../resolve-abouts') |
7 | const Paramap = require('pull-paramap') |
8 | const FilterBlocked = require('../filter-blocked') |
9 | const LookupRoots = require('../lookup-roots') |
10 | |
11 | const async = require('async') |
12 | |
13 | exports.manifest = { |
14 | latest: 'source', |
15 | latestAttending: 'source', |
16 | roots: 'source' |
17 | } |
18 | |
19 | exports.init = function (ssb) { |
20 | return { |
21 | latest: function () { |
22 | return pull( |
23 | ssb.messagesByType({ type: 'gathering', live: true, old: false }), |
24 | ResolveAbouts({ ssb }), |
25 | ApplyFilterResult({ ssb, passThroughOwn: true }), |
26 | pull.filter(msg => !!msg.filterResult) |
27 | ) |
28 | }, |
29 | latestAttending: function () { |
30 | return pull( |
31 | ssb.query.read({ |
32 | query: [{ $filter: { value: { content: { type: 'about', attendee: { link: ssb.id } } } } }] |
33 | }), |
34 | LookupRoots({ ssb }), |
35 | ResolveAbouts({ ssb }), |
36 | ApplyFilterResult({ ssb, passThroughOwn: true }), |
37 | pull.filter(msg => !!msg.filterResult) |
38 | ) |
39 | }, |
40 | roots: function ({ reverse, limit, resume, onlyAttending = false }) { |
41 | // use resume option if specified |
42 | const opts = { reverse, old: true, type: 'gathering', private: true } |
43 | if (resume) { |
44 | opts[reverse ? 'lt' : 'gt'] = resume |
45 | } |
46 | |
47 | return pullResume.source(ssb.messagesByType(opts), { |
48 | limit, |
49 | getResume: (item) => { |
50 | return item.timestamp |
51 | }, |
52 | filterMap: pull( |
53 | // don't include if author blocked |
54 | FilterBlocked([ssb.id], { |
55 | isBlocking: ssb.patchwork.contacts.isBlocking |
56 | }), |
57 | |
58 | // RESOLVE ROOTS WITH ABOUTS |
59 | ResolveAbouts({ ssb }), |
60 | |
61 | // FILTER GATHERINGS BASED ON ATTENDEES AND AUTHOR (and hide if no title) |
62 | ApplyFilterResult({ ssb, onlyAttending }), |
63 | pull.filter(msg => !!msg.filterResult), |
64 | |
65 | // ADD THREAD SUMMARY |
66 | Paramap((item, cb) => { |
67 | threadSummary(item.key, { |
68 | recentLimit: 3, |
69 | readThread: ssb.patchwork.thread.read, |
70 | bumpFilter, |
71 | pullFilter: pull( |
72 | FilterBlocked([item.value && item.value.author, ssb.id], { isBlocking: ssb.patchwork.contacts.isBlocking }), |
73 | ApplyReplyFilterResult({ ssb }) |
74 | ) |
75 | }, (err, summary) => { |
76 | if (err) return cb(err) |
77 | cb(null, extend(item, summary, { |
78 | rootBump: bumpFilter(item) |
79 | })) |
80 | }) |
81 | }, 10) |
82 | ) |
83 | }) |
84 | } |
85 | } |
86 | } |
87 | |
88 | function bumpFilter (msg) { |
89 | if (msg.value.content.type === 'about' && msg.filterResult && msg.value.content.attendee && !msg.value.content.attendee.remove) { |
90 | return { type: 'attending' } |
91 | } |
92 | } |
93 | |
94 | function ApplyFilterResult ({ ssb, passThroughOwn = false, onlyAttending = false }) { |
95 | return pull.asyncMap((msg, cb) => { |
96 | const isYours = ssb.id === msg.value.author |
97 | const recps = msg.value.content.recps |
98 | const passThrough = isYours && passThroughOwn |
99 | ssb.patchwork.contacts.isFollowing({ source: ssb.id, dest: msg.value.author }, (err, followingAuthor) => { |
100 | if (err) return cb(err) |
101 | const attending = (msg.gathering && msg.gathering.attending) || [] |
102 | async.filterSeries(attending, (dest, cb) => { |
103 | ssb.patchwork.contacts.isFollowing({ source: ssb.id, dest }, cb) |
104 | }, (err, followingAttending) => { |
105 | if (err) return cb(err) |
106 | const isAttending = Array.isArray(attending) && attending.includes(ssb.id) |
107 | const isRecp = Array.isArray(recps) && recps.includes(ssb.id) |
108 | const hasTitle = !!msg.gathering.title |
109 | const isVisible = passThrough || hasTitle |
110 | |
111 | if (onlyAttending && !isAttending && !isYours) { |
112 | // only wanting events we are attending, and we are not attending so don't run filters |
113 | } else if ((followingAttending.length || followingAuthor || isYours || isAttending || isRecp) && isVisible) { |
114 | msg.filterResult = { |
115 | followingAttending, |
116 | followingAuthor, |
117 | isAttending, |
118 | isYours, |
119 | hasTitle |
120 | } |
121 | } |
122 | |
123 | cb(null, msg) |
124 | }) |
125 | }) |
126 | }) |
127 | } |
128 | |
129 | function ApplyReplyFilterResult ({ ssb }) { |
130 | return pull.asyncMap((msg, cb) => { |
131 | ssb.patchwork.contacts.isFollowing({ source: ssb.id, dest: msg.value.author }, (err, isFollowing) => { |
132 | if (err) return cb(err) |
133 | if (isFollowing) { |
134 | msg.filterResult = { |
135 | isFollowing |
136 | } |
137 | } |
138 | cb(null, msg) |
139 | }) |
140 | }) |
141 | } |
142 |
Built with git-ssb-web