-
Notifications
You must be signed in to change notification settings - Fork 1
/
feed-client.js
153 lines (124 loc) · 4.26 KB
/
feed-client.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import * as braid from 'https://esm.sh/braid-http?~1.1'
var feed = [],
posts = {},
curr_version,
peer = Math.random().toString(36).substr(3)
async function subscribe_to_feed (url, cb) {
var retry = () => setTimeout(() => subscribe_to_feed(url, cb), 3000)
// Do the initial fetch
try {
var res = await braid.fetch(url, {subscribe: true, parents: curr_version, peer})
console.log('Got res! subscribe is', res.headers.get('subscribe'))
// Server might support subscriptions
if (res.headers.has('subscribe'))
res.subscribe(patch_feed, retry)
// Else just do polling
else {
// Incorporate this update we got
patch_feed({
version: res.version,
body: await res.text()
})
// And poll again
console.log('Polling! Waiting 90 seconds...')
setTimeout(retry, 90 * 1000)
}
}
catch (e) { retry() }
function patch_feed (update) {
console.log('We got a new update!', update)
if (update.body_text) {
// Got a whole new snapshot
feed = JSON.parse(update.body_text)
// Reset everything from scratch
posts = {}
curr_version = undefined
} else
// Got patches to append to the feed
update.patches.forEach(p => {
console.assert(p.unit === 'json')
console.assert(p.range === '[-0:-0]')
feed = feed.concat(JSON.parse(p.content))
})
// Update the current version
curr_version = update.version
// Fetch the post and announce!
fetch_posts(feed, cb)
}
}
async function fetch_post (url, cb) {
var retry = () => setTimeout(() => fetch_post(url, cb), 3000)
// console.log('fetching post', url)
try {
var res = await braid.fetch(url, {subscribe: true})
// Server might support subscriptions
if (res.headers.has('subscribe'))
res.subscribe(update => {
console.log('got update post!!', update)
cb(JSON.parse(update.body_text))
}, retry)
// Else just do polling
else {
// Incorporate this update we got
cb(JSON.parse(await res.text()))
// And poll again
console.log('Polling! Waiting 90 seconds...')
setTimeout(retry, 90 * 1000)
}
}
catch (e) { retry() }
}
function fetch_posts (feed, cb) {
// Initialize posts hash
for (var i=0; i<feed.length; i++) {
if (!feed[i]) continue // Skip null posts
var link = feed[i].link
if (!(link in posts))
posts[link] = undefined
}
// Fetch all missing posts
for (let link in posts)
if (!posts[link]) {
posts[link] = 'pending'
fetch_post(link, post => {
posts[link] = post
var new_feed = compile_posts()
cb(new_feed)
})
}
function compile_posts () {
var result = []
for (var i=0; i<feed.length; i++) {
if (!feed[i]) continue // Skip null posts
var post = posts[feed[i].link]
if (post && post !== 'pending')
result.push({url: feed[i].link, ...post})
}
return result
}
}
function make_new_post (host, params) {
// Generate a random ID
params.url = host + '/post/' + Math.random().toString(36).substr(6)
put_post(params)
}
function put_post (params) {
console.log('PUT post', params)
params.date ??= new Date().getTime()
params.from ??= ['anonymous']
params.to ??= ['public']
params.cc ??= []
if (!params.url) throw new Error('Need a url to put!')
if (params.body === undefined) throw new Error('Need a body to put!')
// Filter it down
var filtered_params =
( ({ from, to, cc, date, subject, body }) =>
({ from, to, cc, date, subject, body }) )(params)
filtered_params['in-reply-to'] = params['in-reply-to']
// Post it to the server
braid.fetch(params.url, {
method: 'PUT',
body: JSON.stringify(filtered_params)
})
}
export { subscribe_to_feed, make_new_post, put_post }