Files: 55fc93a9190c25f467ead205ab8d676b5191dbd4 / lib / plugins / profile.js
3946 bytesRaw
1 | const pull = require('pull-stream') |
2 | const parallel = require('run-parallel') |
3 | const Paramap = require('pull-paramap') |
4 | const extend = require('xtend') |
5 | |
6 | const HLRU = require('hashlru') |
7 | const pullResume = require('../pull-resume') |
8 | const threadSummary = require('../thread-summary') |
9 | const LookupRoots = require('../lookup-roots') |
10 | const ResolveAbouts = require('../resolve-abouts') |
11 | const UniqueRoots = require('../unique-roots') |
12 | const getRoot = require('../get-root') |
13 | |
14 | exports.manifest = { |
15 | avatar: 'async', |
16 | latest: 'source', |
17 | roots: 'source' |
18 | } |
19 | |
20 | exports.init = function (ssb) { |
21 | const cache = HLRU(100) |
22 | |
23 | return { |
24 | avatar: function avatar ({ id }, cb) { |
25 | const result = { id } |
26 | parallel([(done) => { |
27 | ssb.about.socialValue({ dest: id, key: 'name' }, (err, value) => { |
28 | if (err) return done(err) |
29 | result.name = value |
30 | done() |
31 | }) |
32 | }, (done) => { |
33 | ssb.about.socialValue({ dest: id, key: 'image' }, (err, value) => { |
34 | if (err) return done(err) |
35 | if (value && value instanceof Object && value.link) value = value.link |
36 | result.image = value |
37 | done() |
38 | }) |
39 | }], (err) => { |
40 | if (err) return cb(err) |
41 | cb(null, result) |
42 | }) |
43 | }, |
44 | latest: function latest ({ id }) { |
45 | return pull( |
46 | ssb.createUserStream({ id, live: true, old: false, awaitReady: false }), |
47 | pull.filter(bumpFilter), |
48 | LookupRoots({ ssb, cache }), |
49 | pull.filter(msg => { |
50 | return !getRoot(msg.root) |
51 | }) |
52 | // TODO: handle blocked users |
53 | ) |
54 | |
55 | function bumpFilter (msg) { |
56 | return checkBump(msg, { id }) |
57 | } |
58 | }, |
59 | roots: function roots ({ id, limit, reverse, resume }) { |
60 | // use resume option if specified |
61 | |
62 | const opts = { id, reverse, old: true, awaitReady: false } |
63 | if (resume) { |
64 | opts[reverse ? 'lt' : 'gt'] = resume |
65 | } |
66 | |
67 | return pullResume.source(ssb.createUserStream(opts), { |
68 | limit, |
69 | getResume: (item) => { |
70 | return item && item.value && item.value.sequence |
71 | }, |
72 | filterMap: pull( |
73 | pull.filter(bumpFilter), |
74 | |
75 | LookupRoots({ ssb, cache }), |
76 | |
77 | // DON'T REPEAT THE SAME THREAD |
78 | UniqueRoots(), |
79 | |
80 | // DON'T INCLUDE UN-ROOTED MESSAGES (e.g. missing conversation root) |
81 | pull.filter(msg => { |
82 | return !getRoot(msg.root) |
83 | }), |
84 | |
85 | // JUST RETURN THE ROOT OF THE MESSAGE |
86 | pull.map(msg => { |
87 | return msg.root || msg |
88 | }), |
89 | |
90 | // RESOLVE ROOTS WITH ABOUTS (gatherings) |
91 | ResolveAbouts({ ssb }), |
92 | |
93 | // ADD THREAD SUMMARY |
94 | Paramap((item, cb) => { |
95 | threadSummary(item.key, { |
96 | readThread: ssb.patchwork.thread.read, |
97 | recentLimit: 3, |
98 | bumpFilter, |
99 | recentFilter |
100 | // TODO: hide blocked replies from other users |
101 | }, (err, summary) => { |
102 | if (err) return cb(err) |
103 | cb(null, extend(item, summary)) |
104 | }) |
105 | }, 20) |
106 | ) |
107 | }) |
108 | |
109 | function recentFilter (msg) { |
110 | // only show replies by this feed on the profile |
111 | return msg.value.author === id |
112 | } |
113 | |
114 | function bumpFilter (msg) { |
115 | return checkBump(msg, { id }) |
116 | } |
117 | } |
118 | } |
119 | } |
120 | |
121 | function checkBump (msg, { id }) { |
122 | if (msg.value.author === id) { |
123 | const content = msg.value.content |
124 | const type = content.type |
125 | if (type === 'vote' && !getRoot(msg)) { // only show likes when root post |
126 | const vote = content.vote |
127 | if (vote) { |
128 | return { type: 'reaction', reaction: vote.expression, value: vote.value } |
129 | } |
130 | } else if (type === 'post') { |
131 | if (getRoot(msg)) { |
132 | return 'reply' |
133 | } else { |
134 | return 'post' |
135 | } |
136 | } else if (type === 'about') { |
137 | return 'update' |
138 | } else if (type === 'contact') { |
139 | return 'post' |
140 | } |
141 | } |
142 | } |
143 |
Built with git-ssb-web