git ssb

1+

Daan Patchwork / patchwork



Tree: 000777db8b0f37f6c1d99fc608e4395c87512348

Files: 000777db8b0f37f6c1d99fc608e4395c87512348 / lib / plugins / mentions-feed.js

3682 bytesRaw
1'use strict'
2const pull = require('pull-stream')
3const HLRU = require('hashlru')
4const extend = require('xtend')
5const pullResume = require('../pull-resume')
6const threadSummary = require('../thread-summary')
7const LookupRoots = require('../lookup-roots')
8const ResolveAbouts = require('../resolve-abouts')
9const UniqueRoots = require('../unique-roots')
10const Paramap = require('pull-paramap')
11const FilterBlocked = require('../filter-blocked')
12
13exports.manifest = {
14 latest: 'source',
15 roots: 'source'
16}
17
18exports.init = function (ssb) {
19 // cache mostly just to avoid reading the same roots over and over again
20 // not really big enough for multiple refresh cycles
21 const cache = HLRU(100)
22
23 return {
24 latest: function () {
25 const query = [{
26 $filter: {
27 dest: ssb.id
28 }
29 }]
30 return pull(
31 ssb.backlinks.read({ query, live: true, old: false }),
32 pull.filter(bumpFilter),
33 LookupRoots({ ssb, cache })
34 )
35
36 function bumpFilter (msg) {
37 return checkBump(msg, { id: ssb.id })
38 }
39 },
40 roots: function ({ reverse, limit, resume }) {
41 const filter = {
42 dest: ssb.id
43 }
44
45 // use resume option if specified
46 if (resume) {
47 filter.timestamp = reverse ? { $lt: resume } : { $gt: resume }
48 }
49
50 const opts = {
51 reverse,
52 old: true,
53 index: 'DTS',
54 query: [
55 { $filter: filter }
56 ]
57 }
58
59 return pullResume.source(ssb.backlinks.read(opts), {
60 limit,
61 getResume: (item) => {
62 return item.timestamp
63 },
64 filterMap: pull(
65 // CHECK IF IS MENTION
66 pull.filter(bumpFilter),
67
68 // LOOKUP AND ADD ROOTS
69 LookupRoots({ ssb, cache }),
70
71 // FILTER BLOCKED (don't bump if author blocked, don't include if root author blocked)
72 FilterBlocked([ssb.id], {
73 isBlocking: ssb.patchwork.contacts.isBlocking,
74 useRootAuthorBlocks: true,
75 checkRoot: true
76 }),
77
78 // DON'T REPEAT THE SAME THREAD
79 UniqueRoots(),
80
81 // MAP ROOT ITEMS
82 pull.map(item => {
83 const root = item.root || item
84 return root
85 }),
86
87 // RESOLVE ROOTS WITH ABOUTS
88 ResolveAbouts({ ssb }),
89
90 // ADD THREAD SUMMARY
91 Paramap((item, cb) => {
92 threadSummary(item.key, {
93 recentLimit: 3,
94 readThread: ssb.patchwork.thread.read,
95 bumpFilter,
96 recentFilter: bumpFilter,
97 pullFilter: FilterBlocked([ssb.id], { isBlocking: ssb.patchwork.contacts.isBlocking })
98 }, (err, summary) => {
99 if (err) return cb(err)
100 cb(null, extend(item, summary, {
101 filterResult: undefined,
102 rootBump: bumpFilter(item)
103 }))
104 })
105 }, 10)
106 )
107 })
108
109 function bumpFilter (msg) {
110 return checkBump(msg, { id: ssb.id })
111 }
112 }
113 }
114}
115
116function checkBump (msg, { id }) {
117 if (msg && msg.value && msg.value.author !== id) {
118 if (Array.isArray(msg.value.content.mentions) && msg.value.content.mentions.some(mention => {
119 return mention && mention.link === id
120 })) {
121 return 'mention'
122 } else if (msg.value.content.type === 'contact' && msg.value.content.following === true && msg.value.content.contact === id) {
123 return 'follow'
124 }
125 // private gathering invite
126 if (msg.value.content.type === 'gathering' && Array.isArray(msg.value.content.recps) && msg.value.content.recps.includes(id)) {
127 return 'invite'
128 }
129 }
130}
131

Built with git-ssb-web