This repository was archived by the owner on Feb 14, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathkodi.js
105 lines (89 loc) · 2.49 KB
/
kodi.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
const WebSocket = require('ws')
const { EventEmitter } = require('events')
const options = {
host: 'localhost',
port: 9090,
reconnect: false,
reconnectSleep: 3000,
connectionTimeout: 10000,
sendTimeout: 3000
}
const kodi = new EventEmitter()
let jsonrpcId = 0
let socket
const sentRequests = Object.create(null)
kodi.setOptions = opts => {
if (opts === undefined) return
Object.entries(opts).forEach(([ key, value ]) => {
options[key] = value
})
}
kodi.close = opts => {
kodi.setOptions(opts)
socket.close()
}
kodi.connect = opts => {
kodi.setOptions(opts)
socket = new WebSocket(`ws://${options.host}:${options.port}/jsonrpc`)
const connectionTimeout = setTimeout(() => {
kodi.emit('error', new Error('Was not able to connect before reaching timeout.'))
setTimeout(() => socket.terminate(), 1)
}, options.connectionTimeout)
socket.on('open', () => {
clearTimeout(connectionTimeout)
kodi.emit('connect')
})
socket.on('close', () => {
kodi.emit('close')
if (options.reconnect) {
setTimeout(() => {
kodi.connect(options)
}, options.reconnectSleep)
}
})
socket.on('error', error => kodi.emit('error', error))
socket.on('message', message => {
let data
try {
data = JSON.parse(message)
if (data.id && sentRequests[data.id] === undefined) {
throw new Error(`Message for unknown id received.`)
}
} catch (error) {
kodi.emit('error', error)
return
}
const { id, method, params } = data
if (id && sentRequests[id]) {
sentRequests[id](data)
} else {
kodi.emit(method, params)
kodi.emit('notification', { method, params })
}
})
}
kodi.send = (method, params) =>
new Promise((resolve, reject) => {
if (socket.readyState !== WebSocket.OPEN) {
return reject(new Error('Failed to send message. No connection to kodi.'))
}
const message = { jsonrpc: '2.0', method, params, id: (jsonrpcId += 1) }
socket.send(JSON.stringify(message), error => {
if (error) {
return reject(error)
}
const timeout = setTimeout(() => {
reject(new Error('Failed to send message. No response within timeout.'))
delete sentRequests[message.id]
}, options.sendTimeout)
sentRequests[message.id] = ({ id, error, result }) => {
clearTimeout(timeout)
delete sentRequests[id]
if (error) {
return reject(error)
}
resolve(result)
}
})
})
module.exports = kodi