mirror of
https://github.com/MbinOrg/mbin-website.git
synced 2025-06-30 15:18:54 +00:00
Add fedidb.org as server list source, add title to webpages
This commit is contained in:
parent
e118d9d5cd
commit
ed7d5303a0
5 changed files with 119 additions and 59 deletions
|
@ -1,4 +1,3 @@
|
||||||
import { clientOnly } from '@solidjs/start';
|
|
||||||
import { ParentComponent } from 'solid-js';
|
import { ParentComponent } from 'solid-js';
|
||||||
import { SolidMarkdown } from 'solid-markdown';
|
import { SolidMarkdown } from 'solid-markdown';
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// @refresh reload
|
// @refresh reload
|
||||||
import { createHandler, StartServer } from "@solidjs/start/server";
|
import { createHandler, StartServer } from '@solidjs/start/server';
|
||||||
|
|
||||||
export default createHandler(() => (
|
export default createHandler(() => (
|
||||||
<StartServer
|
<StartServer
|
||||||
|
@ -9,6 +9,7 @@ export default createHandler(() => (
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
<title>Join Mbin</title>
|
||||||
{assets}
|
{assets}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
162
src/initdata.js
162
src/initdata.js
|
@ -3,7 +3,14 @@ import fs from 'node:fs/promises';
|
||||||
await fs.rm('./.output/data', { recursive: true, force: true });
|
await fs.rm('./.output/data', { recursive: true, force: true });
|
||||||
await fs.mkdir('./.output/data', { recursive: true });
|
await fs.mkdir('./.output/data', { recursive: true });
|
||||||
|
|
||||||
const initServerData = async () => {
|
/**
|
||||||
|
* @returns {Promise<string>}
|
||||||
|
*/
|
||||||
|
const fetchServerList = async () => {
|
||||||
|
/** @type Set<string> */
|
||||||
|
const servers = new Set();
|
||||||
|
|
||||||
|
// Fetch Mbin servers from fediverse.observer
|
||||||
const fediverseObserver = await (
|
const fediverseObserver = await (
|
||||||
await fetch('https://api.fediverse.observer/', {
|
await fetch('https://api.fediverse.observer/', {
|
||||||
body: '{"query":"{nodes(softwarename:\\"mbin\\" status: \\"UP\\"){domain}}"}',
|
body: '{"query":"{nodes(softwarename:\\"mbin\\" status: \\"UP\\"){domain}}"}',
|
||||||
|
@ -11,65 +18,118 @@ const initServerData = async () => {
|
||||||
})
|
})
|
||||||
).json();
|
).json();
|
||||||
|
|
||||||
/** @type string[] */
|
for (const server of fediverseObserver.data.nodes) {
|
||||||
const servers = fediverseObserver.data.nodes.map((v) => v.domain);
|
servers.add(server.domain);
|
||||||
|
}
|
||||||
|
|
||||||
const serversJson = (
|
// Fetch Mbin servers from fedidb.org. The api used below is not documented and is subject to change;
|
||||||
await Promise.allSettled(
|
// this is used due to the current publicized api not being sufficient for fetching Mbin server lists.
|
||||||
servers.map(async (serverHost) => {
|
// Once issue #3 (https://github.com/fedidb/issues/issues/3) is complete, then we can move to api v1.
|
||||||
console.log('START:', serverHost);
|
const fedidbCookies = (await fetch('https://fedidb.org')).headers
|
||||||
|
.getSetCookie()
|
||||||
|
.map((c) => c.split(';')[0]);
|
||||||
|
|
||||||
const jsonNodeInfo = await (
|
const fedidbHeaders = {
|
||||||
await fetch(`https://${serverHost}/nodeinfo/2.1.json`)
|
Accept: 'application/json',
|
||||||
).json();
|
'Content-Type': 'application/json',
|
||||||
|
'X-XSRF-TOKEN': decodeURIComponent(
|
||||||
|
fedidbCookies
|
||||||
|
.find((c) => c.startsWith('XSRF-TOKEN='))
|
||||||
|
.substring('XSRF-TOKEN='.length),
|
||||||
|
),
|
||||||
|
Cookie: fedidbCookies.join('; '),
|
||||||
|
};
|
||||||
|
|
||||||
if (jsonNodeInfo.software.name != 'mbin') {
|
let fedidbNextCursor = '';
|
||||||
throw new Error(
|
|
||||||
`${serverHost} software does not match mbin (skipped)`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const jsonApiInfo = await (
|
do {
|
||||||
await fetch(`https://${serverHost}/api/info`)
|
const fedidbServers = await (
|
||||||
).json();
|
await fetch(
|
||||||
if (jsonApiInfo.websiteDomain != serverHost) {
|
`https://fedidb.org/api/web/network/software/servers${
|
||||||
throw new Error(`${serverHost} api not setup correctly (skipped)`);
|
fedidbNextCursor ? `?cursor=` + fedidbNextCursor : ''
|
||||||
}
|
}`,
|
||||||
const jsonApiInstance = await (
|
{
|
||||||
await fetch(`https://${serverHost}/api/instance`)
|
headers: fedidbHeaders,
|
||||||
).json();
|
body: '{"slug":"mbin"}',
|
||||||
const jsonApiDefederated = await (
|
method: 'POST',
|
||||||
await fetch(`https://${serverHost}/api/defederated`)
|
},
|
||||||
).json();
|
)
|
||||||
|
).json();
|
||||||
|
|
||||||
console.log('FINISH:', serverHost);
|
for (const server of fedidbServers.data) {
|
||||||
|
servers.add(server.domain);
|
||||||
|
}
|
||||||
|
|
||||||
/** @type import('./routes/servers').Server */
|
fedidbNextCursor = fedidbServers.meta.next_cursor;
|
||||||
const server = {
|
} while (fedidbNextCursor);
|
||||||
domain: serverHost,
|
|
||||||
version: jsonNodeInfo.software.version,
|
|
||||||
name: jsonNodeInfo.metadata.nodeName,
|
|
||||||
description: jsonNodeInfo.metadata.nodeDescription,
|
|
||||||
openRegistrations: jsonNodeInfo.openRegistrations,
|
|
||||||
federationEnabled: jsonApiInfo.websiteFederationEnabled,
|
|
||||||
language: jsonApiInfo.websiteDefaultLang ?? 'en',
|
|
||||||
contactEmail: jsonApiInfo.websiteContactEmail,
|
|
||||||
totalUsers: jsonNodeInfo.usage.users.total,
|
|
||||||
activeHalfyearUsers: jsonNodeInfo.usage.users.activeHalfyear,
|
|
||||||
activeMonthUsers: jsonNodeInfo.usage.users.activeMonth,
|
|
||||||
localPosts: jsonNodeInfo.usage.localPosts,
|
|
||||||
localComments: jsonNodeInfo.usage.localComments,
|
|
||||||
pages: jsonApiInstance,
|
|
||||||
defederated: jsonApiDefederated.instances ?? [],
|
|
||||||
};
|
|
||||||
|
|
||||||
return server;
|
return [...servers];
|
||||||
}),
|
};
|
||||||
)
|
|
||||||
)
|
/**
|
||||||
.filter((v) => v.status == 'fulfilled')
|
* @param {string} domain
|
||||||
|
* @returns {Promise<import('./routes/servers').Server>}
|
||||||
|
*/
|
||||||
|
const fetchServerInfo = async (domain) => {
|
||||||
|
console.log('START:', domain);
|
||||||
|
|
||||||
|
const jsonNodeInfo = await (
|
||||||
|
await fetch(`https://${domain}/nodeinfo/2.1.json`)
|
||||||
|
).json();
|
||||||
|
|
||||||
|
if (jsonNodeInfo.software.name != 'mbin') {
|
||||||
|
throw new Error(`${domain} software does not match mbin (skipped)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const jsonApiInfo = await (await fetch(`https://${domain}/api/info`)).json();
|
||||||
|
if (jsonApiInfo.websiteDomain != domain) {
|
||||||
|
throw new Error(`${domain} api not setup correctly (skipped)`);
|
||||||
|
}
|
||||||
|
const jsonApiInstance = await (
|
||||||
|
await fetch(`https://${domain}/api/instance`)
|
||||||
|
).json();
|
||||||
|
const jsonApiDefederated = await (
|
||||||
|
await fetch(`https://${domain}/api/defederated`)
|
||||||
|
).json();
|
||||||
|
|
||||||
|
console.log('FINISH:', domain);
|
||||||
|
|
||||||
|
return {
|
||||||
|
domain: domain,
|
||||||
|
version: jsonNodeInfo.software.version,
|
||||||
|
name: jsonNodeInfo.metadata.nodeName,
|
||||||
|
description: jsonNodeInfo.metadata.nodeDescription,
|
||||||
|
openRegistrations: jsonNodeInfo.openRegistrations,
|
||||||
|
federationEnabled: jsonApiInfo.websiteFederationEnabled,
|
||||||
|
language: jsonApiInfo.websiteDefaultLang ?? 'en',
|
||||||
|
contactEmail: jsonApiInfo.websiteContactEmail,
|
||||||
|
totalUsers: jsonNodeInfo.usage.users.total,
|
||||||
|
activeHalfyearUsers: jsonNodeInfo.usage.users.activeHalfyear,
|
||||||
|
activeMonthUsers: jsonNodeInfo.usage.users.activeMonth,
|
||||||
|
localPosts: jsonNodeInfo.usage.localPosts,
|
||||||
|
localComments: jsonNodeInfo.usage.localComments,
|
||||||
|
pages: jsonApiInstance,
|
||||||
|
defederated: jsonApiDefederated.instances ?? [],
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const initServerData = async () => {
|
||||||
|
const servers = await fetchServerList();
|
||||||
|
|
||||||
|
const serversJson = (await Promise.allSettled(servers.map(fetchServerInfo)))
|
||||||
|
.filter((v) => {
|
||||||
|
const isOk = v.status == 'fulfilled';
|
||||||
|
|
||||||
|
if (!isOk) {
|
||||||
|
console.error(v.reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
return isOk;
|
||||||
|
})
|
||||||
.map((v) => v.value);
|
.map((v) => v.value);
|
||||||
|
|
||||||
|
console.log('Successful Mbin servers found:', serversJson.length);
|
||||||
|
|
||||||
fs.writeFile(
|
fs.writeFile(
|
||||||
'./.output/data/servers.json',
|
'./.output/data/servers.json',
|
||||||
JSON.stringify(serversJson),
|
JSON.stringify(serversJson),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import type { ClassValue } from "clsx"
|
import type { ClassValue } from 'clsx';
|
||||||
import { clsx } from "clsx"
|
import { clsx } from 'clsx';
|
||||||
import { twMerge } from "tailwind-merge"
|
import { twMerge } from 'tailwind-merge';
|
||||||
|
|
||||||
export function cn(...inputs: ClassValue[]) {
|
export function cn(...inputs: ClassValue[]) {
|
||||||
return twMerge(clsx(inputs))
|
return twMerge(clsx(inputs));
|
||||||
}
|
}
|
|
@ -7,7 +7,7 @@ export default function Home() {
|
||||||
Mbin
|
Mbin
|
||||||
</h1>
|
</h1>
|
||||||
<p class="my-10 text-2xl text-gray-400 block mx-auto">
|
<p class="my-10 text-2xl text-gray-400 block mx-auto">
|
||||||
a federated content aggregator, voting, discussion and microblogging
|
A federated content aggregator, voting, discussion and microblogging
|
||||||
platform
|
platform
|
||||||
<br />
|
<br />
|
||||||
(By the community, for the community)
|
(By the community, for the community)
|
||||||
|
|
Loading…
Add table
Reference in a new issue