diff options
| author | s-ol <s+removethis@s-ol.nu> | 2022-01-14 16:53:52 +0000 |
|---|---|---|
| committer | s-ol <s+removethis@s-ol.nu> | 2022-01-14 16:53:52 +0000 |
| commit | 6754ad08df647e724ea9b71c784cf0d6f4013532 (patch) | |
| tree | c7bd7ef05e84056cee796ec0c52f19d162e948c9 | |
| parent | move DiscDAG discussion ids into /discdag/disc/:id (diff) | |
| download | fedidag-6754ad08df647e724ea9b71c784cf0d6f4013532.tar.gz fedidag-6754ad08df647e724ea9b71c784cf0d6f4013532.zip | |
server: support replying
| -rw-r--r-- | server/main.ts | 105 |
1 files changed, 91 insertions, 14 deletions
diff --git a/server/main.ts b/server/main.ts index e2143b8..02d5933 100644 --- a/server/main.ts +++ b/server/main.ts @@ -23,6 +23,19 @@ if (DEBUG) { app.use(express.json()); app.use(cookieParser()); +type Note = { + type: 'Note'; + published: string; + attributedTo: string | { + id: string; + type: 'Person', + name: string; + }; + inReplyTo: string[]; + replies: string[]; + content: string; +}; + const discdag = express() .post('/login', wrap(async ($req, $res) => { const { username, password } = $req.body; @@ -136,19 +149,6 @@ const discdag = express() if (doc.text().indexOf("Invalid discussion ID:") > -1) return $res.status(404).end(); - type Note = { - type: 'Note'; - published: string; - attributedTo: string | { - id: string; - type: 'Person', - name: string; - }; - inReplyTo: string[]; - replies: string[]; - content: string; - }; - let first = null; const items: Record<string, Note> = {}; for (const node of doc('g.node', 'svg')) { @@ -200,7 +200,84 @@ const discdag = express() first, items, }); - })); + })) + + .put('/disc/:discussion', wrap(async ($req, $res) => { + const { inReplyTo, content } = $req.body as { inReplyTo: string[], content: string }; + const { discussion } = $req.params; + const { digest } = $req.cookies; + + if (!digest || !digest.length) + return $res.status(401).end(); + + if (!inReplyTo.length || !content.length) + return $res.status(400).end(); + + const parents = inReplyTo.map(id => { + const parts = id.split('/'); + return parts[parts.length - 1]; + }).join(','); + + const res = await fetch(DISCDAG_URL, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Cookie': `DiscussionID=${discussion}; digest=${digest}; SelectedNodes=${parents}`, + }, + body: new URLSearchParams({ Action: 'SendReply', ReplyText: content }).toString(), + }); + + if (res.status !== 200) + throw new Error("bad response"); + + const doc = cheerio.load(await res.text()); + + if (doc.text().indexOf("Invalid discussion ID:") > -1) + return $res.status(404).end(); + + if (doc.text().indexOf("Replying only available if you have write access:") > -1) + return $res.status(403).end(); + + const items: Record<string, Note> = {}; + for (const node of doc('g.node polygon[stroke-width=5]', 'svg').parent()) { + const nodeId = doc('title', node).text(); + const [_, time, author] = nodeId.split('_'); + + const id = `${PUBLIC_URL}/discdag/disc/${discussion}/${nodeId}`; + + const content = doc('g:first text', node) + .slice(3) + .map(function(this: any) { return doc(this).text(); }) + .toArray() + .join(' ').trim(); + + items[id] = { + type: 'Note', + published: time.replace(/^(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)[a-z]*/, '$1-$2-$3T$4:$5:$6Z'), + attributedTo: `${PUBLIC_URL}/discdag/user/${author}`, + inReplyTo: [], + replies: [], + content, + }; + } + + for (const node of doc('g.edge', 'svg')) { + let [frm, to] = doc('title', node).text().split('->'); + if (frm === 'SELECTED' || to === 'SELECTED') continue; + frm = `${PUBLIC_URL}/discdag/disc/${discussion}/${frm}`; + to = `${PUBLIC_URL}/discdag/disc/${discussion}/${to}`; + + items[frm]?.replies.push(to); + items[to]?.inReplyTo.push(frm); + } + + return $res + .json({ + '@context': 'https://www.w3.org/ns/activitystreams', + items, + }); + })) +; app.use('/discdag', discdag); |
