campfire/src/lib/client/server.js

143 lines
4 KiB
JavaScript

import * as api from '$lib/api.js';
import { writable } from 'svelte/store';
import { app_name } from '$lib/config.js';
import { browser } from "$app/environment";
const server_types = {
UNSUPPORTED: "unsupported",
MASTODON: "mastodon",
GLITCHSOC: "glitchsoc",
CHUCKYA: "chuckya",
FIREFISH: "firefish",
ICESHRIMP: "iceshrimp",
SHARKEY: "sharkey",
AKKOMA: "akkoma", // TODO: verify
PLEROMA: "pleroma", // TODO: verify
};
export const capabilities = {
MARKDOWN_CONTENT: "markdown_content",
REACTIONS: "reactions",
FOREIGN_REACTIONS: "foreign_reactions",
};
// if server is falsy, assume user has not begun the login process.
export let server = writable(loadServer());
// write to localStorage on each update
server.subscribe(server => {
saveServer(server);
});
/**
* Attempts to create an server object using a given hostname.
* @param {string} host - The domain of the target server.
*/
export async function createServer(host) {
if (!host) {
console.error("Attempted to create server without providing a hostname");
return false;
}
if (host.startsWith("http://")) {
console.error("Cowardly refusing to connect to an insecure server");
return false;
}
let server = {};
server.host = host;
if (host.startsWith("https://")) host = host.substring(8);
const data = await api.getInstance(host);
if (!data) {
console.error(`Failed to connect to ${host}`);
return false;
}
server.version = data.version;
server.type = getType(server.version);
server.capabilities = getCapabilities(server.type);
if (server.type === server_types.UNSUPPORTED) {
console.warn(`Server ${host} is unsupported (${server.version}). Things may break, or not work as expected`);
} else {
console.log(`Server detected as "${server.type}" (${server.version}) with capabilities: {${server.capabilities.join(', ')}}`);
}
return server;
}
/**
* Saves the provided server to localStorage.
* If `server` is falsy, data is removed from localStorage.
* @param {Object} server
*/
function saveServer(server) {
if (!browser) return;
if (!server) {
localStorage.removeItem(app_name + "_server");
return;
}
localStorage.setItem(app_name + "_server", JSON.stringify(server));
}
/**
* Returns server data loaded from localStorage, if it exists.
* Otherwise, returns false.
*/
function loadServer() {
if (!browser) return;
let data = localStorage.getItem(app_name + "_server");
if (!data) return false;
return JSON.parse(data);
}
/**
* Returns the type of an server, inferred from its version string.
* @param {string} version
* @returns the inferred server_type
*/
function getType(version) {
if (version.constructor !== String) return;
let version_lower = version.toLowerCase();
for (let i = 1; i < Object.keys(server_types).length; i++) {
const type = Object.values(server_types)[i];
if (version_lower.includes(type)) {
return type;
}
}
return server_types.UNSUPPORTED;
}
/**
* Returns a list of capabilities for a given server_type.
* @param {string} type
*/
function getCapabilities(type) {
let c = [];
switch (type) {
case server_types.MASTODON:
break;
case server_types.GLITCHSOC:
c.push(capabilities.REACTIONS);
break;
case server_types.CHUCKYA:
c.push(capabilities.REACTIONS);
c.push(capabilities.FOREIGN_REACTIONS);
break;
case server_types.FIREFISH:
c.push(capabilities.REACTIONS);
break;
case server_types.ICESHRIMP:
// more trouble than it's worth atm
// mastodon API already hands html to us
//c.push(capabilities.MARKDOWN_CONTENT);
c.push(capabilities.REACTIONS);
break;
case server_types.SHARKEY:
c.push(capabilities.REACTIONS);
break;
default:
break;
}
return c;
}