From cb0fc3e11d8e6490a3618061b74f1477740a5949 Mon Sep 17 00:00:00 2001 From: Nikita Karamov Date: Sat, 18 Mar 2023 04:14:14 +0100 Subject: [PATCH] Kinda implement Hubzilla? --- src/pages/api/detect/[host].ts | 135 ++++++++++++++++++++++++--------- 1 file changed, 100 insertions(+), 35 deletions(-) diff --git a/src/pages/api/detect/[host].ts b/src/pages/api/detect/[host].ts index 19631bc..ec90055 100644 --- a/src/pages/api/detect/[host].ts +++ b/src/pages/api/detect/[host].ts @@ -3,39 +3,93 @@ * Licensed under AGPL v3 or later */ -import { APIRoute } from "astro"; +import type { APIRoute } from "astro"; import { normalizeURL } from "../../../util"; -const PROJECTS = { - mastodon: { - checkUrl: "/api/v1/instance/rules", - publishEndpoint: "share", - params: { - text: "text", +interface FediverseProjectBasic { + publishEndpoint: string; + params: { + text: string; + }; +} + +interface FediverseProjectCheckFunction extends FediverseProjectBasic { + check: (url: string) => Promise; +} + +interface FediverseProjectCheckUrl extends FediverseProjectBasic { + checkUrl: string; +} + +type FediverseProject = + | FediverseProjectCheckUrl + | FediverseProjectCheckFunction; + +const PROJECTS: Map = new Map([ + [ + "mastodon", + { + checkUrl: "/api/v1/instance/rules", + publishEndpoint: "share", + params: { + text: "text", + }, }, - }, - gnuSocial: { - checkUrl: "/api/gnusocial/config.xml", - publishEndpoint: "/notice/new", - params: { - text: "status_textarea", + ], + [ + "gnuSocial", + { + checkUrl: "/api/gnusocial/config.xml", + publishEndpoint: "/notice/new", + params: { + text: "status_textarea", + }, }, - }, - pleroma: { - checkUrl: "/api/v1/pleroma/federation_status", - publishEndpoint: "share", - params: { - text: "message", + ], + [ + "pleroma", + { + checkUrl: "/api/v1/pleroma/federation_status", + publishEndpoint: "share", + params: { + text: "message", + }, }, - }, - friendica: { - checkUrl: "/api/statusnet/config", - publishEndpoint: "compose", - params: { - text: "body", + ], + [ + "friendica", + { + checkUrl: "/api/statusnet/config", + publishEndpoint: "compose", + params: { + text: "body", + }, }, - }, -}; + ], + [ + "hubzilla", + { + check: async (url: string): Promise => { + const response = await fetch(url); + const htmlBody = await response.text(); + console.debug(htmlBody); + if ( + htmlBody.includes( + '', + ) + ) { + return "hubzilla"; + } + throw new Error(`${url} doesn't host Hubzilla`); + }, + checkUrl: "/.well-known/zot-info", + publishEndpoint: "rpost", + params: { + text: "body", + }, + }, + ], +]); const checkProjectUrl = ( urlToCheck: URL, @@ -57,19 +111,30 @@ const checkProjectUrl = ( }; export const get: APIRoute = async ({ params }) => { - const host = params.host; + const host = params.host as string; - const promises = Object.entries(PROJECTS).map(([service, { checkUrl }]) => - checkProjectUrl(new URL(checkUrl, normalizeURL(host)), service), - ); + const promises = Object.entries(PROJECTS).map(([service, project]) => { + const url = normalizeURL(host); + if (project.check !== undefined) { + return project.check(url); + } + return checkProjectUrl(new URL(project.checkUrl, url), service); + }); try { - const project = await Promise.any(promises); + const projectId = await Promise.any(promises); + + if (!PROJECTS.has(projectId)) { + throw new Error(`Unexpected project ID: ${projectId}`); + } + + const project = PROJECTS.get(projectId) as FediverseProject; + return new Response( JSON.stringify({ host, - project, - publishEndpoint: PROJECTS[project].publishEndpoint, - params: PROJECTS[project].params, + project: projectId, + publishEndpoint: project.publishEndpoint, + params: project.params, }), { status: 200,