tangled
alpha
login
or
join now
leaflet.pub
/
leaflet
289
fork
atom
a tool for shared writing and social publishing
289
fork
atom
overview
issues
28
pulls
pipelines
don't persist cursor for now
awarm.space
5 months ago
281099be
efbe44bd
+182
-199
1 changed file
expand all
collapse all
unified
split
appview
index.ts
+182
-199
appview/index.ts
···
31
31
);
32
32
const QUOTE_PARAM = "/l-quote/";
33
33
async function main() {
34
34
-
let startCursor;
35
35
-
try {
36
36
-
let file = (await readFile(cursorFile)).toString();
37
37
-
console.log("START CURSOR: " + file);
38
38
-
startCursor = parseInt(file);
39
39
-
console.log(startCursor);
40
40
-
if (Number.isNaN(startCursor)) startCursor = undefined;
41
41
-
} catch (e) {}
42
42
-
43
43
-
async function handleEvent(evt: Event) {
44
44
-
if (evt.event === "identity") {
45
45
-
if (evt.handle)
46
46
-
await supabase
47
47
-
.from("bsky_profiles")
48
48
-
.update({ handle: evt.handle })
49
49
-
.eq("did", evt.did);
50
50
-
}
51
51
-
if (
52
52
-
evt.event == "account" ||
53
53
-
evt.event === "identity" ||
54
54
-
evt.event === "sync"
55
55
-
)
56
56
-
return;
57
57
-
if (evt.collection !== "app.bsky.feed.post")
58
58
-
console.log(`${evt.event} in ${evt.collection} @ ${evt.seq}: ${evt.uri}`);
59
59
-
if (evt.collection === ids.PubLeafletDocument) {
60
60
-
if (evt.event === "create" || evt.event === "update") {
61
61
-
let record = PubLeafletDocument.validateRecord(evt.record);
62
62
-
if (!record.success) {
63
63
-
return;
64
64
-
}
65
65
-
await supabase.from("documents").upsert({
66
66
-
uri: evt.uri.toString(),
67
67
-
data: record.value as Json,
68
68
-
});
69
69
-
let publicationURI = new AtUri(record.value.publication);
70
70
-
71
71
-
if (publicationURI.host !== evt.uri.host) {
72
72
-
console.log("Unauthorized to create post!");
73
73
-
return;
74
74
-
}
75
75
-
await supabase.from("documents_in_publications").insert({
76
76
-
publication: record.value.publication,
77
77
-
document: evt.uri.toString(),
78
78
-
});
79
79
-
}
80
80
-
if (evt.event === "delete") {
81
81
-
await supabase.from("documents").delete().eq("uri", evt.uri.toString());
82
82
-
}
83
83
-
}
84
84
-
if (evt.collection === ids.PubLeafletPublication) {
85
85
-
if (evt.event === "create" || evt.event === "update") {
86
86
-
let record = PubLeafletPublication.validateRecord(evt.record);
87
87
-
if (!record.success) return;
88
88
-
let { error } = await supabase.from("publications").upsert({
89
89
-
uri: evt.uri.toString(),
90
90
-
identity_did: evt.did,
91
91
-
name: record.value.name,
92
92
-
record: record.value as Json,
93
93
-
});
94
94
-
95
95
-
if (error && error.code === "23503") {
96
96
-
console.log("creating identity");
97
97
-
let client = new Client({ connectionString: process.env.DB_URL });
98
98
-
let db = drizzle(client);
99
99
-
await createIdentity(db, { atp_did: evt.did });
100
100
-
client.end();
101
101
-
await supabase.from("publications").upsert({
102
102
-
uri: evt.uri.toString(),
103
103
-
identity_did: evt.did,
104
104
-
name: record.value.name,
105
105
-
record: record.value as Json,
106
106
-
});
107
107
-
}
108
108
-
}
109
109
-
if (evt.event === "delete") {
110
110
-
await supabase
111
111
-
.from("publications")
112
112
-
.delete()
113
113
-
.eq("uri", evt.uri.toString());
114
114
-
}
115
115
-
}
116
116
-
if (evt.collection === ids.PubLeafletComment) {
117
117
-
if (evt.event === "create" || evt.event === "update") {
118
118
-
let record = PubLeafletComment.validateRecord(evt.record);
119
119
-
if (!record.success) return;
120
120
-
let { error } = await supabase.from("comments_on_documents").upsert({
121
121
-
uri: evt.uri.toString(),
122
122
-
profile: evt.did,
123
123
-
document: record.value.subject,
124
124
-
record: record.value as Json,
125
125
-
});
126
126
-
}
127
127
-
if (evt.event === "delete") {
128
128
-
await supabase
129
129
-
.from("comments_on_documents")
130
130
-
.delete()
131
131
-
.eq("uri", evt.uri.toString());
132
132
-
}
133
133
-
}
134
134
-
if (evt.collection === ids.PubLeafletGraphSubscription) {
135
135
-
if (evt.event === "create" || evt.event === "update") {
136
136
-
let record = PubLeafletGraphSubscription.validateRecord(evt.record);
137
137
-
if (!record.success) return;
138
138
-
let { error } = await supabase
139
139
-
.from("publication_subscriptions")
140
140
-
.upsert({
141
141
-
uri: evt.uri.toString(),
142
142
-
identity: evt.did,
143
143
-
publication: record.value.publication,
144
144
-
record: record.value as Json,
145
145
-
});
146
146
-
if (error && error.code === "23503") {
147
147
-
console.log("creating identity");
148
148
-
let client = new Client({ connectionString: process.env.DB_URL });
149
149
-
let db = drizzle(client);
150
150
-
await createIdentity(db, { atp_did: evt.did });
151
151
-
client.end();
152
152
-
await supabase.from("publication_subscriptions").upsert({
153
153
-
uri: evt.uri.toString(),
154
154
-
identity: evt.did,
155
155
-
publication: record.value.publication,
156
156
-
record: record.value as Json,
157
157
-
});
158
158
-
}
159
159
-
}
160
160
-
if (evt.event === "delete") {
161
161
-
await supabase
162
162
-
.from("publication_subscriptions")
163
163
-
.delete()
164
164
-
.eq("uri", evt.uri.toString());
165
165
-
}
166
166
-
}
167
167
-
// if (evt.collection === ids.AppBskyActorProfile) {
168
168
-
// //only listen to updates because we should fetch it for the first time when they subscribe!
169
169
-
// if (evt.event === "update") {
170
170
-
// await supabaseServerClient
171
171
-
// .from("bsky_profiles")
172
172
-
// .update({ record: evt.record as Json })
173
173
-
// .eq("did", evt.did);
174
174
-
// }
175
175
-
// }
176
176
-
if (evt.collection === "app.bsky.feed.post") {
177
177
-
if (evt.event !== "create") return;
178
178
-
179
179
-
// Early exit if no embed
180
180
-
if (
181
181
-
!evt.record ||
182
182
-
typeof evt.record !== "object" ||
183
183
-
!("embed" in evt.record)
184
184
-
)
185
185
-
return;
186
186
-
187
187
-
// Check if embed contains our quote param using optional chaining
188
188
-
const embedRecord = evt.record as any;
189
189
-
const hasQuoteParam =
190
190
-
embedRecord.embed?.external?.uri?.includes(QUOTE_PARAM) ||
191
191
-
embedRecord.embed?.media?.external?.uri?.includes(QUOTE_PARAM);
192
192
-
193
193
-
if (!hasQuoteParam) return;
194
194
-
console.log("FOUND EMBED!!!");
195
195
-
196
196
-
// Now validate the record since we know it contains our quote param
197
197
-
let record = AppBskyFeedPost.validateRecord(evt.record);
198
198
-
if (!record.success) return;
199
199
-
200
200
-
let embed: string | null = null;
201
201
-
if (
202
202
-
AppBskyEmbedExternal.isMain(record.value.embed) &&
203
203
-
record.value.embed.external.uri.includes(QUOTE_PARAM)
204
204
-
) {
205
205
-
embed = record.value.embed.external.uri;
206
206
-
}
207
207
-
if (
208
208
-
AppBskyEmbedRecordWithMedia.isMain(record.value.embed) &&
209
209
-
AppBskyEmbedExternal.isMain(record.value.embed.media) &&
210
210
-
record.value.embed.media?.external?.uri.includes(QUOTE_PARAM)
211
211
-
) {
212
212
-
embed = record.value.embed.media.external.uri;
213
213
-
}
214
214
-
if (embed) {
215
215
-
console.log(
216
216
-
"processing post mention: " + embed + " in " + evt.uri.toString(),
217
217
-
);
218
218
-
await inngest.send({
219
219
-
name: "appview/index-bsky-post-mention",
220
220
-
data: { post_uri: evt.uri.toString(), document_link: embed },
221
221
-
});
222
222
-
}
223
223
-
}
224
224
-
}
225
225
-
226
226
-
const runner = new MemoryRunner({
227
227
-
startCursor,
228
228
-
setCursor: async (cursor) => {
229
229
-
// persist cursor
230
230
-
await writeFile(cursorFile, cursor.toString(), { flush: true });
231
231
-
},
232
232
-
});
34
34
+
const runner = new MemoryRunner({});
233
35
let firehose = new Firehose({
234
36
service: "wss://relay1.us-west.bsky.network",
235
37
subscriptionReconnectDelay: 3000,
···
267
69
}
268
70
269
71
main();
72
72
+
73
73
+
async function handleEvent(evt: Event) {
74
74
+
if (evt.event === "identity") {
75
75
+
if (evt.handle)
76
76
+
await supabase
77
77
+
.from("bsky_profiles")
78
78
+
.update({ handle: evt.handle })
79
79
+
.eq("did", evt.did);
80
80
+
}
81
81
+
if (
82
82
+
evt.event == "account" ||
83
83
+
evt.event === "identity" ||
84
84
+
evt.event === "sync"
85
85
+
)
86
86
+
return;
87
87
+
if (evt.collection !== "app.bsky.feed.post")
88
88
+
console.log(`${evt.event} in ${evt.collection} @ ${evt.seq}: ${evt.uri}`);
89
89
+
if (evt.collection === ids.PubLeafletDocument) {
90
90
+
if (evt.event === "create" || evt.event === "update") {
91
91
+
let record = PubLeafletDocument.validateRecord(evt.record);
92
92
+
if (!record.success) {
93
93
+
return;
94
94
+
}
95
95
+
await supabase.from("documents").upsert({
96
96
+
uri: evt.uri.toString(),
97
97
+
data: record.value as Json,
98
98
+
});
99
99
+
let publicationURI = new AtUri(record.value.publication);
100
100
+
101
101
+
if (publicationURI.host !== evt.uri.host) {
102
102
+
console.log("Unauthorized to create post!");
103
103
+
return;
104
104
+
}
105
105
+
await supabase.from("documents_in_publications").insert({
106
106
+
publication: record.value.publication,
107
107
+
document: evt.uri.toString(),
108
108
+
});
109
109
+
}
110
110
+
if (evt.event === "delete") {
111
111
+
await supabase.from("documents").delete().eq("uri", evt.uri.toString());
112
112
+
}
113
113
+
}
114
114
+
if (evt.collection === ids.PubLeafletPublication) {
115
115
+
if (evt.event === "create" || evt.event === "update") {
116
116
+
let record = PubLeafletPublication.validateRecord(evt.record);
117
117
+
if (!record.success) return;
118
118
+
let { error } = await supabase.from("publications").upsert({
119
119
+
uri: evt.uri.toString(),
120
120
+
identity_did: evt.did,
121
121
+
name: record.value.name,
122
122
+
record: record.value as Json,
123
123
+
});
124
124
+
125
125
+
if (error && error.code === "23503") {
126
126
+
console.log("creating identity");
127
127
+
let client = new Client({ connectionString: process.env.DB_URL });
128
128
+
let db = drizzle(client);
129
129
+
await createIdentity(db, { atp_did: evt.did });
130
130
+
client.end();
131
131
+
await supabase.from("publications").upsert({
132
132
+
uri: evt.uri.toString(),
133
133
+
identity_did: evt.did,
134
134
+
name: record.value.name,
135
135
+
record: record.value as Json,
136
136
+
});
137
137
+
}
138
138
+
}
139
139
+
if (evt.event === "delete") {
140
140
+
await supabase
141
141
+
.from("publications")
142
142
+
.delete()
143
143
+
.eq("uri", evt.uri.toString());
144
144
+
}
145
145
+
}
146
146
+
if (evt.collection === ids.PubLeafletComment) {
147
147
+
if (evt.event === "create" || evt.event === "update") {
148
148
+
let record = PubLeafletComment.validateRecord(evt.record);
149
149
+
if (!record.success) return;
150
150
+
let { error } = await supabase.from("comments_on_documents").upsert({
151
151
+
uri: evt.uri.toString(),
152
152
+
profile: evt.did,
153
153
+
document: record.value.subject,
154
154
+
record: record.value as Json,
155
155
+
});
156
156
+
}
157
157
+
if (evt.event === "delete") {
158
158
+
await supabase
159
159
+
.from("comments_on_documents")
160
160
+
.delete()
161
161
+
.eq("uri", evt.uri.toString());
162
162
+
}
163
163
+
}
164
164
+
if (evt.collection === ids.PubLeafletGraphSubscription) {
165
165
+
if (evt.event === "create" || evt.event === "update") {
166
166
+
let record = PubLeafletGraphSubscription.validateRecord(evt.record);
167
167
+
if (!record.success) return;
168
168
+
let { error } = await supabase.from("publication_subscriptions").upsert({
169
169
+
uri: evt.uri.toString(),
170
170
+
identity: evt.did,
171
171
+
publication: record.value.publication,
172
172
+
record: record.value as Json,
173
173
+
});
174
174
+
if (error && error.code === "23503") {
175
175
+
console.log("creating identity");
176
176
+
let client = new Client({ connectionString: process.env.DB_URL });
177
177
+
let db = drizzle(client);
178
178
+
await createIdentity(db, { atp_did: evt.did });
179
179
+
client.end();
180
180
+
await supabase.from("publication_subscriptions").upsert({
181
181
+
uri: evt.uri.toString(),
182
182
+
identity: evt.did,
183
183
+
publication: record.value.publication,
184
184
+
record: record.value as Json,
185
185
+
});
186
186
+
}
187
187
+
}
188
188
+
if (evt.event === "delete") {
189
189
+
await supabase
190
190
+
.from("publication_subscriptions")
191
191
+
.delete()
192
192
+
.eq("uri", evt.uri.toString());
193
193
+
}
194
194
+
}
195
195
+
// if (evt.collection === ids.AppBskyActorProfile) {
196
196
+
// //only listen to updates because we should fetch it for the first time when they subscribe!
197
197
+
// if (evt.event === "update") {
198
198
+
// await supabaseServerClient
199
199
+
// .from("bsky_profiles")
200
200
+
// .update({ record: evt.record as Json })
201
201
+
// .eq("did", evt.did);
202
202
+
// }
203
203
+
// }
204
204
+
if (evt.collection === "app.bsky.feed.post") {
205
205
+
if (evt.event !== "create") return;
206
206
+
207
207
+
// Early exit if no embed
208
208
+
if (
209
209
+
!evt.record ||
210
210
+
typeof evt.record !== "object" ||
211
211
+
!("embed" in evt.record)
212
212
+
)
213
213
+
return;
214
214
+
215
215
+
// Check if embed contains our quote param using optional chaining
216
216
+
const embedRecord = evt.record as any;
217
217
+
const hasQuoteParam =
218
218
+
embedRecord.embed?.external?.uri?.includes(QUOTE_PARAM) ||
219
219
+
embedRecord.embed?.media?.external?.uri?.includes(QUOTE_PARAM);
220
220
+
221
221
+
if (!hasQuoteParam) return;
222
222
+
console.log("FOUND EMBED!!!");
223
223
+
224
224
+
// Now validate the record since we know it contains our quote param
225
225
+
let record = AppBskyFeedPost.validateRecord(evt.record);
226
226
+
if (!record.success) return;
227
227
+
228
228
+
let embed: string | null = null;
229
229
+
if (
230
230
+
AppBskyEmbedExternal.isMain(record.value.embed) &&
231
231
+
record.value.embed.external.uri.includes(QUOTE_PARAM)
232
232
+
) {
233
233
+
embed = record.value.embed.external.uri;
234
234
+
}
235
235
+
if (
236
236
+
AppBskyEmbedRecordWithMedia.isMain(record.value.embed) &&
237
237
+
AppBskyEmbedExternal.isMain(record.value.embed.media) &&
238
238
+
record.value.embed.media?.external?.uri.includes(QUOTE_PARAM)
239
239
+
) {
240
240
+
embed = record.value.embed.media.external.uri;
241
241
+
}
242
242
+
if (embed) {
243
243
+
console.log(
244
244
+
"processing post mention: " + embed + " in " + evt.uri.toString(),
245
245
+
);
246
246
+
await inngest.send({
247
247
+
name: "appview/index-bsky-post-mention",
248
248
+
data: { post_uri: evt.uri.toString(), document_link: embed },
249
249
+
});
250
250
+
}
251
251
+
}
252
252
+
}