-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathlistener.js
126 lines (114 loc) · 3.21 KB
/
listener.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
const hypercore = require('hypercore')
const hyperdiscovery = require('hyperdiscovery')
const fs = require('fs')
const path = require('path')
const homedir = require('os').homedir()
const remoteChatDirectory = path.resolve(homedir, './hyperchats/remote')
class Listener {
constructor (key, receiver) {
this.swarm = undefined
this.name = undefined
try {
fs.statSync(remoteChatDirectory)
} catch (e) {
fs.mkdirSync(remoteChatDirectory)
}
this.receiver = receiver
this.feed = hypercore(path.join(remoteChatDirectory, key), key, { valueEncoding: 'json', sparse: true, live: true })
this.feed.on('ready', () => this.connect())
this.feed.on('error', e => console.error('feed error:', e))
this.lastVersion = undefined
// start listening to append messages
this.feed.on('append', this._newData.bind(this))
}
get key () {
return this.feed.key.toString('hex')
}
connect () {
console.log('Listening to:', this.key)
const archive = this.feed
const receiver = this.receiver.feed
this.swarm = hyperdiscovery(this.feed, {
stream: function (peer) {
const stream = archive.replicate({
live: true,
upload: true,
download: true,
userData: receiver.key
})
stream.on('handshake', () => {
console.log('HANDSHAKE LISTENER', stream.remoteUserData.toString('hex'))
})
return stream
}
})
this.swarm.once('connection', () => {
this.lastVersion = this.feed.length
this.receiver.emit('listening', { key: this.key })
this.feed.get(0, this._setName.bind(this))
this._update()
})
}
_setName (err, data) {
if (err) throw err
this.name = data.name || this.key
}
_update () {
this.feed.update(() => {
this.lastVersion = this.feed.length
this._update()
})
}
_newData () {
const last = this.lastVersion || 0
const newest = this.feed.length
if (newest > last) {
this.lastVersion = newest
this.feed.download({start: last, end: newest}, () => {
for (var i = last; i < newest; i++) {
const index = i
this.feed.get(
index,
{wait: false, valueEncoding: 'json'},
(err, data) => this._gotMessage(err, data, index)
)
}
})
}
}
_gotMessage (err, data, index) {
if (err) throw err
if (data.msg) {
this.receiver.emit('message', {
name: this.name,
message: data.msg,
time: data.time,
index
})
this.receiver.heard(this.discoveryKey, index)
}
switch (data.status) {
case 'START':
this.receiver.emit('started', { name: this.name })
break
case 'END':
this.receiver.emit('ended', { name: this.name })
break
case 'HEARD':
const who = data.heard === this.discoveryKey ? 'you' : data.heard
this.receiver.emit('heard', {name: this.name, who, index: data.index})
break
}
}
disconnect (cb) {
if (this.swarm) {
this._destroy(cb)
}
}
_destroy (cb) {
this.swarm.leave(this.feed.discoveryKey)
this.swarm.destroy(cb)
this.swarm = undefined
}
}
module.exports = Listener