aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s+removethis@s-ol.nu>2022-01-14 16:53:52 +0000
committers-ol <s+removethis@s-ol.nu>2022-01-14 16:53:52 +0000
commit6754ad08df647e724ea9b71c784cf0d6f4013532 (patch)
treec7bd7ef05e84056cee796ec0c52f19d162e948c9
parentmove DiscDAG discussion ids into /discdag/disc/:id (diff)
downloadfedidag-6754ad08df647e724ea9b71c784cf0d6f4013532.tar.gz
fedidag-6754ad08df647e724ea9b71c784cf0d6f4013532.zip
server: support replying
-rw-r--r--server/main.ts105
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);