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