git ssb

2+

ev / mvd



Commit b7fa14294c552a418b5403b44385f0761fce9638

minimum viable decent

Ev Bogue committed on 4/20/2018, 4:56:34 AM

Files changed

.gitignoreadded
bin.jsadded
config.jsadded
index.jsadded
keys.jsadded
manifest.jsonadded
package-lock.jsonadded
package.jsonadded
render.jsadded
scuttlebot.jsadded
style.cssadded
style.css.jsonadded
style.jsadded
views.jsadded
.gitignoreView
@@ -1,0 +1,2 @@
1 +build
2 +node_modules
bin.jsView
@@ -1,0 +1,136 @@
1 +var fs = require('fs')
2 +var path = require('path')
3 +var ssbKeys = require('ssb-keys')
4 +var stringify = require('pull-stringify')
5 +var open = require('opn')
6 +var home = require('os-homedir')()
7 +var nonPrivate = require('non-private-ip')
8 +var muxrpcli = require('muxrpcli')
9 +
10 +var SEC = 1e3
11 +var MIN = 60*SEC
12 +
13 +var config = {
14 + name: 'ssb',
15 + host: nonPrivate.v4 || '',
16 + timeout: 0,
17 + local: 'true',
18 + port: 8008,
19 + path: path.join(home, '.ssb'),
20 + ws: { port: 8989 },
21 + caps: {
22 + shs: '1KHLiKZvAvjbY1ziZEHMXawbCEIM6qwjCDm3VYRan/s=',
23 + sign: null
24 + },
25 + friends: {
26 + dunbar: 150,
27 + hops: 3
28 + },
29 + gossip: {
30 + connections: 3
31 + },
32 + timers: {
33 + connection: 0,
34 + reconnect: 5*SEC,
35 + ping: 5*MIN,
36 + handshake: 5*SEC
37 + },
38 + master: [],
39 + party: true
40 +}
41 +
42 +config.keys = ssbKeys.loadOrCreateSync(path.join(config.path, 'secret'))
43 +
44 +var coraClient = fs.readFileSync(path.join('./build/index.html'))
45 +
46 +var manifestFile = path.join(config.path, 'manifest.json')
47 +
48 +var argv = process.argv.slice(2)
49 +var i = argv.indexOf('--')
50 +var conf = argv.slice(i+1)
51 +argv = ~i ? argv.slice(0, i) : argv
52 +
53 +if (argv[0] == 'server') {
54 +
55 + var createSbot = require('scuttlebot')
56 + .use(require('scuttlebot/plugins/master'))
57 + .use(require('scuttlebot/plugins/gossip'))
58 + .use(require('scuttlebot/plugins/replicate'))
59 + .use(require('ssb-friends'))
60 + .use(require('ssb-blobs'))
61 + .use(require('ssb-query'))
62 + .use(require('ssb-links'))
63 + .use(require('ssb-ebt'))
64 + .use(require('scuttlebot/plugins/invite'))
65 + .use(require('scuttlebot/plugins/local'))
66 + .use(require('decent-ssb/plugins/ws'))
67 + .use({
68 + name: 'serve',
69 + version: '1.0.0',
70 + init: function (sbot) {
71 + sbot.ws.use(function (req, res, next) {
72 + var send = {}
73 + send = config
74 + delete send.keys // very important to keep this, as it removes the server keys from the config before broadcast
75 + send.address = sbot.ws.getAddress()
76 + if(req.url == '/')
77 + res.end(coraClient)
78 + if(req.url == '/get-config')
79 + res.end(JSON.stringify(send))
80 + else next()
81 + })
82 + }
83 + })
84 +
85 + open('http://localhost:' + config.ws.port, {wait: false})
86 +
87 + var server = createSbot(config)
88 +
89 + fs.writeFileSync(manifestFile, JSON.stringify(server.getManifest(), null, 2))
90 +} else {
91 +
92 + var manifest
93 + try {
94 + manifest = JSON.parse(fs.readFileSync(manifestFile))
95 + } catch (err) {
96 + throw explain(err,
97 + 'no manifest file'
98 + + '- should be generated first time server is run'
99 + )
100 + }
101 +
102 + // connect
103 + require('ssb-client')(config.keys, {
104 + manifest: manifest,
105 + port: config.port,
106 + host: config.host||'localhost',
107 + caps: config.caps,
108 + key: config.key || config.keys.id
109 + }, function (err, rpc) {
110 + if(err) {
111 + if (/could not connect/.test(err.message)) {
112 + console.log('Error: Could not connect to the scuttlebot server.')
113 + console.log('Use the "server" command to start it.')
114 + if(config.verbose) throw err
115 + process.exit(1)
116 + }
117 + throw err
118 + }
119 +
120 + // add some extra commands
121 + manifest.version = 'async'
122 + manifest.config = 'sync'
123 + rpc.version = function (cb) {
124 + console.log(require('./package.json').version)
125 + cb()
126 + }
127 + rpc.config = function (cb) {
128 + console.log(JSON.stringify(config, null, 2))
129 + cb()
130 + }
131 +
132 + // run commandline flow
133 + muxrpcli(argv, manifest, rpc, config.verbose)
134 + })
135 +}
136 +
config.jsView
@@ -1,0 +1,24 @@
1 +var http = require('http')
2 +
3 +module.exports = function () {
4 + var host = window.location.origin
5 +
6 + http.get(host + '/get-config', function (res) {
7 + res.on('data', function (data, remote) {
8 + config = data
9 + localStorage[host] = config
10 + })
11 + })
12 +
13 + var config = JSON.parse(localStorage[host])
14 +
15 + config.blobsUrl = host + '/blobs/get/'
16 + config.emojiUrl = host + '/img/emoji/'
17 +
18 + if (config.ws.remote)
19 + config.remote = config.ws.remote
20 + else
21 + config.remote = config.address
22 +
23 + return config
24 +}
index.jsView
@@ -1,0 +1,17 @@
1 +var h = require('hyperscript')
2 +
3 +var views = require('./views')
4 +
5 +document.head.appendChild(h('style', require('./style.css.json')))
6 +
7 +var src = window.location.hash
8 +
9 +window.onhashchange = function () {
10 + window.location.reload()
11 +}
12 +
13 +if (src == '#raw') {
14 + views.rawstream()
15 +} else {
16 + views.logstream()
17 +}
keys.jsView
@@ -1,0 +1,6 @@
1 +
2 +var config = require('./config')()
3 +var ssbKeys = require('ssb-keys')
4 +var path = require('path')
5 +
6 +module.exports = ssbKeys.loadOrCreateSync(path.join(config.caps.shs + '/secret'))
manifest.jsonView
@@ -1,0 +1,74 @@
1 +{
2 + "auth": "async",
3 + "address": "sync",
4 + "manifest": "sync",
5 + "get": "async",
6 + "createFeedStream": "source",
7 + "createLogStream": "source",
8 + "messagesByType": "source",
9 + "createHistoryStream": "source",
10 + "createUserStream": "source",
11 + "links": "source",
12 + "relatedMessages": "async",
13 + "add": "async",
14 + "publish": "async",
15 + "getAddress": "sync",
16 + "getLatest": "async",
17 + "latest": "source",
18 + "latestSequence": "async",
19 + "whoami": "sync",
20 + "usage": "sync",
21 + "gossip": {
22 + "peers": "sync",
23 + "add": "sync",
24 + "ping": "duplex",
25 + "connect": "async",
26 + "changes": "source",
27 + "reconnect": "sync"
28 + },
29 + "friends": {
30 + "all": "async",
31 + "hops": "async",
32 + "createFriendStream": "source",
33 + "get": "sync"
34 + },
35 + "replicate": {
36 + "changes": "source"
37 + },
38 + "invite": {
39 + "create": "async",
40 + "accept": "async",
41 + "use": "async"
42 + },
43 + "block": {
44 + "isBlocked": "sync"
45 + },
46 + "private": {
47 + "publish": "async",
48 + "unbox": "sync"
49 + },
50 + "blobs": {
51 + "get": "source",
52 + "add": "sink",
53 + "ls": "source",
54 + "has": "async",
55 + "size": "async",
56 + "meta": "async",
57 + "want": "async",
58 + "push": "async",
59 + "changes": "source",
60 + "createWants": "source"
61 + },
62 + "links2": {
63 + "read": "source",
64 + "dump": "source"
65 + },
66 + "query": {
67 + "read": "source",
68 + "dump": "source"
69 + },
70 + "ws": {},
71 + "fulltext": {
72 + "search": "source"
73 + }
74 +}
package-lock.jsonView
The diff is too large to show. Use a local git client to view these changes.
Old file size: 0 bytes
New file size: 215241 bytes
package.jsonView
@@ -1,0 +1,42 @@
1 +{
2 + "name": "mvd",
3 + "version": "1.0.0",
4 + "description": "minimum viable decent",
5 + "main": "index.js",
6 + "scripts": {
7 + "start": "node bin server",
8 + "build": "node style.js && mkdir -p build && browserify index.js | indexhtmlify > build/index.html"
9 + },
10 + "devDependencies": {
11 + "browserify": "^14.5.0",
12 + "indexhtmlify": "^1.3.1"
13 + },
14 + "author": "Ev Bogue <ev@evbogue.com>",
15 + "license": "MIT",
16 + "dependencies": {
17 + "decent-ssb": "^4.3.0",
18 + "human-time": "0.0.1",
19 + "hyperloadmore": "^1.1.0",
20 + "hyperscript": "^2.0.2",
21 + "hyperscroll": "^1.0.0",
22 + "muxrpcli": "^1.1.0",
23 + "non-private-ip": "^1.4.3",
24 + "opn": "^5.3.0",
25 + "os-homedir": "^1.0.2",
26 + "patchapp-raw": "^1.0.1",
27 + "pull-more": "^1.1.0",
28 + "pull-reconnect": "0.0.3",
29 + "pull-stream": "^3.6.7",
30 + "pull-stringify": "^2.0.0",
31 + "scuttlebot": "^11.2.1",
32 + "ssb-blobs": "^1.1.4",
33 + "ssb-client": "^4.5.7",
34 + "ssb-ebt": "^5.1.5",
35 + "ssb-friends": "^2.4.0",
36 + "ssb-keys": "^7.0.14",
37 + "ssb-links": "^3.0.3",
38 + "ssb-markdown": "^3.6.0",
39 + "ssb-query": "^2.0.1",
40 + "ssb-ref": "^2.9.1"
41 + }
42 +}
render.jsView
@@ -1,0 +1,15 @@
1 +var h = require('hyperscript')
2 +
3 +var human = require('human-time')
4 +
5 +var markdown = require('ssb-markdown')
6 +
7 +module.exports = function (msg) {
8 + if (msg.value.content.type == 'post') {
9 + return h('div.message__content',
10 + h('span.timestamp', h('a', {href: msg.key}, human(new Date(msg.value.timestamp)))),
11 + msg.value.author,
12 + msg.value.content.text
13 + )
14 + } else { return }
15 +}
scuttlebot.jsView
@@ -1,0 +1,45 @@
1 +var pull = require('pull-stream')
2 +var ssbKeys = require('ssb-keys')
3 +var ref = require('ssb-ref')
4 +var reconnect = require('pull-reconnect')
5 +
6 +var config = require('./config')()
7 +var createClient = require('ssb-client')
8 +var keys = require('./keys')
9 +
10 +var CACHE = {}
11 +
12 +var rec = reconnect(function (isConn) {
13 + function notify (value) {
14 + isConn(value)
15 + }
16 +
17 + createClient(keys, {
18 + manifest: require('./manifest.json'),
19 + remote: config.remote,
20 + caps: config.caps
21 + }, function (err, _sbot) {
22 + if(err)
23 + return notify(err)
24 +
25 + sbot = _sbot
26 + sbot.on('closed', function () {
27 + sbot = null
28 + notify(new Error('closed'))
29 + })
30 +
31 + notify()
32 + })
33 +})
34 +
35 +module.exports = {
36 + createLogStream: rec.source(function (opts) {
37 + return pull(
38 + sbot.createLogStream(opts),
39 + pull.through(function (e) {
40 + CACHE[e.key] = CACHE[e.key] || e.value
41 + })
42 + )
43 + })
44 +}
45 +
style.cssView
@@ -1,0 +1,16 @@
1 +.hyperscroll {
2 + width: 100%;
3 +}
4 +
5 +.hyperscroll > .content {
6 + max-width: 680px;
7 + margin-left: auto;
8 + margin-right: auto;
9 +}
10 +
11 +
12 +.message {
13 + display: block;
14 + margin-top: .25em;
15 + margin-bottom: .25em;
16 +}
style.css.jsonView
@@ -1,0 +1,1 @@
1 +".hyperscroll {\n width: 100%;\n}\n\n.hyperscroll > .content {\n max-width: 680px;\n margin-left: auto;\n margin-right: auto;\n}\n\n\n.message {\n display: block;\n margin-top: .25em;\n margin-bottom: .25em;\n}\n"
style.jsView
@@ -1,0 +1,8 @@
1 +var fs = require('fs')
2 +var path = require('path')
3 +
4 +fs.writeFileSync(
5 + path.join(__dirname, 'style.css.json'),
6 + JSON.stringify(fs.readFileSync(path.join(__dirname, 'style.css'), 'utf8'))
7 +)
8 +
views.jsView
@@ -1,0 +1,71 @@
1 +var pull = require('pull-stream')
2 +var sbot = require('./scuttlebot')
3 +var hyperscroll = require('hyperscroll')
4 +var More = require('pull-more')
5 +var stream = require('hyperloadmore/stream')
6 +var h = require('hyperscript')
7 +var render = require('./render')
8 +
9 +module.exports.logstream = function () {
10 + var content = h('div.content')
11 +
12 + document.body.appendChild(h('div.screen',
13 + {style: {position: 'absolute', top: '0px', bottom: '0px', left: '0px', right: '0px'}},
14 + hyperscroll(content)
15 + ))
16 +
17 + function createStream (opts) {
18 + return pull(
19 + More(sbot.createLogStream, opts),
20 + pull.filter(function (data) {
21 + return 'string' === typeof data.value.content.text
22 + }),
23 + pull.map(function (msg) {
24 + return h('div.message', render(msg))
25 + })
26 + )
27 + }
28 +
29 + pull(
30 + createStream({old: false, limit: 100}),
31 + stream.top(content)
32 + )
33 +
34 + pull(
35 + createStream({reverse: true, live: false, limit: 100}),
36 + stream.bottom(content)
37 + )
38 +}
39 +
40 +var rawJSON = require('patchapp-raw/json')
41 +
42 +module.exports.rawstream = function () {
43 + var content = h('div.content')
44 +
45 + document.body.appendChild(h('div.screen',
46 + {style: {position: 'absolute', top: '0px', bottom: '0px', left: '0px', right: '0px'}},
47 + hyperscroll(content)
48 + ))
49 +
50 + function createStream (opts) {
51 + return pull(
52 + More(sbot.createLogStream, opts),
53 + pull.filter(function (data) {
54 + return 'string' === typeof data.value.content.text
55 + }),
56 + pull.map(function (msg) {
57 + return h('pre.raw__json', {id: msg.key}, rawJSON(msg))
58 + })
59 + )
60 + }
61 +
62 + pull(
63 + createStream({old: false, limit: 10}),
64 + stream.top(content)
65 + )
66 +
67 + pull(
68 + createStream({reverse: true, live: false, limit: 10}),
69 + stream.bottom(content)
70 + )
71 +}

Built with git-ssb-web