Files: dca7b4f2e6012767054e42e07ff8ea31ea0b501c / about / obs.js
3929 bytesRaw
1 | var {Value, computed} = require('mutant') |
2 | var pull = require('pull-stream') |
3 | var nest = require('depnest') |
4 | var ref = require('ssb-ref') |
5 | var colorHash = new (require('color-hash'))() |
6 | var fallbackImageUrl = 'data:image/gif;base64,R0lGODlhAQABAPAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==' |
7 | |
8 | exports.needs = nest({ |
9 | 'sbot.pull.stream': 'first', |
10 | 'blob.sync.url': 'first', |
11 | 'keys.sync.id': 'first' |
12 | }) |
13 | |
14 | exports.gives = nest({ |
15 | 'about.obs': [ |
16 | 'name', |
17 | 'description', |
18 | 'image', |
19 | 'imageUrl', |
20 | 'names', |
21 | 'images', |
22 | 'color', |
23 | 'value', |
24 | 'values' |
25 | ] |
26 | }) |
27 | |
28 | exports.create = function (api) { |
29 | var sync = Value(false) |
30 | var cache = null |
31 | |
32 | return nest({ |
33 | 'about.obs': { |
34 | // quick helpers, probably should deprecate! |
35 | name: (id) => value(id, 'name', id.slice(1, 10)), |
36 | description: (id) => value(id, 'description'), |
37 | image: (id) => value(id, 'image'), |
38 | names: (id) => values(id, 'name'), |
39 | images: (id) => values(id, 'images'), |
40 | color: (id) => computed(id, (id) => colorHash.hex(id)), |
41 | imageUrl: (id) => computed(value(id, 'image'), (blobId) => { |
42 | return blobId ? api.blob.sync.url(blobId) : fallbackImageUrl |
43 | }), |
44 | |
45 | // custom abouts (the future!) |
46 | value, |
47 | values |
48 | } |
49 | }) |
50 | |
51 | function value (id, key, defaultValue) { |
52 | if (!ref.isLink(id)) throw new Error('About requires an ssb ref!') |
53 | var yourId = api.keys.sync.id() |
54 | return computed([get(id), key, id, yourId, defaultValue], socialValue) |
55 | } |
56 | |
57 | function values (id, key) { |
58 | if (!ref.isLink(id)) throw new Error('About requires an ssb ref!') |
59 | return computed([get(id), 'name'], allValues) |
60 | } |
61 | |
62 | function get (id) { |
63 | if (!ref.isLink(id)) throw new Error('About requires an ssb ref!') |
64 | load() |
65 | if (!cache[id]) { |
66 | cache[id] = Value({}) |
67 | } |
68 | return cache[id] |
69 | } |
70 | |
71 | function load () { |
72 | if (!cache) { |
73 | cache = {} |
74 | pull( |
75 | api.sbot.pull.stream(sbot => sbot.about.stream({live: true})), |
76 | pull.drain(item => { |
77 | for (var target in item) { |
78 | var state = get(target) |
79 | var lastState = state() |
80 | var values = item[target] |
81 | var changed = false |
82 | for (var key in values) { |
83 | var valuesForKey = lastState[key] = lastState[key] || {} |
84 | for (var author in values[key]) { |
85 | var value = values[key][author] |
86 | if (!valuesForKey[author] || value[1] > valuesForKey[author][1]) { |
87 | valuesForKey[author] = value |
88 | changed = true |
89 | } |
90 | } |
91 | } |
92 | if (changed) { |
93 | state.set(lastState) |
94 | } |
95 | } |
96 | |
97 | if (!sync()) { |
98 | sync.set(true) |
99 | } |
100 | }) |
101 | ) |
102 | } |
103 | } |
104 | } |
105 | |
106 | function socialValue (lookup, key, id, yourId, fallback) { |
107 | var result = lookup[key] ? getValue(lookup[key][yourId]) || getValue(lookup[key][id]) || highestRank(lookup[key]) : null |
108 | if (result != null) { |
109 | return result |
110 | } else { |
111 | return fallback || null |
112 | } |
113 | } |
114 | |
115 | function allValues (lookup, key) { |
116 | var values = {} |
117 | for (var author in lookup[key]) { |
118 | var value = getValue(lookup[key][author]) |
119 | if (value != null) { |
120 | values[value] = values[value] || [] |
121 | values[value].push(author) |
122 | } |
123 | } |
124 | return values |
125 | } |
126 | |
127 | function highestRank (lookup) { |
128 | var counts = {} |
129 | var highestCount = 0 |
130 | var currentHighest = null |
131 | for (var key in lookup) { |
132 | var value = getValue(lookup[key]) |
133 | if (value != null) { |
134 | counts[value] = (counts[value] || 0) + 1 |
135 | if (counts[value] > highestCount) { |
136 | currentHighest = value |
137 | highestCount = counts[value] |
138 | } |
139 | } |
140 | } |
141 | return currentHighest |
142 | } |
143 | |
144 | function getValue (item) { |
145 | if (item && item[0]) { |
146 | if (typeof item[0] === 'string') { |
147 | return item[0] |
148 | } else if (item[0] && item[0].link && ref.isLink(item[0].link)) { |
149 | return item[0].link |
150 | } |
151 | } |
152 | } |
153 |
Built with git-ssb-web