2022-04-25 11:57:24 -07:00
|
|
|
import { createAsyncThunk } from '@reduxjs/toolkit';
|
2022-06-16 12:32:17 -07:00
|
|
|
import get from 'lodash/get';
|
2023-10-27 12:18:30 -07:00
|
|
|
import { gte } from 'semver';
|
2022-01-10 14:25:06 -08:00
|
|
|
|
2022-11-15 12:42:22 -08:00
|
|
|
import KVStore from 'soapbox/storage/kv-store';
|
2022-04-25 11:57:24 -07:00
|
|
|
import { RootState } from 'soapbox/store';
|
2023-07-20 13:03:23 -07:00
|
|
|
import { getAuthUserUrl, getMeUrl } from 'soapbox/utils/auth';
|
2023-10-27 12:18:30 -07:00
|
|
|
import { MASTODON, parseVersion, PLEROMA, REBASED } from 'soapbox/utils/features';
|
2022-03-18 14:04:08 -07:00
|
|
|
|
2022-01-10 14:01:24 -08:00
|
|
|
import api from '../api';
|
2021-10-20 11:18:55 -07:00
|
|
|
|
2022-04-25 11:57:24 -07:00
|
|
|
/** Figure out the appropriate instance to fetch depending on the state */
|
2022-03-15 06:48:18 -07:00
|
|
|
export const getHost = (state: RootState) => {
|
2022-12-25 15:31:07 -08:00
|
|
|
const accountUrl = getMeUrl(state) || getAuthUserUrl(state) as string;
|
2021-10-20 11:18:55 -07:00
|
|
|
|
|
|
|
try {
|
|
|
|
return new URL(accountUrl).host;
|
|
|
|
} catch {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-04-25 11:57:24 -07:00
|
|
|
export const rememberInstance = createAsyncThunk(
|
|
|
|
'instance/remember',
|
|
|
|
async(host: string) => {
|
2023-10-27 12:18:30 -07:00
|
|
|
const instance = await KVStore.getItemOrError(`instance:${host}`);
|
|
|
|
|
|
|
|
return { instance, host };
|
2022-04-25 11:57:24 -07:00
|
|
|
},
|
|
|
|
);
|
2021-10-20 11:18:55 -07:00
|
|
|
|
2023-10-27 12:18:30 -07:00
|
|
|
const supportsInstanceV2 = (instance: Record<string, any>): boolean => {
|
|
|
|
const v = parseVersion(get(instance, 'version'));
|
|
|
|
return (v.software === MASTODON && gte(v.compatVersion, '4.0.0')) ||
|
|
|
|
(v.software === PLEROMA && v.build === REBASED && gte(v.version, '2.5.54'));
|
|
|
|
};
|
|
|
|
|
2022-04-25 11:57:24 -07:00
|
|
|
/** We may need to fetch nodeinfo on Pleroma < 2.1 */
|
2022-03-15 06:48:18 -07:00
|
|
|
const needsNodeinfo = (instance: Record<string, any>): boolean => {
|
2021-10-20 13:17:02 -07:00
|
|
|
const v = parseVersion(get(instance, 'version'));
|
2023-10-27 12:18:30 -07:00
|
|
|
return v.software === PLEROMA && !get(instance, ['pleroma', 'metadata']);
|
2021-10-20 13:17:02 -07:00
|
|
|
};
|
|
|
|
|
2023-10-27 12:18:30 -07:00
|
|
|
export const fetchInstance = createAsyncThunk<{ instance: Record<string, any>; host?: string | null }, string | null | undefined, { state: RootState }>(
|
2022-04-25 11:57:24 -07:00
|
|
|
'instance/fetch',
|
2023-10-27 12:18:30 -07:00
|
|
|
async(host, { dispatch, getState, rejectWithValue }) => {
|
2022-05-02 09:46:18 -07:00
|
|
|
try {
|
|
|
|
const { data: instance } = await api(getState).get('/api/v1/instance');
|
2023-10-27 12:18:30 -07:00
|
|
|
|
|
|
|
if (supportsInstanceV2(instance)) {
|
|
|
|
return dispatch(fetchInstanceV2(host)) as any as { instance: Record<string, any>; host?: string | null };
|
|
|
|
}
|
|
|
|
|
2022-05-02 09:46:18 -07:00
|
|
|
if (needsNodeinfo(instance)) {
|
|
|
|
dispatch(fetchNodeinfo());
|
|
|
|
}
|
2023-10-27 12:18:30 -07:00
|
|
|
return { instance, host };
|
|
|
|
} catch (e) {
|
|
|
|
return rejectWithValue(e);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
);
|
|
|
|
|
|
|
|
export const fetchInstanceV2 = createAsyncThunk<{ instance: Record<string, any>; host?: string | null }, string | null | undefined, { state: RootState }>(
|
|
|
|
'instance/fetch',
|
|
|
|
async(host, { getState, rejectWithValue }) => {
|
|
|
|
try {
|
|
|
|
const { data: instance } = await api(getState).get('/api/v2/instance');
|
|
|
|
return { instance, host };
|
2022-05-11 10:40:34 -07:00
|
|
|
} catch (e) {
|
2022-05-02 09:46:18 -07:00
|
|
|
return rejectWithValue(e);
|
2022-04-25 11:57:24 -07:00
|
|
|
}
|
|
|
|
},
|
|
|
|
);
|
2020-04-01 13:05:52 -07:00
|
|
|
|
2022-04-25 11:57:24 -07:00
|
|
|
/** Tries to remember the instance from browser storage before fetching it */
|
|
|
|
export const loadInstance = createAsyncThunk<void, void, { state: RootState }>(
|
|
|
|
'instance/load',
|
|
|
|
async(_arg, { dispatch, getState }) => {
|
2021-10-20 11:18:55 -07:00
|
|
|
const host = getHost(getState());
|
2023-10-27 12:18:30 -07:00
|
|
|
const rememberedInstance = await dispatch(rememberInstance(host || ''));
|
|
|
|
|
|
|
|
if (rememberedInstance.payload && supportsInstanceV2((rememberedInstance.payload as any).instance)) {
|
|
|
|
await dispatch(fetchInstanceV2(host));
|
2023-10-28 03:13:31 -07:00
|
|
|
} else {
|
|
|
|
await dispatch(fetchInstance(host));
|
|
|
|
}
|
2022-04-25 11:57:24 -07:00
|
|
|
},
|
|
|
|
);
|
2021-10-20 11:18:55 -07:00
|
|
|
|
2022-10-27 10:46:03 -07:00
|
|
|
export const fetchNodeinfo = createAsyncThunk<void, void, { state: RootState }>(
|
|
|
|
'nodeinfo/fetch',
|
|
|
|
async(_arg, { getState }) => await api(getState).get('/nodeinfo/2.1.json'),
|
|
|
|
);
|