Files: 2cf06eb4b4d0e4ac4b6f5dced90ef5da82a0a8fd / message / obs / webshares.js
2387 bytesRaw
1 | var nest = require('depnest') |
2 | var ref = require('ssb-ref') |
3 | var MutantArray = require('mutant/array') |
4 | var concat = require('mutant/concat') |
5 | |
6 | var { computed } = require('mutant') |
7 | |
8 | exports.needs = nest({ |
9 | 'message.sync.unbox': 'first', |
10 | 'backlinks.obs.for': 'first' |
11 | }) |
12 | |
13 | exports.gives = nest({ |
14 | 'sbot.hook.publish': true, |
15 | 'message.obs.webshares': true |
16 | }) |
17 | |
18 | |
19 | function isShare(c) { |
20 | if (c.type !== 'share') return false |
21 | |
22 | if (!c.share || !c.share.link || !ref.isMsg(c.share.link) || !c.share.hasOwnProperty('url')) { |
23 | return false |
24 | } |
25 | |
26 | return true |
27 | } |
28 | |
29 | |
30 | exports.create = function (api) { |
31 | var activeShares = new Set() |
32 | return nest({ |
33 | 'sbot.hook.publish': (msg) => { |
34 | if (!(msg && msg.value && msg.value.content)) return |
35 | if (typeof msg.value.content === 'string') { |
36 | msg = api.message.sync.unbox(msg) |
37 | if (!msg) return |
38 | } |
39 | |
40 | var c = msg.value.content |
41 | |
42 | if (!isShare(c)) return |
43 | |
44 | activeShares.forEach((shares) => { |
45 | if (shares.id === c.share.link) { |
46 | shares.push(msg) |
47 | } |
48 | }) |
49 | }, |
50 | 'message.obs.webshares': (id) => { |
51 | if (!ref.isLink(id)) throw new Error('an id must be specified') |
52 | var obs = get(id) |
53 | obs.id = id |
54 | var result = computed(obs, getShares, { |
55 | // allow manual append for simulated realtime |
56 | onListen: () => activeShares.add(obs), |
57 | onUnlisten: () => activeShares.delete(obs) |
58 | }) |
59 | result.sync = obs.sync |
60 | return result |
61 | } |
62 | }) |
63 | |
64 | function get(id) { |
65 | var backlinks = api.backlinks.obs.for(id) |
66 | var merge = MutantArray() |
67 | |
68 | var shares = computed([backlinks.sync, concat([backlinks, merge])], (sync, backlinks) => { |
69 | if (sync) { |
70 | return backlinks.reduce((result, msg) => { |
71 | var c = msg.value.content |
72 | if (isShare(c) && c.share.link === id) { |
73 | var value = result[msg.value.author] |
74 | if (!value || value[0] < msg.value.timestamp) { |
75 | result[msg.value.author] = [msg.value.timestamp, c.share.url] |
76 | } |
77 | } |
78 | return result |
79 | }, {}) |
80 | } else { |
81 | return {} |
82 | } |
83 | }) |
84 | |
85 | shares.push = merge.push |
86 | shares.sync = backlinks.sync |
87 | return shares |
88 | } |
89 | } |
90 | |
91 | function getShares(shares) { |
92 | return Object.keys(shares).reduce((result, id) => { |
93 | if (shares[id].length >= 1) { |
94 | result.push(id) |
95 | } |
96 | return result |
97 | }, []) |
98 | } |
Built with git-ssb-web