From 28ecb9d912236841c456dddd3d66edd8e9d65121 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sat, 12 Mar 2022 15:54:28 -0600 Subject: [PATCH] Normalize Card entity --- .../__fixtures__/status-with-card.json | 210 ++++++++++++++++++ .../normalizers/__tests__/card-test.js | 14 ++ .../normalizers/__tests__/status-test.js | 9 + app/soapbox/normalizers/card.ts | 28 +++ app/soapbox/normalizers/status.ts | 11 + 5 files changed, 272 insertions(+) create mode 100644 app/soapbox/__fixtures__/status-with-card.json create mode 100644 app/soapbox/normalizers/__tests__/card-test.js create mode 100644 app/soapbox/normalizers/card.ts diff --git a/app/soapbox/__fixtures__/status-with-card.json b/app/soapbox/__fixtures__/status-with-card.json new file mode 100644 index 000000000..da2f83b94 --- /dev/null +++ b/app/soapbox/__fixtures__/status-with-card.json @@ -0,0 +1,210 @@ +{ + "account": { + "acct": "alex", + "avatar": "https://media.gleasonator.com/6d64aecb17348b23aaff78db4687b9476cb0da1c07cc6a819c2e6ec7144c18b1.png", + "avatar_static": "https://media.gleasonator.com/6d64aecb17348b23aaff78db4687b9476cb0da1c07cc6a819c2e6ec7144c18b1.png", + "bot": false, + "created_at": "2020-01-08T01:25:43.000Z", + "display_name": "Alex Gleason", + "emojis": [ + { + "shortcode": "soapbox", + "static_url": "https://gleasonator.com/emoji/Gleasonator/soapbox.png", + "url": "https://gleasonator.com/emoji/Gleasonator/soapbox.png", + "visible_in_picker": false + } + ], + "fields": [ + { + "name": "Website", + "value": "https://alexgleason.me" + }, + { + "name": "Soapbox :soapbox:", + "value": "https://soapbox.pub" + }, + { + "name": "Email", + "value": "alex@alexgleason.me" + }, + { + "name": "Gender identity", + "value": "Soyboy" + }, + { + "name": "Donate (PayPal)", + "value": "https://paypal.me/gleasonator" + }, + { + "name": "$BTC", + "value": "bc1q9cx35adpm73aq2fw40ye6ts8hfxqzjr5unwg0n" + }, + { + "name": "$ETH", + "value": "0xAc9aB5Fc04Dc1cB1789Af75b523Bd23C70B2D717" + }, + { + "name": "$DOGE", + "value": "D5zVZs6jrRakaPVGiErkQiHt9sayzm6V5D" + }, + { + "name": "$XMR", + "value": "45JDCLrjJ4bgVUSbbs2yjy9m5Mf4VLPW8fG7jw9sq5u69rXZZopQogZNeyYkMBnXpkaip4p4QwaaJNhdTotPa9g44DBCzdK" + } + ], + "followers_count": 2476, + "following_count": 1584, + "fqn": "alex@gleasonator.com", + "header": "https://media.gleasonator.com/accounts/headers/000/000/001/original/9d0e4dbf1c9dbc8f.png", + "header_static": "https://media.gleasonator.com/accounts/headers/000/000/001/original/9d0e4dbf1c9dbc8f.png", + "id": "9v5bmRalQvjOy0ECcC", + "last_status_at": "2022-03-12T16:35:10", + "locked": false, + "note": "I create Fediverse software that empowers people online. :soapbox:

I'm vegan btw

Note: If you have a question for me, please tag me publicly. This gives the opportunity for others to chime in, and bystanders to learn.", + "pleroma": { + "accepts_chat_messages": true, + "also_known_as": [ + "https://mitra.social/users/alex" + ], + "ap_id": "https://gleasonator.com/users/alex", + "background_image": null, + "birthday": "1993-07-03", + "favicon": "https://gleasonator.com/favicon.png", + "hide_favorites": true, + "hide_followers": false, + "hide_followers_count": false, + "hide_follows": false, + "hide_follows_count": false, + "is_admin": true, + "is_confirmed": true, + "is_moderator": false, + "is_suggested": true, + "relationship": {}, + "skip_thread_containment": false, + "tags": [] + }, + "source": { + "fields": [ + { + "name": "Website", + "value": "https://alexgleason.me" + }, + { + "name": "Soapbox :soapbox:", + "value": "https://soapbox.pub" + }, + { + "name": "Email", + "value": "alex@alexgleason.me" + }, + { + "name": "Gender identity", + "value": "Soyboy" + }, + { + "name": "Donate (PayPal)", + "value": "https://paypal.me/gleasonator" + }, + { + "name": "$BTC", + "value": "bc1q9cx35adpm73aq2fw40ye6ts8hfxqzjr5unwg0n" + }, + { + "name": "$ETH", + "value": "0xAc9aB5Fc04Dc1cB1789Af75b523Bd23C70B2D717" + }, + { + "name": "$DOGE", + "value": "D5zVZs6jrRakaPVGiErkQiHt9sayzm6V5D" + }, + { + "name": "$XMR", + "value": "45JDCLrjJ4bgVUSbbs2yjy9m5Mf4VLPW8fG7jw9sq5u69rXZZopQogZNeyYkMBnXpkaip4p4QwaaJNhdTotPa9g44DBCzdK" + } + ], + "note": "I create Fediverse software that empowers people online. :soapbox:\r\n\r\nI'm vegan btw\r\n\r\nNote: If you have a question for me, please tag me publicly. This gives the opportunity for others to chime in, and bystanders to learn.", + "pleroma": { + "actor_type": "Person", + "discoverable": false + }, + "sensitive": false + }, + "statuses_count": 23674, + "url": "https://gleasonator.com/users/alex", + "username": "alex" + }, + "application": null, + "bookmarked": false, + "card": { + "author_name": "Alex Gleason", + "author_url": "https://soapbox.pub/author/alex/", + "blurhash": null, + "description": "On cryptocurrency I’ve always believed integrated donations would be a necessary part of the Fediverse. Admins do all the heavy lifting; it’s a thankless job. Meanwhile users want to help secure their new online home, but feel powerless to do so. I have been running an experimental payment platform based on Stripe alongside my Soapbox […]", + "embed_url": null, + "height": 338, + "html": "", + "image": "https://gleasonator.com/proxy/L2kUi5uxMdoC6LYYrnAdlJviPGQ/aHR0cHM6Ly9tZWRpYS5zb2FwYm94LnB1Yi91cGxvYWRzLzIwMjEvMDcvdi0xLTMtdGh1bWIucG5n/v-1-3-thumb.png", + "provider_name": "Soapbox", + "provider_url": "https://soapbox.pub", + "title": "Soapbox FE v1.3: The Crypto Release - Soapbox", + "type": "link", + "url": "https://soapbox.pub/blog/soapbox-fe-v1.3-cryptocurrency-release/", + "width": 600 + }, + "content": "

Soapbox FE v1.3 released. Read about it here: https://soapbox.pub/blog/soapbox-fe-v1.3-cryptocurrency-release/

Enjoy!

", + "created_at": "2021-07-02T20:49:39.000Z", + "emojis": [], + "favourited": false, + "favourites_count": 29, + "id": "A8tEMYF2GNnfPcL4dc", + "in_reply_to_account_id": null, + "in_reply_to_id": null, + "language": null, + "media_attachments": [], + "mentions": [], + "muted": false, + "pinned": true, + "pleroma": { + "content": { + "text/plain": "Soapbox FE v1.3 released. Read about it here: https://soapbox.pub/blog/soapbox-fe-v1.3-cryptocurrency-release/Enjoy!" + }, + "conversation_id": "16496668", + "direct_conversation_id": null, + "emoji_reactions": [ + { + "count": 5, + "me": false, + "name": "❤️" + }, + { + "count": 1, + "me": false, + "name": "👍" + } + ], + "expires_at": null, + "in_reply_to_account_acct": null, + "local": true, + "parent_visible": false, + "pinned_at": "2021-11-23T01:38:44.000Z", + "quote": null, + "quote_url": null, + "quote_visible": false, + "spoiler_text": { + "text/plain": "" + }, + "thread_muted": false + }, + "poll": null, + "reblog": null, + "reblogged": false, + "reblogs_count": 16, + "replies_count": 7, + "sensitive": false, + "spoiler_text": "", + "tags": [], + "text": null, + "uri": "https://gleasonator.com/objects/3eabaf63-47f4-4314-9ddb-ce7dbf46b393", + "url": "https://gleasonator.com/notice/A8tEMYF2GNnfPcL4dc", + "visibility": "public" +} diff --git a/app/soapbox/normalizers/__tests__/card-test.js b/app/soapbox/normalizers/__tests__/card-test.js new file mode 100644 index 000000000..e8ac120b0 --- /dev/null +++ b/app/soapbox/normalizers/__tests__/card-test.js @@ -0,0 +1,14 @@ +import { Record as ImmutableRecord, fromJS } from 'immutable'; + +import { normalizeCard } from '../card'; + +describe('normalizeCard()', () => { + it('adds base fields', () => { + const card = fromJS({}); + const result = normalizeCard(card); + + expect(ImmutableRecord.isRecord(result)).toBe(true); + expect(result.type).toEqual('link'); + expect(result.url).toEqual(''); + }); +}); diff --git a/app/soapbox/normalizers/__tests__/status-test.js b/app/soapbox/normalizers/__tests__/status-test.js index fc8b351f2..2824615cc 100644 --- a/app/soapbox/normalizers/__tests__/status-test.js +++ b/app/soapbox/normalizers/__tests__/status-test.js @@ -186,4 +186,13 @@ describe('normalizeStatus()', () => { expect(ImmutableRecord.isRecord(result.poll.emojis.get(0))).toBe(true); expect(result.poll.emojis.get(1).shortcode).toEqual('soapbox'); }); + + it('normalizes a card', () => { + const status = fromJS(require('soapbox/__fixtures__/status-with-card.json')); + const result = normalizeStatus(status); + + expect(ImmutableRecord.isRecord(result.card)).toBe(true); + expect(result.card.type).toEqual('link'); + expect(result.card.provider_url).toEqual('https://soapbox.pub'); + }); }); diff --git a/app/soapbox/normalizers/card.ts b/app/soapbox/normalizers/card.ts new file mode 100644 index 000000000..c9ac76adb --- /dev/null +++ b/app/soapbox/normalizers/card.ts @@ -0,0 +1,28 @@ +/** + * Card normalizer: + * Converts API cards into our internal format. + * @see {@link https://docs.joinmastodon.org/entities/card/} + */ +import { Record as ImmutableRecord, Map as ImmutableMap } from 'immutable'; + +// https://docs.joinmastodon.org/entities/card/ +const CardRecord = ImmutableRecord({ + author_name: '', + author_url: '', + blurhash: null, + description: '', + embed_url: '', + height: 0, + html: '', + image: null, + provider_name: '', + provider_url: '', + title: '', + type: 'link', + url: '', + width: 0, +}); + +export const normalizeCard = (card: ImmutableMap) => { + return CardRecord(card); +}; diff --git a/app/soapbox/normalizers/status.ts b/app/soapbox/normalizers/status.ts index 4cbf83e5b..2a1039f45 100644 --- a/app/soapbox/normalizers/status.ts +++ b/app/soapbox/normalizers/status.ts @@ -10,6 +10,7 @@ import { } from 'immutable'; import { normalizeAttachment } from 'soapbox/normalizers/attachment'; +import { normalizeCard } from 'soapbox/normalizers/card'; import { normalizeEmoji } from 'soapbox/normalizers/emoji'; import { normalizeMention } from 'soapbox/normalizers/mention'; import { normalizePoll } from 'soapbox/normalizers/poll'; @@ -83,6 +84,15 @@ const normalizeStatusPoll = (status: ImmutableMap) => { } }; +// Normalize card +const normalizeStatusCard = (status: ImmutableMap) => { + if (status.get('card')) { + return status.update('card', ImmutableMap(), normalizeCard); + } else { + return status.set('card', null); + } +}; + // Fix order of mentions const fixMentionsOrder = (status: ImmutableMap) => { const mentions = status.get('mentions', ImmutableList()); @@ -132,6 +142,7 @@ export const normalizeStatus = (status: ImmutableMap): IStatus => { normalizeMentions(status); normalizeEmojis(status); normalizeStatusPoll(status); + normalizeStatusCard(status); fixMentionsOrder(status); addSelfMention(status); fixQuote(status);