git ssb

2+

mixmix / ticktack



Commit dc5f4dc6989f09141fae9235f7690c01ebdc9e74

Merge pull request #146 from ticktackim/export-full

wip export side PR
Andre Alves Garzia authored on 5/28/2018, 1:38:49 AM
GitHub committed on 5/28/2018, 1:38:49 AM
Parent: 5d4d175f2895574c5670910407ca9436c1154f06
Parent: 2266bb60f9e3162b169687e66a63363af534ece5

Files changed

app/html/app.jschanged
ftu/app.jschanged
package-lock.jsonchanged
package.jsonchanged
ssb-server-ticktack.jschanged
app/html/app.jsView
@@ -1,6 +1,6 @@
11 const nest = require('depnest')
2-const { h, Value } = require('mutant')
2+const { h, Value, onceTrue } = require('mutant')
33
44 exports.gives = nest('app.html.app')
55
66 exports.needs = nest({
@@ -12,15 +12,17 @@
1212 'keys.sync.id': 'first',
1313 'router.sync.router': 'first',
1414 'settings.sync.get': 'first',
1515 'settings.sync.set': 'first',
16-
1716 'invite.async.autofollow': 'first',
1817 'config.sync.load': 'first',
1918 'sbot.async.friendsGet': 'first',
20- 'sbot.async.get': 'first'
19+ 'sbot.async.get': 'first',
20+ 'sbot.obs.connection': 'first' // EBT
2121 })
2222
23+var count = 0 // TODO - rm
24+
2325 exports.create = (api) => {
2426 var view
2527
2628 return nest({
@@ -33,12 +35,33 @@
3335 api.history.obs.location()(loc => console.log('location:', loc))
3436
3537 startApp()
3638
39+ onceTrue(api.sbot.obs.connection, server => getMySeq(server)) // EBT
40+
3741 return app
3842 }
3943 })
4044
45+ function getMySeq (server) {
46+ console.log('REMOVE THIS')
47+ // server.ebt.peerStatus(server.id, err, data) => {
48+ // server.latestSequence(server.id, (err, seq) => {
49+ // console.log(`${count} mins`)
50+ // count = count + 1
51+ // console.log('actual seq:', seq)
52+ // console.log(JSON.stringify(data, null, 2))
53+ // console.log('ticktack pubs', [
54+ // '@7xMrWP8708+LDvaJrRMRQJEixWYp4Oipa9ohqY7+NyQ=.ed25519',
55+ // '@MflVZCcOBOUe6BLrm/8TyirkTu9/JtdnIJALcd8v5bc=.ed25519'
56+ // ])
57+ // console.log('------------------')
58+ // })
59+ // })
60+
61+ // setTimeout(() => getMySeq(server), 60000)
62+ }
63+
4164 function renderLocation (loc) {
4265 var page = api.router.sync.router(loc)
4366 if (page) {
4467 view.set([
@@ -85,19 +108,25 @@
85108 console.log('no invites')
86109 return
87110 }
88111
89- var self_id = api.config.sync.load().keys.id
90- api.sbot.async.friendsGet({dest: self_id}, function (err, friends) {
91- // if you have less than 5 followers, maybe use the autoinvite
92- if (Object.keys(friends).length <= 5) {
93- invites.forEach(invite => {
94- console.log('using invite:', invite)
95- api.invite.async.autofollow(invite, (err, follows) => {
96- if (err) console.error('Autofollow error:', err)
97- else console.log('Autofollow success', follows)
98- })
112+ useInvites(invites)
113+ // TODO change it so that if you already have a bunch of friends you unfollow the pubs after they follow you?
114+
115+ // var myKey = api.config.sync.load().keys.id
116+ // api.sbot.async.friendsGet({dest: myKey}, function (err, friends) {
117+ // // if you have less than 5 followers, maybe use the autoinvite
118+ // if (Object.keys(friends).length <= 5) useInvites(invites)
119+ // else console.log('no autoinvite - you have friends already')
120+ // })
121+
122+ function useInvites (invites) {
123+ invites.forEach(invite => {
124+ console.log('using invite:', invite)
125+ api.invite.async.autofollow(invite, (err, follows) => {
126+ if (err) console.error('Autofollow error:', err)
127+ else console.log('Autofollow success', follows)
99128 })
100- } else { console.log('no autoinvite - you have friends already') }
101- })
129+ })
130+ }
102131 }
103132 }
ftu/app.jsView
@@ -4,34 +4,38 @@
44 const fs = require('fs')
55 const { remote } = require('electron')
66 const insertCss = require('insert-css')
77 const values = require('lodash/values')
8+const get = require('lodash/get')
89 const electron = require('electron')
910 const { dialog } = require('electron').remote
1011 const os = require('os')
12+const progress = require('progress-string')
13+
1114 const appName = process.env.SSB_APPNAME || 'ssb'
1215 const configFolder = path.join(os.homedir(), `.${appName}`)
1316
1417 var isBusy = Value(false)
1518 var isPresentingOptions = Value(true)
19+var checkerTimeout
1620
1721 // these initial values are overwritten by the identity file.
1822 var state = Struct({
1923 latestSequence: 0,
24+ confirmedRemotely: false,
2025 currentSequence: -1
2126 })
2227
2328 exports.gives = nest('ftu.app')
2429
2530 exports.needs = nest({
2631 'styles.css': 'reduce',
27- 'translations.sync.strings': 'first',
32+ 'translations.sync.strings': 'first'
2833 })
2934
3035 exports.create = (api) => {
3136 return nest({
32- 'ftu.app': function app() {
33-
37+ 'ftu.app': function app () {
3438 const strings = api.translations.sync.strings()
3539
3640 const css = values(api.styles.css()).join('\n')
3741 insertCss(css)
@@ -50,24 +54,35 @@
5054 when(isBusy, busyMessage, actionButtons)
5155 ])
5256 ])
5357
54- var importProcess = h('Page -ftu', [
58+ var importProgress = h('Page -ftu', [
5559 h('div.content', [
5660 h('h1', strings.backup.import.header),
57- h('p', [strings.backup.import.synchronizeMessage, state.currentSequence, '/', state.latestSequence]),
61+ h('p', [strings.backup.import.synchronizeMessage]),
62+ h('pre', computed(state, s => {
63+ return progress({
64+ width: 42,
65+ total: s.latestSequence,
66+ style: function (complete, incomplete) {
67+ // add an arrow at the head of the completed part
68+ return `${complete}>${incomplete} (${s.currentSequence}/ ${s.latestSequence})`
69+ }
70+ })(s.currentSequence)
71+ }))
5872 ])
5973 ])
6074
6175 // This watcher is responsible for switching from FTU to Ticktack main app
6276 watch(throttle(state, 500), s => {
63- if (s.currentSequence >= s.latestSequence) {
77+ if (s.currentSequence >= s.latestSequence && s.confirmedRemotely) {
6478 console.log('all imported')
79+ clearTimeout(checkerTimeout)
6580 electron.ipcRenderer.send('import-completed')
6681 }
6782 })
6883
69- if (fs.existsSync(path.join(configFolder, "secret"))) {
84+ if (fs.existsSync(path.join(configFolder, 'secret'))) {
7085 // somehow the FTU started but the identity is already in place.
7186 // treat it as a failed import and start importing...
7287 console.log('resuming import')
7388 let previousData = getImportData()
@@ -88,9 +103,9 @@
88103 var app = h('App', [
89104 h('Header', [
90105 windowControls()
91106 ]),
92- when(isPresentingOptions, initialOptions, importProcess)
107+ when(isPresentingOptions, initialOptions, importProgress)
93108 ])
94109
95110 return app
96111 }
@@ -102,27 +117,24 @@
102117
103118 observeSequence()
104119 })
105120
106-
107-
108-function actionCreateNewOne() {
121+function actionCreateNewOne () {
109122 isBusy.set(true)
110- const manifest = JSON.parse(fs.readFileSync(path.join(__dirname, "../manifest.json")))
123+ const manifest = JSON.parse(fs.readFileSync(path.join(__dirname, '../manifest.json')))
111124 const manifestFile = path.join(configFolder, 'manifest.json')
112125 if (!fs.existsSync(configFolder)) {
113126 fs.mkdirSync(configFolder)
114127 }
115128 fs.writeFileSync(manifestFile, JSON.stringify(manifest))
116129
117-
118130 electron.ipcRenderer.send('create-new-identity')
119131 }
120132
121-function actionImportIdentity(strings) {
122- const peersFile = path.join(configFolder, "gossip.json")
123- const secretFile = path.join(configFolder, "secret")
124- const manifest = JSON.parse(fs.readFileSync(path.join(__dirname, "../manifest.json")))
133+function actionImportIdentity (strings) {
134+ const peersFile = path.join(configFolder, 'gossip.json')
135+ const secretFile = path.join(configFolder, 'secret')
136+ const manifest = JSON.parse(fs.readFileSync(path.join(__dirname, '../manifest.json')))
125137 const manifestFile = path.join(configFolder, 'manifest.json')
126138
127139 // place the other files first
128140 dialog.showOpenDialog(
@@ -132,19 +144,19 @@
132144 defaultPath: 'ticktack-identity.backup',
133145 properties: ['openFile']
134146 },
135147 (filenames) => {
136- if (typeof filenames !== "undefined") {
148+ if (typeof filenames !== 'undefined') {
137149 let filename = filenames[0]
138150 let data = JSON.parse(fs.readFileSync(filename))
139- if (data.hasOwnProperty("secret") && data.hasOwnProperty("peers") && data.hasOwnProperty("latestSequence")) {
151+ if (data.hasOwnProperty('secret') && data.hasOwnProperty('peers') && data.hasOwnProperty('latestSequence')) {
140152 if (!fs.existsSync(configFolder)) {
141153 fs.mkdirSync(configFolder)
142154 }
143155
144156 fs.writeFileSync(manifestFile, JSON.stringify(manifest))
145- fs.writeFileSync(peersFile, JSON.stringify(data.peers), "utf8")
146- fs.writeFileSync(secretFile, data.secret, "utf8")
157+ fs.writeFileSync(peersFile, JSON.stringify(data.peers), 'utf8')
158+ fs.writeFileSync(secretFile, data.secret, 'utf8')
147159 state.latestSequence.set(data.latestSequence)
148160 state.currentSequence.set(0)
149161 isPresentingOptions.set(false)
150162
@@ -154,18 +166,18 @@
154166 setImportData(data)
155167
156168 electron.ipcRenderer.send('import-identity')
157169 } else {
158- console.log("> bad export file")
170+ console.log('> bad export file')
159171 console.log(data)
160- alert("Bad Export File")
172+ alert('Bad Export File')
161173 }
162174 }
163175 }
164176 )
165177 }
166178
167-function windowControls() {
179+function windowControls () {
168180 if (process.platform === 'darwin') return
169181
170182 const window = remote.getCurrentWindow()
171183 const minimize = () => window.minimize()
@@ -190,15 +202,13 @@
190202 })
191203 ])
192204 }
193205
194-
195-function assetPath(name) {
206+function assetPath (name) {
196207 return path.join(__dirname, '../assets', name)
197208 }
198209
199-
200-function getImportData() {
210+function getImportData () {
201211 var importFile = path.join(configFolder, 'importing.json')
202212 if (fs.existsSync(importFile)) {
203213 let data = JSON.parse(fs.readFileSync(importFile))
204214 return data || false
@@ -206,41 +216,83 @@
206216 return false
207217 }
208218 }
209219
210-function setImportData(data) {
220+function setImportData (data) {
211221 var importFile = path.join(configFolder, 'importing.json')
212222 fs.writeFileSync(importFile, JSON.stringify(data))
213223 }
214224
215-function observeSequence() {
225+function observeSequence () {
216226 const pull = require('pull-stream')
217227 const Client = require('ssb-client')
218228 const config = require('../config').create().config.sync.load()
219- const _ = require('lodash')
220229
221230 Client(config.keys, config, (err, ssbServer) => {
222- if (err) {
223- console.error('problem starting client', err)
224- } else {
225- console.log('> sbot running!!!!')
231+ if (err) return console.error('problem starting client', err)
226232
227- var feedSource = ssbServer.createUserStream({
228- live: true,
229- id: ssbServer.id
230- })
233+ console.log('> sbot running!!!!')
231234
232- var valueLogger = pull.drain((msg) => {
233- let seq = _.get(msg, "value.sequence", false)
235+ ssbServer.gossip.peers((err, peers) => {
236+ if (err) return console.error(err)
237+
238+ connectToPeers(peers)
239+ checkPeers()
240+ })
241+
242+ // start listening to the my seq, and update the state
243+ pull(
244+ ssbServer.createUserStream({ live: true, id: ssbServer.id }),
245+ pull.drain((msg) => {
246+ let seq = get(msg, 'value.sequence', false)
234247 if (seq) {
235248 state.currentSequence.set(seq)
236249 }
237250 })
251+ )
238252
239- pull(
240- feedSource,
241- valueLogger,
242- )
253+ function connectToPeers (peers) {
254+ if (peers.length > 10) {
255+ const lessPeers = peers.filter(p => !p.error)
256+ if (lessPeers.length > 10) peers = lessPeers
257+ }
243258
259+ peers.forEach(({ host, port, key }) => {
260+ if (host && port && key) {
261+ ssbServer.gossip.connect({ host, port, key }, (err, v) => {
262+ if (err) console.log('error connecting to ', host, err)
263+ else console.log('connected to ', host)
264+ })
265+ }
266+ })
244267 }
268+ function checkPeers () {
269+ ssbServer.ebt.peerStatus(ssbServer.id, (err, data) => {
270+ if (err) {
271+ checkerTimeout = setTimeout(checkPeers, 5000)
272+ return
273+ }
274+
275+ const latest = resolve(state.latestSequence)
276+
277+ const remoteSeqs = Object.keys(data.peers)
278+ .map(p => data.peers[p].seq) // get my seq reported by each peer
279+ .filter(s => s >= latest) // only keep remote seq that confirm or update backup seq
280+ .sort((a, b) => a > b ? -1 : 1) // order them
281+
282+ console.log(remoteSeqs)
283+
284+ const newLatest = remoteSeqs[0]
285+ if (newLatest) {
286+ state.latestSequence.set(newLatest)
287+
288+ // if this value is confirmed remotely twice, assume safe
289+ if (remoteSeqs.filter(s => s === newLatest).length >= 2) {
290+ state.confirmedRemotely.set(true)
291+ }
292+ }
293+
294+ checkerTimeout = setTimeout(checkPeers, 5000)
295+ })
296+ }
245297 })
246-}
298+}
package-lock.jsonView
The diff is too large to show. Use a local git client to view these changes.
Old file size: 289973 bytes
New file size: 290240 bytes
package.jsonView
@@ -49,8 +49,9 @@
4949 "patch-profile": "^1.0.4",
5050 "patch-settings": "^1.1.2",
5151 "patch-suggest": "^1.1.0",
5252 "patchcore": "^1.23.3",
53+ "progress-string": "^1.2.2",
5354 "pull-defer": "^0.2.2",
5455 "pull-next": "^1.0.1",
5556 "pull-next-step": "^1.0.0",
5657 "pull-obv": "^1.3.0",
@@ -65,9 +66,9 @@
6566 "ssb-backlinks": "^0.6.1",
6667 "ssb-blobs": "^1.1.4",
6768 "ssb-client": "4.5.2",
6869 "ssb-config": "^2.2.0",
69- "ssb-ebt": "^5.1.5",
70+ "ssb-ebt": "^5.2.0",
7071 "ssb-friends": "^2.3.5",
7172 "ssb-keys": "^7.0.10",
7273 "ssb-markdown": "^3.3.0",
7374 "ssb-mentions": "^0.4.0",
ssb-server-ticktack.jsView
@@ -191,9 +191,9 @@
191191 delete opts.limit
192192 // have to remove limit from the query otherwise Next stalls out if it doesn't get a new result
193193
194194 const _source = pull(
195- server.messagesByType(opts),
195+ server.messagesByType(opts), // TODO - check/ note why I didn't use e.g. readComments
196196 pull.filter(makeFilter(blogIds)),
197197 limit ? pull.take(limit) : true
198198 )
199199

Built with git-ssb-web