import { create } from 'mutative'; import { type Instance, instanceSchema, PleromaConfig } from 'pl-api'; import * as v from 'valibot'; import { ADMIN_CONFIG_UPDATE_REQUEST, ADMIN_CONFIG_UPDATE_SUCCESS, type AdminActions } from 'pl-fe/actions/admin'; import { INSTANCE_FETCH_FAIL, INSTANCE_FETCH_SUCCESS, type InstanceAction } from 'pl-fe/actions/instance'; import { PLEROMA_PRELOAD_IMPORT, type PreloadAction } from 'pl-fe/actions/preload'; import KVStore from 'pl-fe/storage/kv-store'; import ConfigDB from 'pl-fe/utils/config-db'; const initialState: State = { fetched: false, ...v.parse(instanceSchema, {}) }; type State = Instance & { fetched: boolean }; const preloadImport = (state: State, action: PreloadAction, path: string): State => { const instance = action.data[path]; const parsedInstance = v.safeParse(instanceSchema, instance); if (parsedInstance.success) { return { fetched: true, ...parsedInstance.output }; } return state; }; const getConfigValue = (instanceConfig: Array, key: string) => { const v = instanceConfig .find(value => value?.tuple?.[0] === key); return v ? v?.tuple?.[1] : undefined; }; const importConfigs = (state: State, configs: PleromaConfig['configs']) => { // FIXME: This is pretty hacked together. Need to make a cleaner map. const config = ConfigDB.find(configs, ':pleroma', ':instance'); if (!config) return state; if (config) { const value = config.value || []; const registrationsOpen = getConfigValue(value, ':registrations_open') as boolean | undefined; const approvalRequired = getConfigValue(value, ':account_approval_required') as boolean | undefined; state.registrations = { ...state.registrations, enabled: registrationsOpen ?? state.registrations.enabled, approval_required: approvalRequired ?? state.registrations.approval_required, }; } }; const handleAuthFetch = (state: State) => { // Authenticated fetch is enabled, so make the instance appear censored return { ...state, title: state.title || '██████', description: state.description || '████████████', }; }; const getHost = (instance: { domain: string }) => { const domain = instance.domain; try { return new URL(domain).host; } catch { try { return new URL(`https://${domain}`).host; } catch { return null; } } }; const persistInstance = (instance: { domain: string }, host: string | null = getHost(instance)) => { if (host) { KVStore.setItem(`instance:${host}`, instance).catch(console.error); } }; const handleInstanceFetchFail = (state: State, error: any) => { if (error.response?.status === 401) { return handleAuthFetch(state); } else { return state; } }; const instance = (state = initialState, action: AdminActions | InstanceAction | PreloadAction): State => { switch (action.type) { case PLEROMA_PRELOAD_IMPORT: return preloadImport(state, action, '/api/v1/instance'); case INSTANCE_FETCH_SUCCESS: persistInstance(action.instance); return { fetched: true, ...action.instance }; case INSTANCE_FETCH_FAIL: return handleInstanceFetchFail(state, action.error); case ADMIN_CONFIG_UPDATE_REQUEST: case ADMIN_CONFIG_UPDATE_SUCCESS: return create(state, (draft) => importConfigs(draft, action.configs)); default: return state; } }; export { instance as default };