git ssb

1+

mixmix / scuttle-shell



Tree: 03e93a181a950f167f1950200f8137d21b89cbb2

Files: 03e93a181a950f167f1950200f8137d21b89cbb2 / server.js

6899 bytesRaw
1#! /usr/bin/env node
2
3const fs = require('fs')
4const path = require('path')
5const ssbKeys = require('ssb-keys')
6const minimist = require('minimist')
7const notifier = require('node-notifier')
8const SysTray = require('forked-systray').default
9
10// uninitialized
11let tray = null
12let ssbConfig = null
13
14function noop () {}
15
16function start (customConfig, donecb) {
17 donecb = donecb || noop
18 // TODO: try { allthethings } catch(e) { donecb(e) }
19 customConfig = customConfig || {}
20 let appname = customConfig.appname || false
21 let customPluginPaths = customConfig.plugins || false
22 let argv = process.argv.slice(2)
23 let i = argv.indexOf('--')
24 let conf = argv.slice(i + 1)
25 argv = ~i ? argv.slice(0, i) : argv
26 let ssbAppName = appname || process.env.ssb_appname
27
28 const config = require('ssb-config/inject')(ssbAppName, minimist(conf))
29
30 const keys = ssbKeys.loadOrCreateSync(path.join(config.path, 'secret'))
31 if (keys.curve === 'k256') {
32 // i think this is _really_ old and could be removed
33 throw new Error('k256 curves are no longer supported,' +
34 'please delete' + path.join(config.path, 'secret'))
35 }
36 config.keys = keys
37 ssbConfig = config
38
39 const manifestFile = path.join(config.path, 'manifest.json')
40
41 const createSbot = require('scuttlebot')
42 .use(require('scuttlebot/plugins/plugins'))
43 .use(require('scuttlebot/plugins/onion'))
44 .use(require('scuttlebot/plugins/unix-socket'))
45 .use(require('scuttlebot/plugins/no-auth'))
46 .use(require('scuttlebot/plugins/master'))
47 .use(require('scuttlebot/plugins/gossip'))
48 .use(require('scuttlebot/plugins/replicate'))
49 .use(require('scuttlebot/plugins/invite'))
50 .use(require('scuttlebot/plugins/local'))
51 .use(require('scuttlebot/plugins/logging'))
52 .use(require('ssb-about'))
53 .use(require('ssb-backlinks'))
54 .use(require('ssb-blobs'))
55 .use(require('ssb-chess-db'))
56 .use(require('ssb-ebt'))
57 .use(require('ssb-friends'))
58 .use(require('ssb-links')) // needed by patchfoo
59 .use(require('ssb-names'))
60 .use(require('ssb-meme'))
61 .use(require('ssb-ooo'))
62 .use(require('ssb-private'))
63 .use(require('ssb-query'))
64 .use(require('ssb-search'))
65 .use(require('ssb-tags'))
66 .use(require('ssb-talequery')) // only tale:net - close to obsolete %qJqQbvb8vLh5SUcSIlMeM2u0vt0M1RRaczb5NqH4tB8=.sha256
67 .use(require('ssb-threads'))
68 .use(require('ssb-unread'))
69 .use(require('ssb-ws'))
70
71 // load user plugins (from $HOME/.ssb/node_modules using $HOME/.ssb/config plugins {name:true})
72 require('scuttlebot/plugins/plugins').loadUserPlugins(createSbot, config)
73
74 // Custom plugins from json
75 let appManifestFile = path.resolve('scuttleshell.json')
76 if (fs.existsSync(appManifestFile)) {
77 let manifest = JSON.parse(fs.readFileSync(appManifestFile))
78 if (manifest.hasOwnProperty('plugins') && Array.isArray(manifest.plugins)) {
79 console.log('loading custom plugins: ', manifest.plugins.join(', '))
80 manifest.plugins.forEach(plugin => createSbot.use(require(plugin)))
81 }
82 }
83
84 // from customConfig.plugins
85 if (Array.isArray(customPluginPaths)) {
86 console.log('loading custom plugins: ', customPluginPaths.join(', '))
87 customPluginPaths.forEach(plugin => createSbot.use(require(plugin)))
88 }
89
90 // --extra-plugin
91 const args = minimist(process.argv.slice(1))
92 const extraPlugin = args['extra-plugin']
93 if (typeof extraPlugin === 'string') { // one
94 createSbot.use(require(extraPlugin))
95 } else if (extraPlugin instanceof Array) { // multiple
96 extraPlugin.forEach((plugPath) => createSbot.use(require(plugPath)))
97 }
98
99 // start server
100 const server = createSbot(config)
101
102 // write RPC manifest to ~/.ssb/manifest.json
103 fs.writeFileSync(manifestFile, JSON.stringify(server.getManifest(), null, 2))
104
105 const icon = fs.readFileSync(path.join(__dirname, `icon.${process.platform === 'win32' ? 'ico' : 'png'}`))
106 tray = new SysTray({
107 menu: {
108 icon: icon.toString('base64'),
109 title: 'Scuttle-Shell',
110 tooltip: 'Secure Scuttlebutt',
111 items: [
112 {
113 title: 'starting...',
114 checked: false,
115 enabled: true
116 },
117 {
118 title: 'version: unset',
119 checked: false,
120 enabled: false
121 },
122 {
123 title: 'Quit',
124 tooltip: 'Stop sbot and quit tray application',
125 checked: false,
126 enabled: true
127 }
128 ]
129 },
130 debug: false,
131 copyDir: true
132 })
133
134 tray.on('click', (action) => {
135 console.log('scuttle-shell got action:', action)
136 switch (action.item.title) {
137 case 'Quit':
138 console.log('### EXITING IN TWO SECONDS ###')
139
140 notifier.notify({
141 title: 'Secure Scuttlebutt',
142 message: `Secure Scuttlebutt will exit in two seconds...`,
143 icon: path.join(__dirname, 'icon.png'),
144 wait: true,
145 id: 0
146 })
147
148 tray.kill()
149 }
150 })
151
152 tray.on('exit', (code, signal) => {
153 console.log('scuttle-shell got exit:', code)
154 setTimeout(() =>
155 process.exit(0), 2000)
156 })
157
158 const sbotVersion = server.version()
159 console.log(`started sbot server v${sbotVersion}`)
160 tray.emit('action', {
161 type: 'update-item',
162 seq_id: 1,
163 item: {
164 title: `sbot version: ${sbotVersion}`,
165 checked: false,
166 enabled: false
167 }
168 })
169
170 server.about.get((err, curr) => {
171 if (err) {
172 console.warn('got err from about idx:', err)
173 return
174 }
175 // new key maybe? might not have set a name yet
176 if (typeof curr === 'undefined') {
177 return
178 }
179 const myAbouts = curr[ssbConfig.keys.id]
180 if (typeof myAbouts === 'undefined') {
181 return
182 }
183 const myNames = myAbouts['name']
184 if (typeof myNames === 'undefined') {
185 return
186 }
187 const fromMe = myNames[ssbConfig.keys.id]
188 if (fromMe instanceof Array && fromMe.length === 2) { // format is [ 'name', ts ]
189 tray.emit('action', {
190 type: 'update-item',
191 seq_id: 0,
192 item: {
193 title: `@${fromMe[0]}`,
194 tooltip: ssbConfig.keys.id,
195 checked: false,
196 enabled: false
197 }
198 })
199 }
200 })
201 donecb(null)
202}
203
204function stop () {
205 // todo: sbot shutdown handler?
206 tray.kill()
207}
208
209const getConfig = () => {
210 if (ssbConfig === null) {
211 return { type: 'error', msg: 'uninitialized config - call start() first' }
212 }
213 try {
214 const k = ssbConfig.keys
215 const manifest = JSON.parse(fs.readFileSync(path.join(ssbConfig.path, 'manifest.json')))
216 const remote = 'ws://localhost:8989~shs:' + k.id.substring(1, k.id.indexOf('.'))
217 return {
218 type: 'config',
219 keys: k,
220 manifest: manifest,
221 remote: remote
222 }
223 } catch (n) {
224 return { type: 'error', msg: n.message }
225 }
226}
227
228module.exports = { start, stop, getConfig }
229
230if (require.main === module) {
231 start({}, (err) => {
232 if (err) console.error(err)
233 })
234}
235

Built with git-ssb-web