git ssb

0+

Dominic / yap-patch



Tree: cb2a914cb1b67be199e798ca44039444c43341fc

Files: cb2a914cb1b67be199e798ca44039444c43341fc / thread.js

5563 bytesRaw
1var pull = require('pull-stream')
2var ref = require('ssb-ref')
3var msum = require('markdown-summary')
4var sort = require('ssb-sort')
5var u = require('yap-util')
6
7var toUrl = u.toUrl
8
9function uniqueRecps (recps) {
10 if(!recps || !recps.length) return
11 recps = recps.map(function (e) {
12 return 'string' === typeof e ? e : e.link
13 })
14 .filter(Boolean)
15 return recps.filter(function (id, i) {
16 return !~recps.indexOf(id, i+1)
17 })
18}
19
20function getThread(sbot, id, cb) {
21 pull(
22 sbot.query.read({
23 //hack so that ssb-query filters on post but uses
24 //indexes for root.
25 query: [{$filter: {
26 value: { content: {root: id} }
27 }},{$filter: {
28 value: { content: {type: 'post'} }
29 }}]
30 }),
31 pull.collect(function (err, ary) {
32 if(err) return cb(err)
33 cb(null, ary)
34 })
35 )
36}
37
38function isObject(o) {
39 return o && 'object' === typeof o
40}
41var isArray = Array.isArray
42
43function backlinks (sbot, id, cb) {
44 var likes = [], backlinks = []
45 pull(
46 sbot.links({dest: id, values: true}),
47 pull.drain(function (e) {
48 var content = e.value.content
49 var vote = content.vote
50 if(isObject(vote) &&
51 vote.value == 1 && vote.link == id)
52 likes.push(e)
53 else if(content.type == 'post' && isArray(content.mentions)) {
54 for(var i in content.mentions) {
55 var m = content.mentions[i]
56 if(m && m.link == id) {
57 backlinks.push(e)
58 return //if something links twice, don't back link it twice
59 }
60 }
61 }
62 }, function () {
63 cb(null, likes, backlinks)
64 })
65 )
66}
67
68
69module.exports = function (sbot) {
70 return function (opts, apply, req) {
71 var context = req.cookies
72 var since = apply.since
73 var tr = require('./translations')(context.lang)
74 return function (cb) {
75 var cacheTime = 0
76 if(!ref.isMsg(opts.id))
77 return cb(new Error('expected valid msg id as id'))
78 sbot.get({id:opts.id, private: true}, function (err, msg) {
79 if(err) return cb(err)
80 var data = {key: opts.id, value: msg, timestamp: msg.timestamp || Date.now() }
81 if(data.value.content.root)
82 cb(null, apply('message', data)) //just show one message
83 else if(data.value.content.type != 'post')
84 cb(null, apply('message', data)) //just show one message
85 else
86 getThread(sbot, opts.id, function (err, ary) {
87 var root = opts.id
88 ary = [data].concat(ary || [])
89 var branch = sort.heads(ary)
90 var recps = uniqueRecps(ary[0].value.content.recps)
91
92 ary.unshift(data)
93 var o = {}, cacheTime
94 ary = ary.filter(function (e) {
95 if(o[e.key]) return false
96 return o[e.key] = true
97 })
98 sort(ary)
99 var recipients = ' '
100 if(ary[0].value.content.recps)
101 recipients = ['div.Recipients', tr('ThreadRecipients'),
102 ary[0].value.content.recps.map(function (e) {
103 return apply('avatar', e)
104 })]
105 cb(null,
106 ['div.thread',
107 apply.cacheAttrs(apply.toUrl('thread', opts), data.key, since),
108 ary[0].value.content.text && ['title', msum.title(ary[0].value.content.text)],
109 recipients,
110 ary.map(function (data) {
111 return ['div.MessageContainer',
112 apply('message', data),
113 function (cb) {
114 backlinks(sbot, data.key, function (err, likes, backlinks) {
115 if(err) return cb(err)
116
117 var expression = tr('Like')
118 cb(null, ['div.MessageExtra',
119 apply('publish', {
120 id: context.id,
121 suggestedRecps: data.value.author,
122 content: {
123 type: 'vote',
124 root: root, branch: branch,
125 vote: {
126 link:data.key, value: 1,
127 expression: expression
128 },
129 channel: data.value.content.channel,
130 recps: recps
131 },
132 name: expression + ' ' + (likes.length ? '('+likes.length+')' : '')
133 }),
134 (backlinks.length ?
135 ['ul.MessageBacklinks',
136 backlinks.map(function (e) {
137 return ['li', apply('avatar', {id:e.value.author}),
138 ' ',
139 apply('/patch/messageLink', e),
140 ' ',
141 e.value.content.channel && apply('/patch/channelLink', e.value.content.channel)
142 ]
143 })
144 ] : '')
145 ])
146 })
147 }
148 ]
149 }),
150 apply('compose', {
151 content: {
152 type: 'post',
153 root: root,
154 recps: recps,
155 branch: branch,
156 channel: ary[0].value.content.channel
157 }
158 })
159 ]
160 )
161 })
162 })
163 }
164 }
165}
166

Built with git-ssb-web