forked from shadowfacts/shadowfacts.net
Add remote interaction
This commit is contained in:
parent
b5f101a4e7
commit
7d8754ad82
|
@ -4,6 +4,7 @@ import comments from "./comments";
|
||||||
import federate from "./federate";
|
import federate from "./federate";
|
||||||
import followers from "./followers";
|
import followers from "./followers";
|
||||||
import inbox from "./inbox";
|
import inbox from "./inbox";
|
||||||
|
import interact from "./interact";
|
||||||
import nodeinfo from "./nodeinfo";
|
import nodeinfo from "./nodeinfo";
|
||||||
import webfinger from "./webfinger";
|
import webfinger from "./webfinger";
|
||||||
|
|
||||||
|
@ -14,6 +15,7 @@ export = {
|
||||||
federate,
|
federate,
|
||||||
followers,
|
followers,
|
||||||
inbox,
|
inbox,
|
||||||
|
interact,
|
||||||
nodeinfo,
|
nodeinfo,
|
||||||
webfinger
|
webfinger
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
import {Router} from "express";
|
||||||
|
import {queryWebfinger} from "./webfinger";
|
||||||
|
|
||||||
|
const domain = process.env.DOMAIN;
|
||||||
|
|
||||||
|
export default async function interact(router: Router) {
|
||||||
|
router.post("/interact", async (req, res) => {
|
||||||
|
const permalink = req.body.permalink;
|
||||||
|
const acct = req.body.remote_follow.acct;
|
||||||
|
const webfingerResult = await queryWebfinger(acct);
|
||||||
|
const link = webfingerResult.links.find((l) => l.rel === "http://ostatus.org/schema/1.0/subscribe");
|
||||||
|
if (link && 'template' in link) {
|
||||||
|
res.redirect(link.template.replace("{uri}", `https://${domain}${permalink}`));
|
||||||
|
} else {
|
||||||
|
res.status(400).send("Unable to find remote subscribe URL");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
|
@ -1,9 +1,21 @@
|
||||||
import express, { Router } from "express";
|
import express, { Router } from "express";
|
||||||
|
import fetch from "node-fetch";
|
||||||
|
|
||||||
const domain = process.env.DOMAIN;
|
const domain = process.env.DOMAIN;
|
||||||
|
|
||||||
export default function webfinger(router: Router) {
|
export default function webfinger(router: Router) {
|
||||||
router.get("/.well-known/webfinger", (req, res) => {
|
router.get("/.well-known/webfinger", (req, res) => {
|
||||||
|
res.json({
|
||||||
|
subject: `acct:block@${domain}`,
|
||||||
|
aliases: [`https://${domain}/ap/actor`],
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
rel: "self",
|
||||||
|
type: "application/activity+json",
|
||||||
|
href: `https://${domain}/ap/actor`,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
} as WebfingerResult);
|
||||||
res.json({
|
res.json({
|
||||||
"subject": `acct:blog@${domain}`,
|
"subject": `acct:blog@${domain}`,
|
||||||
"links": [
|
"links": [
|
||||||
|
@ -17,3 +29,22 @@ export default function webfinger(router: Router) {
|
||||||
res.end();
|
res.end();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function queryWebfinger(acct: string): Promise<WebfingerResult> {
|
||||||
|
if (acct.startsWith("@")) {
|
||||||
|
acct = acct.substring(1);
|
||||||
|
}
|
||||||
|
const parts = acct.split("@");
|
||||||
|
if (parts.length !== 2) {
|
||||||
|
throw "Invalid account";
|
||||||
|
}
|
||||||
|
const response = await fetch(`https://${parts[1]}/.well-known/webfinger?resource=${acct}`);
|
||||||
|
const json = await response.json();
|
||||||
|
return json as WebfingerResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WebfingerResult {
|
||||||
|
subject: string;
|
||||||
|
aliases: string[];
|
||||||
|
links: Array<{rel: string, type: string, href: string} | {rel: "https://ostatus.org/schema/1.0/subscribe", template: string}>;
|
||||||
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@ function watch() {
|
||||||
const app = express();
|
const app = express();
|
||||||
app.use(morgan("dev"));
|
app.use(morgan("dev"));
|
||||||
app.use(bodyParser.json({ type: "application/activity+json" }));
|
app.use(bodyParser.json({ type: "application/activity+json" }));
|
||||||
|
app.use(bodyParser.urlencoded());
|
||||||
|
|
||||||
const connection = await createConnection({
|
const connection = await createConnection({
|
||||||
"type": "postgres",
|
"type": "postgres",
|
||||||
|
@ -82,6 +83,8 @@ function watch() {
|
||||||
|
|
||||||
await activitypub.articles.setup(posts);
|
await activitypub.articles.setup(posts);
|
||||||
|
|
||||||
|
await activitypub.interact(app);
|
||||||
|
|
||||||
const apRouter = Router();
|
const apRouter = Router();
|
||||||
apRouter.use(validateHttpSig);
|
apRouter.use(validateHttpSig);
|
||||||
await activitypub.actor(apRouter);
|
await activitypub.actor(apRouter);
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
"markdown-it": "^8.4.2",
|
"markdown-it": "^8.4.2",
|
||||||
"markdown-it-footnote": "^3.0.2",
|
"markdown-it-footnote": "^3.0.2",
|
||||||
"morgan": "^1.9.1",
|
"morgan": "^1.9.1",
|
||||||
|
"node-fetch": "^2.6.7",
|
||||||
"pg": "^8.5.1",
|
"pg": "^8.5.1",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"request": "^2.88.0",
|
"request": "^2.88.0",
|
||||||
|
@ -1746,6 +1747,25 @@
|
||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/node-fetch": {
|
||||||
|
"version": "2.6.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||||
|
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"whatwg-url": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "4.x || >=6.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"encoding": "^0.1.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"encoding": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/normalize-path": {
|
"node_modules/normalize-path": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||||
|
@ -2511,6 +2531,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
|
||||||
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
|
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
|
||||||
},
|
},
|
||||||
|
"node_modules/tr46": {
|
||||||
|
"version": "0.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||||
|
"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
|
||||||
|
},
|
||||||
"node_modules/ts-node": {
|
"node_modules/ts-node": {
|
||||||
"version": "9.1.1",
|
"version": "9.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz",
|
||||||
|
@ -2877,6 +2902,20 @@
|
||||||
"extsprintf": "^1.2.0"
|
"extsprintf": "^1.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/webidl-conversions": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||||
|
"integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
|
||||||
|
},
|
||||||
|
"node_modules/whatwg-url": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||||
|
"integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
|
||||||
|
"dependencies": {
|
||||||
|
"tr46": "~0.0.3",
|
||||||
|
"webidl-conversions": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/wrappy": {
|
"node_modules/wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
|
@ -4305,6 +4344,14 @@
|
||||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
|
||||||
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
|
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
|
||||||
},
|
},
|
||||||
|
"node-fetch": {
|
||||||
|
"version": "2.6.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||||
|
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
|
||||||
|
"requires": {
|
||||||
|
"whatwg-url": "^5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"normalize-path": {
|
"normalize-path": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||||
|
@ -4911,6 +4958,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"tr46": {
|
||||||
|
"version": "0.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||||
|
"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
|
||||||
|
},
|
||||||
"ts-node": {
|
"ts-node": {
|
||||||
"version": "9.1.1",
|
"version": "9.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz",
|
||||||
|
@ -5169,6 +5221,20 @@
|
||||||
"extsprintf": "^1.2.0"
|
"extsprintf": "^1.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webidl-conversions": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||||
|
"integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
|
||||||
|
},
|
||||||
|
"whatwg-url": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||||
|
"integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
|
||||||
|
"requires": {
|
||||||
|
"tr46": "~0.0.3",
|
||||||
|
"webidl-conversions": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"wrappy": {
|
"wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
"markdown-it": "^8.4.2",
|
"markdown-it": "^8.4.2",
|
||||||
"markdown-it-footnote": "^3.0.2",
|
"markdown-it-footnote": "^3.0.2",
|
||||||
"morgan": "^1.9.1",
|
"morgan": "^1.9.1",
|
||||||
|
"node-fetch": "^2.6.7",
|
||||||
"pg": "^8.5.1",
|
"pg": "^8.5.1",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"request": "^2.88.0",
|
"request": "^2.88.0",
|
||||||
|
|
|
@ -354,7 +354,47 @@ article {
|
||||||
}
|
}
|
||||||
|
|
||||||
#comments-info {
|
#comments-info {
|
||||||
margin-top: 0;
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#remote-interact {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: baseline;
|
||||||
|
|
||||||
|
input {
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=text] {
|
||||||
|
flex-grow: 1;
|
||||||
|
padding: 0 4px;
|
||||||
|
background-color: var(--content-background-color);
|
||||||
|
border: 1px solid var(--accent-color);
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 2rem;
|
||||||
|
color: var(--content-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=submit] {
|
||||||
|
background-color: var(--ui-background-color);
|
||||||
|
border: 1px solid var(--accent-color);
|
||||||
|
color: var(--accent-color);
|
||||||
|
line-height: 2rem;
|
||||||
|
padding: 0 1rem;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: bold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
|
||||||
|
-webkit-transition: 0.3s ease-out;
|
||||||
|
transition: 0.3s ease-out;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--accent-color);
|
||||||
|
color: var(--ui-background-color);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#comments-js-warning {
|
#comments-js-warning {
|
||||||
|
|
|
@ -23,9 +23,20 @@ metadata.layout = "default.html.ejs"
|
||||||
<h2 id="comments-container-title">Comments</h2>
|
<h2 id="comments-container-title">Comments</h2>
|
||||||
</summary>
|
</summary>
|
||||||
<p id="comments-info">
|
<p id="comments-info">
|
||||||
Comments powered by ActivityPub. To respond to this post or to another comment, copy its URL into the search interface of your client for Mastodon, Pleroma, or other compatible software.
|
Comments powered by ActivityPub. To respond to this post enter your username and instance below, or copy its URL into the search interface of your client for Mastodon, Pleroma, or other compatible software.
|
||||||
<a href="/2019/reincarnation/#activity-pub">Learn more</a>.
|
<a href="/2019/reincarnation/#activity-pub">Learn more</a>.
|
||||||
</p>
|
</p>
|
||||||
|
<form action="/interact" method="POST" id="remote-interact">
|
||||||
|
<span>Reply from your instance:</span>
|
||||||
|
<% if (metadata.useOldPermalinkForComments) { %>
|
||||||
|
<input type="hidden" name="permalink" value="<%= metadata.oldPermalink %>">
|
||||||
|
<% } else { %>
|
||||||
|
<input type="hidden" name="permalink" value="<%= metadata.permalink %>">
|
||||||
|
<% } %>
|
||||||
|
<!-- name needs to be exactly that to get the browser to use same completions as mastodon -->
|
||||||
|
<input type="text" placeholder="Enter your user@domain" required id="acct" name="remote_follow[acct]">
|
||||||
|
<input type="submit" value="Interact">
|
||||||
|
</form>
|
||||||
<noscript>
|
<noscript>
|
||||||
<p id="comments-js-warning">
|
<p id="comments-js-warning">
|
||||||
JavaScript is required to display comments.
|
JavaScript is required to display comments.
|
||||||
|
|
Loading…
Reference in New Issue