git ssb

0+

Matt McKegg / ssb-backlinks



Tree: 2761a4d2dadc72d5445a4987705dd0822fde18cf

Files: 2761a4d2dadc72d5445a4987705dd0822fde18cf / index.js

2329 bytesRaw
1var FlumeQueryLinks = require('./lib/flumeview-links-raw')
2var ref = require('ssb-ref')
3var deepEqual = require('deep-equal')
4var extend = require('xtend')
5var matchChannel = /^#[^\s#]+$/
6var ssbKeys = require('ssb-keys')
7var toUrlFriendly = require('base64-url').escape
8
9var indexes = [
10 { key: 'DTS', value: [['dest'], ['timestamp']] },
11 { key: 'DTA', value: [['dest'], ['value', 'timestamp']] }, // asserted timestamp
12 { key: 'TDT', value: [['value', 'content', 'type'], ['dest'], ['value', 'timestamp']] }
13]
14
15var indexVersion = 3
16
17exports.name = 'backlinks'
18exports.version = require('./package.json').version
19exports.manifest = {
20 read: 'source'
21}
22
23exports.init = function (ssb, config) {
24 return ssb._flumeUse(
25 `backlinks-${toUrlFriendly(ssb.id.slice(1, 10))}`,
26 FlumeQueryLinks(indexes, extractLinks, indexVersion, unbox)
27 )
28
29 function unbox (msg) {
30 if (typeof msg.value.content === 'string') {
31 var value = unboxValue(msg.value)
32 if (value) {
33 return {
34 key: msg.key, value: value, timestamp: msg.timestamp
35 }
36 }
37 }
38 return msg
39 }
40
41 function unboxValue (value) {
42 var plaintext = null
43 try {
44 plaintext = ssbKeys.unbox(value.content, ssb.keys.private)
45 } catch (ex) {}
46 if (!plaintext) return null
47 return {
48 previous: value.previous,
49 author: value.author,
50 sequence: value.sequence,
51 timestamp: value.timestamp,
52 hash: value.hash,
53 content: plaintext,
54 private: true
55 }
56 }
57}
58
59function extractLinks (msg, emit) {
60 var links = new Set()
61 walk(msg.value.content, function (path, value) {
62 // HACK: handle legacy channel mentions
63 if (deepEqual(path, ['channel']) && typeof value === 'string' && value.length < 30) {
64 value = `#${value.replace(/\s/g, '')}`
65 }
66
67 // TODO: should add channel matching to ref.type
68 if (ref.type(value) || isChannel(value)) {
69 links.add(value)
70 }
71 })
72 links.forEach(link => {
73 emit(extend(msg, {
74 dest: link
75 }))
76 })
77}
78
79function isChannel (value) {
80 return typeof value === 'string' && value.length < 30 && matchChannel.test(value)
81}
82
83function walk (obj, fn, prefix) {
84 if (obj && typeof obj === 'object') {
85 for (var k in obj) {
86 walk(obj[k], fn, (prefix || []).concat(k))
87 }
88 } else {
89 fn(prefix, obj)
90 }
91}
92

Built with git-ssb-web