git ssb

10+

Matt McKegg / patchwork



Tree: 13be5ee9906beb5d8c2a24db46c68ef183c78d3a

Files: 13be5ee9906beb5d8c2a24db46c68ef183c78d3a / lib / feed-summary.js

4172 bytesRaw
1var pull = require('pull-stream')
2var pullPushable = require('pull-pushable')
3var pullNext = require('pull-next')
4var SortedArray = require('sorted-array-functions')
5
6module.exports = FeedSummary
7
8function FeedSummary (source, windowSize, cb) {
9 var last = null
10 var returned = false
11 var done = false
12 return pullNext(() => {
13 if (!done) {
14 var next = {reverse: true, limit: windowSize || 1000, live: false}
15 if (last) {
16 next.lt = last.timestamp || last.value.sequence
17 }
18 var pushable = pullPushable()
19 pull(
20 source(next),
21 pull.collect((err, values) => {
22 if (err) throw err
23 if (!values.length) {
24 done = true
25 } else {
26 groupMessages(values).forEach(v => pushable.push(v))
27 last = values[values.length - 1]
28 }
29 pushable.end()
30 if (!returned) cb && cb()
31 returned = true
32 })
33 )
34 }
35 return pushable
36 })
37}
38
39function groupMessages (messages, filter) {
40 var follows = {}
41 var messageUpdates = {}
42 reverseForEach(messages, function (msg) {
43 if (!msg.value) return
44 var c = msg.value.content
45 if (c.type === 'contact') {
46 updateContact(msg, follows)
47 } else if (c.type === 'vote') {
48 if (c.vote && c.vote.link) {
49 // only show digs of posts added in the current window
50 // and only for the main post
51 const group = messageUpdates[c.vote.link]
52 if (group) {
53 if (c.vote.value > 0) {
54 group.lastUpdateType = 'dig'
55 group.digs.add(msg.value.author)
56 group.updated = msg.timestamp
57 } else {
58 group.digs.delete(msg.value.author)
59 if (group.lastUpdateType === 'dig' && !group.digs.size && !group.replies.length) {
60 group.lastUpdateType = 'reply'
61 }
62 }
63 }
64 }
65 } else {
66 if (c.root) {
67 const group = ensureMessage(c.root, messageUpdates)
68 group.lastUpdateType = 'reply'
69 group.repliesFrom.add(msg.value.author)
70 //SortedArray.add(group.replies, msg, compareUserTimestamp)
71 group.replies.push(msg)
72 group.channel = group.channel || msg.value.content.channel
73 group.updated = msg.timestamp
74 } else {
75 const group = ensureMessage(msg.key, messageUpdates)
76 group.lastUpdateType = 'post'
77 group.updated = msg.timestamp
78 group.author = msg.value.author
79 group.channel = msg.value.content.channel
80 group.message = msg
81 }
82 }
83 })
84
85 var result = []
86 Object.keys(follows).forEach((key) => {
87 SortedArray.add(result, follows[key], compareUpdated)
88 })
89 Object.keys(messageUpdates).forEach((key) => {
90 SortedArray.add(result, messageUpdates[key], compareUpdated)
91 })
92 return result
93}
94
95function compareUserTimestamp (a, b) {
96 return a.value.timestamp - b.value.timestamp
97}
98
99function compareUpdated (a, b) {
100 return b.updated - a.updated
101}
102
103function reverseForEach (items, fn) {
104 var i = items.length - 1
105 var start = Date.now()
106 nextBatch()
107
108 function nextBatch () {
109 while (i >= 0 && Date.now() - start < 10) {
110 fn(items[i], i)
111 i -= 1
112 }
113
114 if (i > 0) {
115 setImmediate(nextBatch)
116 }
117 }
118}
119
120function updateContact (msg, groups) {
121 var c = msg.value.content
122 var id = msg.value.author
123 var group = groups[id]
124 if (c.contact) {
125 if (c.following) {
126 if (!group) {
127 group = groups[id] = {
128 type: 'follow',
129 lastUpdateType: null,
130 contacts: new Set(),
131 updated: 0,
132 author: id,
133 id: id
134 }
135 }
136 group.contacts.add(c.contact)
137 group.updated = msg.timestamp
138 } else {
139 if (group) {
140 group.contacts.delete(c.contact)
141 if (!group.contacts.size) {
142 delete groups[id]
143 }
144 }
145 }
146 }
147}
148
149function ensureMessage (id, groups) {
150 var group = groups[id]
151 if (!group) {
152 group = groups[id] = {
153 type: 'message',
154 repliesFrom: new Set(),
155 replies: [],
156 message: null,
157 messageId: id,
158 digs: new Set(),
159 updated: 0
160 }
161 }
162 return group
163}
164

Built with git-ssb-web