Initial status posting capability.

This commit is contained in:
Andrew Pietila 2023-11-20 20:27:38 -06:00
parent f057686813
commit 0f2c1af2c7
3 changed files with 279 additions and 1 deletions

173
package-lock.json generated
View file

@ -21,6 +21,7 @@
"jsonld": "^8.3.1",
"path-to-regexp": "^6.2.1",
"qs": "^6.11.2",
"sanitize-html": "^2.11.0",
"web-push": "^3.6.6"
},
"devDependencies": {
@ -1274,6 +1275,14 @@
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
"dev": true
},
"node_modules/deepmerge": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/define-data-property": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.0.tgz",
@ -1347,6 +1356,57 @@
"node": ">=6.0.0"
}
},
"node_modules/dom-serializer": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
"dependencies": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.2",
"entities": "^4.2.0"
},
"funding": {
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
}
},
"node_modules/domelementtype": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
]
},
"node_modules/domhandler": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
"dependencies": {
"domelementtype": "^2.3.0"
},
"engines": {
"node": ">= 4"
},
"funding": {
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/domutils": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
"integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
"dependencies": {
"dom-serializer": "^2.0.0",
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3"
},
"funding": {
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
"node_modules/dotenv": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-5.0.1.tgz",
@ -1403,6 +1463,17 @@
"once": "^1.4.0"
}
},
"node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/env-paths": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
@ -1520,7 +1591,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"dev": true,
"engines": {
"node": ">=10"
},
@ -2540,6 +2610,24 @@
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
"integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ=="
},
"node_modules/htmlparser2": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
"integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
"funding": [
"https://github.com/fb55/htmlparser2?sponsor=1",
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
],
"dependencies": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3",
"domutils": "^3.0.1",
"entities": "^4.4.0"
}
},
"node_modules/http_ece": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/http_ece/-/http_ece-1.1.0.tgz",
@ -2893,6 +2981,14 @@
"node": ">=8"
}
},
"node_modules/is-plain-object": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-regex": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
@ -3461,6 +3557,23 @@
"integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==",
"optional": true
},
"node_modules/nanoid": {
"version": "3.3.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"bin": {
"nanoid": "bin/nanoid.cjs"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/napi-build-utils": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
@ -3904,6 +4017,11 @@
"node": ">= 0.6"
}
},
"node_modules/parse-srcset": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz",
"integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q=="
},
"node_modules/parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@ -3977,6 +4095,38 @@
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz",
"integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw=="
},
"node_modules/picocolors": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
},
"node_modules/postcss": {
"version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
"integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"dependencies": {
"nanoid": "^3.3.6",
"picocolors": "^1.0.0",
"source-map-js": "^1.0.2"
},
"engines": {
"node": "^10 || ^12 || >=14"
}
},
"node_modules/prebuild-install": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz",
@ -4390,6 +4540,19 @@
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"node_modules/sanitize-html": {
"version": "2.11.0",
"resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.11.0.tgz",
"integrity": "sha512-BG68EDHRaGKqlsNjJ2xUB7gpInPA8gVx/mvjO743hZaeMCZ2DwzW7xvsqZ+KNU4QKwj86HJ3uu2liISf2qBBUA==",
"dependencies": {
"deepmerge": "^4.2.2",
"escape-string-regexp": "^4.0.0",
"htmlparser2": "^8.0.0",
"is-plain-object": "^5.0.0",
"parse-srcset": "^1.0.2",
"postcss": "^8.3.11"
}
},
"node_modules/semver": {
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
@ -4600,6 +4763,14 @@
"node": ">= 10"
}
},
"node_modules/source-map-js": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/sqlite3": {
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.6.tgz",

View file

@ -21,6 +21,7 @@
"jsonld": "^8.3.1",
"path-to-regexp": "^6.2.1",
"qs": "^6.11.2",
"sanitize-html": "^2.11.0",
"web-push": "^3.6.6"
},
"type": "commonjs",

106
routes/api/v1/statuses.js Normal file
View file

@ -0,0 +1,106 @@
const sanitizeHtml = require("sanitize-html");
const auth = require("../../../middleware/auth");
const databaseHandler = require("../../../lib/database-handler");
module.exports = {
route: (routeObj) => {
routeObj.post(auth.auth_token(true, "write:statuses"), (req, res) => {
const id = process.hrtime.bigint().toString(10);
const token = req.brainz.token;
const account = databaseHandler.getAccountByToken(token.token);
const created_at = Date.now();
const statusText = sanitizeHtml(req.body.status, {
allowedTags: [],
allowedAttributes: {},
});
const status = {
"@id": `https://${req.header.host}/users/${account.username}/statuses/${id}`,
"@type": "https://www.w3.org/ns/activitystreams#Note",
"http://ostatus.org#atomUri": `https://${req.header.host}/users/${account.username}/statuses/${id}`,
"http://ostatus.org#conversation": null, // TODO: wut
"http://ostatus.org#inReplyToAtomUri": null,
"https://www.w3.org/ns/activitystreams#attachment": [],
"https://www.w3.org/ns/activitystreams#attributedTo": {
"@id": `https://${req.headers.host}/users/${account.username}`,
},
"https://www.w3.org/ns/activitystreams#cc": {
"@id": `https://${req.headers.host}/users/${account.username}/followers`,
},
"https://www.w3.org/ns/activitystreams#content": [
`<p>${statusText.split("\n").join("</p><p>")}</p>`,
],
"https://www.w3.org/ns/activitystreams#inReplyTo": null,
"https://www.w3.org/ns/activitystreams#published": {
"@type": "http://www.w3.org/2001/XMLSchema#dateTime",
"@value": new Date(created_at).toISOString(),
},
"https://www.w3.org/ns/activitystreams#replies": {
"@id": `https://${req.headers.host}/users/${account.username}/statuses/${id}/replies`,
"@type": "https://www.w3.org/ns/activitystreams#Collection",
"https://www.w3.org/ns/activitystreams#first": {
"@type": "https://www.w3.org/ns/activitystreams#CollectionPage",
"https://www.w3.org/ns/activitystreams#items": [],
"https://www.w3.org/ns/activitystreams#next": {
"@id": `https://${req.headers.host}/users/${account.username}/statuses/${id}/replies?only_other_accounts=true&page=true`,
},
"https://www.w3.org/ns/activitystreams#partOf": {
"@id": `https://${req.headers.host}/users/${account.username}/statuses/${id}/replies`,
},
},
},
"https://www.w3.org/ns/activitystreams#tag": [],
"https://www.w3.org/ns/activitystreams#to": {
"@id": "https://www.w3.org/ns/activitystreams#Public",
},
"https://www.w3.org/ns/activitystreams#url": {
"@id": `https://${req.headers.host}/@${account.username}/${id}`,
},
};
status["https://www.w3.org/ns/activitystreams#summary"] = req.body.spoiler_text ?? "";
status["https://www.w3.org/ns/activitystreams#sensitive"] = req.body.spoiler_text ?? req.body.spoiler_text ? true : false;
databaseHandler.activity[`https://${req.header.host}/users/${account.username}/statuses/${id}`] = {
object: JSON.stringify(status),
type: status["@type"],
local: true,
owner: account.username,
created_at,
};
// TODO: Distribution queue.
const retObj = {
id: status["@id"],
created_at: status["https://www.w3.org/ns/activitystreams#published"]["@value"],
in_reply_to_id: null,
in_reply_to_account_id: null,
sensitive: status["https://www.w3.org/ns/activitystreams#sensitive"],
spoiler_text: status["https://www.w3.org/ns/activitystreams#summary"],
visibility: "public", // TODO: Private posting capability.
language: "en", // TODO: Other languages.
uri: status["@id"],
url: status["@id"],
replies_count: 0, // Future copy paste jobs - These counts should be accurate.
reblogs_count: 0,
favourites_count: 0,
favourited: false,
reblogged: false,
muted: false,
bookmarked: false,
content: status["https://www.w3.org/ns/activitystreams#content"][0],
reblog: null,
account: {},
media_attachments: [], // TODO: Support media.
mentions: [],
tags: [],
emojis: [],
card: null,
poll: null,
};
return retObj;
});
},
};