git.s-ol.nu fedidag / 09395af
server: ActivityStreams reply/link/unlink API s-ol 1 year, 7 months ago
1 changed file(s) with 85 addition(s) and 30 deletion(s). Raw diff Collapse all Expand all
2222 app.use(express.json());
2323 app.use(cookieParser());
2424
25 type LinkOr<T> = string | T;
26
27 type Person = {
28 id: string;
29 type: 'Person',
30 name: string;
31 };
32
2533 type Note = {
2634 type: 'Note';
2735 published: string;
28 attributedTo: string | {
29 id: string;
30 type: 'Person',
31 name: string;
32 };
36 attributedTo: LinkOr<Person>;
3337 inReplyTo: string[];
3438 replies: string[];
3539 content: string;
40 };
41
42 type Relationship<S, O> = {
43 type: 'Relationship';
44 relationship: string;
45 subject: S;
46 object: O;
47 };
48
49 type Create<O> = {
50 type: 'Create';
51 actor: LinkOr<Person>;
52 object: O;
53 };
54
55 type Delete<O> = {
56 type: 'Create';
57 actor: LinkOr<Person>;
58 object: O;
59 };
60
61 const iri2id = (iri: string) => {
62 const parts = iri.split('/');
63 return parts[parts.length - 1];
3664 };
3765
3866 const discdag = express()
188216 {
189217 items: {
190218 '@id': 'as:items',
191 '@type': '@id',
192219 '@container': '@id'
193220 },
194221 },
201228 });
202229 }))
203230
204 .put('/disc/:discussion', wrap(async ($req, $res) => {
205 const { inReplyTo, content } = $req.body as { inReplyTo: string[], content: string };
231 .post('/disc/:discussion', wrap(async ($req, $res) => {
206232 const { discussion } = $req.params;
207233 const { digest } = $req.cookies;
208234
209235 if (!digest || !digest.length)
210236 return $res.status(401).end();
211237
212 if (!inReplyTo.length || !content.length)
213 return $res.status(400).end();
214
215 const parents = inReplyTo.map(id => {
216 const parts = id.split('/');
217 return parts[parts.length - 1];
218 }).join(',');
219
220 const res = await fetch(DISCDAG_URL, {
221 method: 'POST',
222 headers: {
223 'Content-Type': 'application/x-www-form-urlencoded',
224 'Cookie': `DiscussionID=${discussion}; digest=${digest}; SelectedNodes=${parents}`,
225 },
226 body: new URLSearchParams({ Action: 'SendReply', ReplyText: content }).toString(),
227 });
238 type Activity =
239 | Create<Note>
240 | Create<Relationship<string, string>>
241 | Delete<Relationship<string, string>>
242 ;
243 const activity = $req.body as Activity;
244
245 let selection: string[];
246 let body: string;
247 let method = 'GET';
248 if (activity.type === 'Create' && activity.object?.type === 'Note') {
249 method = 'POST';
250 selection = activity.object.inReplyTo.map(iri2id);
251 body = new URLSearchParams({ Action: 'SendReply', ReplyText: activity.object.content }).toString();
252 } else if (activity.object?.type === 'Relationship' && activity.object.relationship === 'as:inReplyTo') {
253 const frm = iri2id(activity.object.object);
254 const to = iri2id(activity.object.subject);
255 selection = [frm, to];
256 body = new URLSearchParams({
257 Action: activity.type === 'Create' ? 'CreateLink' : 'RemoveLink',
258 N0: frm,
259 N1: to,
260 }).toString();
261 } else {
262 return $res.status(501).end();
263 }
264
265 const headers = {
266 'Content-Type': 'application/x-www-form-urlencoded',
267 'Cookie': `DiscussionID=${discussion}; digest=${digest}; SelectedNodes=${selection.join(',')}`,
268 };
269
270 let res;
271 if (method === 'POST') {
272 res = await fetch(DISCDAG_URL, { method, headers, body });
273 } else {
274 res = await fetch(DISCDAG_URL + `?${body}`, { method, headers });
275 }
228276
229277 if (res.status !== 200)
230278 throw new Error("bad response");
270318 items[to]?.inReplyTo.push(frm);
271319 }
272320
273 return $res
274 .json({
275 '@context': 'https://www.w3.org/ns/activitystreams',
276 items,
277 });
321 return $res.json({
322 '@context': [
323 'https://www.w3.org/ns/activitystreams',
324 {
325 items: {
326 '@id': 'as:items',
327 '@container': '@id'
328 },
329 },
330 ],
331 items,
332 });
278333 }))
279334 ;
280335
317372
318373 try {
319374 app.listen(PORT, (): void => {
320 console.log(`Connected successfully on port ${PORT}`);
375 console.log(`Connected successfully on port ${PORT}`);
321376 });
322377 } catch (error) {
323378 console.error(`Error occured: ${error}`);