git ssb

7+

dinoworm ๐Ÿ› / patchcore



Tree: 06f2cf64aba94839fa02b58ea578954fba561c5d

Files: 06f2cf64aba94839fa02b58ea578954fba561c5d / about / obs.js

5257 bytesRaw
1var {Value, Struct, Dict, computed} = require('mutant')
2var pullPause = require('pull-pause')
3var pull = require('pull-stream')
4var msgs = require('ssb-msgs')
5var nest = require('depnest')
6var ref = require('ssb-ref')
7var colorHash = new (require('color-hash'))()
8
9exports.needs = nest({
10 'sbot.pull.query': 'first',
11 'blob.sync.url': 'first',
12 'keys.sync.id': 'first'
13})
14exports.gives = nest({
15 'about.obs': [
16 'name',
17 'description',
18 'image',
19 'imageUrl',
20 'names',
21 'images',
22 'color'
23 ],
24 'sbot.hook.feed': true
25})
26
27exports.create = function (api) {
28 var sync = Value(false)
29 var cache = {}
30 var cacheLoading = false
31
32 return nest({
33 'about.obs': {
34 name: (id) => get(id).displayName,
35 description: (id) => get(id).description,
36 image: (id) => get(id).image,
37 imageUrl: (id) => get(id).imageUrl,
38
39 names: (id) => get(id).names,
40 images: (id) => get(id).images,
41 color: (id) => computed(id, (id) => colorHash.hex(id))
42 },
43 'sbot.hook.feed': function (msg) {
44 if (isAbout(msg) && msg.timestamp) {
45 var target = msg.value.content.about
46 var from = cache[target]
47 if (from) {
48 from.push({
49 author: msg.value.author,
50 timestamp: msg.timestamp,
51 name: msg.value.content.name,
52 image: msg.value.content.image,
53 description: msg.value.content.description
54 })
55 }
56 }
57 }
58 })
59
60 function get (id) {
61 if (!cacheLoading) {
62 cacheLoading = true
63 loadCache()
64 }
65 if (!cache[id]) {
66 cache[id] = About(api, id, sync)
67 }
68 return cache[id]
69 }
70
71 function loadCache () {
72 pull(
73 api.sbot.pull.query({
74 query: [
75 {$filter: {
76 value: {
77 content: {
78 type: 'about'
79 }
80 }
81 }},
82 {$map: {
83 timestamp: 'timestamp',
84 author: ['value', 'author'],
85 id: ['value', 'content', 'about'],
86 name: ['value', 'content', 'name'],
87 image: ['value', 'content', 'image'],
88 description: ['value', 'content', 'description']
89 }}
90 ],
91 live: true
92 }),
93 pull.drain(
94 msg => {
95 if (msg.sync) {
96 sync.set(true)
97 } else if (msgs.isLink(msg.id, 'feed')) {
98 get(msg.id).push(msg)
99 }
100 },
101 () => sync.set(true)
102 )
103 )
104 }
105}
106
107function About (api, id, sync) {
108 if (!ref.isLink(id)) throw new Error('About requires an id!')
109
110 var pauser = pullPause((paused) => {})
111
112 // transparent image
113 var fallbackImageUrl = 'data:image/gif;base64,R0lGODlhAQABAPAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='
114
115 var yourId = api.keys.sync.id()
116 var lastestTimestamps = {}
117
118 var obs = Struct({
119 assignedNames: Dict(),
120 assignedImages: Dict(),
121 assignedDescriptions: Dict()
122 }, {
123 onListen: pauser.resume,
124 onUnlisten: pauser.pause
125 })
126
127 obs.sync = computed([sync, obs], (v) => v)
128 obs.displayName = computed([obs.assignedNames, id, yourId, id.slice(1, 10)], socialValue)
129 obs.description = computed([obs.assignedDescriptions, id, yourId], socialValue)
130 obs.image = computed([obs.assignedImages, id, yourId], socialValue)
131
132 obs.names = computed(obs.assignedNames, indexByValue)
133 obs.images = computed(obs.assignedImages, indexByValue)
134
135 obs.imageUrl = computed(obs.image, (blobId) => {
136 if (blobId) {
137 return api.blob.sync.url(blobId)
138 } else {
139 return fallbackImageUrl
140 }
141 })
142
143 obs.push = push
144
145 return obs
146
147 // scoped
148
149 function push (msg) {
150 if (!lastestTimestamps[msg.author]) {
151 lastestTimestamps[msg.author] = {
152 name: 0, image: 0, description: 0
153 }
154 }
155 if (msg.name && lastestTimestamps[msg.author].name < msg.timestamp) {
156 lastestTimestamps[msg.author].name = msg.timestamp
157 obs.assignedNames.put(msg.author, msg.name)
158 }
159 if (msg.image && lastestTimestamps[msg.author].image < msg.timestamp) {
160 lastestTimestamps[msg.author].image = msg.timestamp
161 var obj = msgs.link(msg.image, 'blob')
162 if (obj && obj.link) {
163 obs.assignedImages.put(msg.author, obj.link)
164 }
165 }
166 if (msg.description && lastestTimestamps[msg.author].description < msg.timestamp) {
167 lastestTimestamps[msg.author].description = msg.timestamp
168 obs.assignedDescriptions.put(msg.author, msg.description)
169 }
170 }
171}
172
173function socialValue (lookup, id, yourId, fallback) {
174 return lookup[yourId] || lookup[id] || highestRank(lookup) || fallback || null
175}
176
177function highestRank (lookup) {
178 var indexed = indexByValue(lookup)
179 var highestCount = 0
180 var currentHighest = null
181 Object.keys(indexed).forEach((item) => {
182 var count = indexed[item].length
183 if (count > highestCount) {
184 highestCount = count
185 currentHighest = item
186 }
187 })
188 return currentHighest
189}
190
191function indexByValue (lookup) {
192 var result = {}
193 Object.keys(lookup).forEach((key) => {
194 var value = lookup[key]
195 if (!result[value]) {
196 result[value] = []
197 }
198 result[value].push(key)
199 })
200 return result
201}
202
203function isAbout (msg) {
204 return msg.value && msg.value.content && msg.value.content.type === 'about'
205}
206

Built with git-ssb-web