bigbuffet-rw/app/soapbox/normalizers/account.ts

201 lines
6 KiB
TypeScript
Raw Normal View History

2022-03-12 13:01:00 -08:00
/**
* Account normalizer:
* Converts API accounts into our internal format.
* @see {@link https://docs.joinmastodon.org/entities/account/}
*/
2022-03-11 18:48:00 -08:00
import escapeTextContentForBrowser from 'escape-html';
2022-03-09 14:00:43 -08:00
import {
Map as ImmutableMap,
List as ImmutableList,
Record as ImmutableRecord,
2022-03-16 19:33:09 -07:00
fromJS,
2022-03-09 14:00:43 -08:00
} from 'immutable';
2022-03-11 18:48:00 -08:00
import emojify from 'soapbox/features/emoji/emoji';
import { normalizeEmoji } from 'soapbox/normalizers/emoji';
import { IAccount } from 'soapbox/types';
2022-03-11 18:48:00 -08:00
import { unescapeHTML } from 'soapbox/utils/html';
import { mergeDefined, makeEmojiMap } from 'soapbox/utils/normalizers';
2022-03-11 18:48:00 -08:00
// https://docs.joinmastodon.org/entities/account/
2022-03-16 19:15:38 -07:00
export const AccountRecord = ImmutableRecord({
2022-03-08 21:25:30 -08:00
acct: '',
avatar: '',
avatar_static: '',
birthday: undefined,
bot: false,
created_at: new Date(),
display_name: '',
emojis: ImmutableList(),
fields: ImmutableList(),
followers_count: 0,
following_count: 0,
fqn: '',
header: '',
header_static: '',
id: '',
last_status_at: new Date(),
location: '',
locked: false,
moved: null,
note: '',
pleroma: ImmutableMap(),
source: ImmutableMap(),
statuses_count: 0,
uri: '',
url: '',
username: '',
verified: false,
// Internal fields
display_name_html: '',
note_emojified: '',
note_plain: '',
2022-03-08 22:38:28 -08:00
patron: ImmutableMap(),
relationship: ImmutableList(),
2022-03-08 21:25:30 -08:00
should_refetch: false,
});
2022-03-11 18:48:00 -08:00
// https://docs.joinmastodon.org/entities/field/
2022-03-16 19:15:38 -07:00
export const FieldRecord = ImmutableRecord({
2022-03-11 18:48:00 -08:00
name: '',
value: '',
verified_at: null,
// Internal fields
name_emojified: '',
value_emojified: '',
value_plain: '',
});
// https://gitlab.com/soapbox-pub/soapbox-fe/-/issues/549
const normalizePleromaLegacyFields = (account: ImmutableMap<string, any>) => {
return account.update('pleroma', ImmutableMap(), (pleroma: ImmutableMap<string, any>) => {
return pleroma.withMutations(pleroma => {
const legacy = ImmutableMap({
is_active: !pleroma.get('deactivated'),
is_confirmed: !pleroma.get('confirmation_pending'),
is_approved: !pleroma.get('approval_pending'),
});
pleroma.mergeWith(mergeDefined, legacy);
pleroma.deleteAll(['deactivated', 'confirmation_pending', 'approval_pending']);
});
});
};
2022-03-11 18:48:00 -08:00
// Add avatar, if missing
const normalizeAvatar = (account: ImmutableMap<string, any>) => {
const avatar = account.get('avatar');
const avatarStatic = account.get('avatar_static');
const missing = require('images/avatar-missing.png');
return account.withMutations(account => {
account.set('avatar', avatar || avatarStatic || missing);
account.set('avatar_static', avatarStatic || avatar || missing);
});
};
// Normalize custom fields
const normalizeFields = (account: ImmutableMap<string, any>) => {
return account.update('fields', ImmutableList(), fields => fields.map(FieldRecord));
};
// Normalize emojis
const normalizeEmojis = (entity: ImmutableMap<string, any>) => {
const emojis = entity.get('emojis', ImmutableList()).map(normalizeEmoji);
return entity.set('emojis', emojis);
};
// Normalize Pleroma/Fedibird birthday
const normalizeBirthday = (account: ImmutableMap<string, any>) => {
2022-02-27 12:42:42 -08:00
const birthday = [
account.getIn(['pleroma', 'birthday']),
account.getIn(['other_settings', 'birthday']),
].find(Boolean);
return account.set('birthday', birthday);
};
// Get Pleroma tags
const getTags = (account: ImmutableMap<string, any>): ImmutableList<any> => {
const tags = account.getIn(['pleroma', 'tags']);
return ImmutableList(ImmutableList.isList(tags) ? tags : []);
};
// Normalize Truth Social/Pleroma verified
const normalizeVerified = (account: ImmutableMap<string, any>) => {
return account.update('verified', verified => {
return [
verified === true,
getTags(account).includes('verified'),
].some(Boolean);
});
};
// Normalize Fedibird/Truth Social/Pleroma location
const normalizeLocation = (account: ImmutableMap<string, any>) => {
2022-02-28 15:25:20 -08:00
return account.update('location', location => {
return [
location,
account.getIn(['pleroma', 'location']),
2022-02-28 15:25:20 -08:00
account.getIn(['other_settings', 'location']),
].find(Boolean);
});
};
2022-03-10 15:57:12 -08:00
// Set username from acct, if applicable
const fixUsername = (account: ImmutableMap<string, any>) => {
2022-03-11 18:48:00 -08:00
const acct = account.get('acct') || '';
const username = account.get('username') || '';
return account.set('username', username || acct.split('@')[0]);
};
// Set display name from username, if applicable
const fixDisplayName = (account: ImmutableMap<string, any>) => {
const displayName = account.get('display_name') || '';
return account.set('display_name', displayName.trim().length === 0 ? account.get('username') : displayName);
};
// Emojification, etc
const addInternalFields = (account: ImmutableMap<string, any>) => {
const emojiMap = makeEmojiMap(account.get('emojis'));
return account.withMutations((account: ImmutableMap<string, any>) => {
// Emojify account properties
account.merge({
display_name_html: emojify(escapeTextContentForBrowser(account.get('display_name')), emojiMap),
note_emojified: emojify(account.get('note', ''), emojiMap),
note_plain: unescapeHTML(account.get('note', '')),
});
// Emojify fields
account.update('fields', ImmutableList(), fields => {
return fields.map((field: ImmutableMap<string, any>) => {
return field.merge({
name_emojified: emojify(escapeTextContentForBrowser(field.get('name')), emojiMap),
value_emojified: emojify(field.get('value'), emojiMap),
value_plain: unescapeHTML(field.get('value')),
});
});
});
});
2022-03-10 15:57:12 -08:00
};
2022-03-16 19:33:09 -07:00
export const normalizeAccount = (account: Record<string, any>): IAccount => {
2022-03-08 21:25:30 -08:00
return AccountRecord(
2022-03-16 19:33:09 -07:00
ImmutableMap(fromJS(account)).withMutations(account => {
2022-03-08 21:25:30 -08:00
normalizePleromaLegacyFields(account);
2022-03-11 18:48:00 -08:00
normalizeEmojis(account);
normalizeAvatar(account);
normalizeFields(account);
2022-03-08 21:25:30 -08:00
normalizeVerified(account);
normalizeBirthday(account);
normalizeLocation(account);
2022-03-10 15:57:12 -08:00
fixUsername(account);
2022-03-11 18:48:00 -08:00
fixDisplayName(account);
addInternalFields(account);
2022-03-08 21:25:30 -08:00
}),
);
};