diff --git a/app/soapbox/__fixtures__/pleroma-status-with-poll.json b/app/soapbox/__fixtures__/pleroma-status-with-poll.json
new file mode 100644
index 000000000..452a5acb7
--- /dev/null
+++ b/app/soapbox/__fixtures__/pleroma-status-with-poll.json
@@ -0,0 +1,201 @@
+{
+ "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": [],
+ "fields": [
+ {
+ "name": "Website",
+ "value": "https://alexgleason.me"
+ },
+ {
+ "name": "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": 2465,
+ "following_count": 1581,
+ "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-10T18:19:50",
+ "locked": false,
+ "note": "I create Fediverse software that empowers people online.
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",
+ "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.\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": 23648,
+ "url": "https://gleasonator.com/users/alex",
+ "username": "alex"
+ },
+ "application": null,
+ "bookmarked": false,
+ "card": null,
+ "content": "
What is tolerance?
", + "created_at": "2020-03-23T19:33:06.000Z", + "emojis": [], + "favourited": false, + "favourites_count": 49, + "id": "103874034847713213", + "in_reply_to_account_id": null, + "in_reply_to_id": null, + "language": null, + "media_attachments": [], + "mentions": [], + "muted": false, + "pinned": true, + "pleroma": { + "content": { + "text/plain": "What is tolerance?" + }, + "conversation_id": "3023268", + "direct_conversation_id": null, + "emoji_reactions": [ + { + "count": 3, + "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": { + "emojis": [], + "expired": true, + "expires_at": "2020-03-24T19:33:06.000Z", + "id": "4930", + "multiple": false, + "options": [ + { + "title": "Banning, censoring, and deplatforming anyone you disagree with", + "votes_count": 2 + }, + { + "title": "Promoting free speech, even for people and ideas you dislike", + "votes_count": 36 + } + ], + "voters_count": 2, + "votes_count": 38 + }, + "reblog": null, + "reblogged": false, + "reblogs_count": 27, + "replies_count": 15, + "sensitive": false, + "spoiler_text": "", + "tags": [], + "text": null, + "uri": "https://gleasonator.com/users/alex/statuses/103874034847713213", + "url": "https://gleasonator.com/notice/103874034847713213", + "visibility": "public" +} diff --git a/app/soapbox/normalizers/__tests__/status-test.js b/app/soapbox/normalizers/__tests__/status-test.js index 26428e3ba..54117e167 100644 --- a/app/soapbox/normalizers/__tests__/status-test.js +++ b/app/soapbox/normalizers/__tests__/status-test.js @@ -1,4 +1,4 @@ -import { fromJS } from 'immutable'; +import { Record as ImmutableRecord, fromJS } from 'immutable'; import { normalizeStatus } from '../status'; @@ -7,12 +7,13 @@ describe('normalizeStatus', () => { const status = fromJS({}); const result = normalizeStatus(status); - expect(result.get('emojis')).toEqual(fromJS([])); - expect(result.get('favourites_count')).toBe(0); - expect(result.get('mentions')).toEqual(fromJS([])); - expect(result.get('reblog')).toBe(null); - expect(result.get('uri')).toBe(''); - expect(result.get('visibility')).toBe('public'); + expect(ImmutableRecord.isRecord(result)).toBe(true); + expect(result.emojis).toEqual(fromJS([])); + expect(result.favourites_count).toBe(0); + expect(result.mentions).toEqual(fromJS([])); + expect(result.reblog).toBe(null); + expect(result.uri).toBe(''); + expect(result.visibility).toBe('public'); }); it('fixes the order of mentions', () => { @@ -88,22 +89,22 @@ describe('normalizeStatus', () => { const result = normalizeStatus(status); - expect(result.get('media_attachments')).toEqual(expected); + expect(result.media_attachments).toEqual(expected); }); it('leaves Pleroma attachments alone', () => { const status = fromJS(require('soapbox/__fixtures__/pleroma-status-with-attachments.json')); const result = normalizeStatus(status); - expect(status.get('media_attachments')).toEqual(result.get('media_attachments')); + expect(status.get('media_attachments')).toEqual(result.media_attachments); }); it('normalizes Pleroma quote post', () => { const status = fromJS(require('soapbox/__fixtures__/pleroma-quote-post.json')); const result = normalizeStatus(status); - expect(result.get('quote')).toEqual(status.getIn(['pleroma', 'quote'])); - expect(result.getIn(['pleroma', 'quote'])).toBe(undefined); + expect(result.quote).toEqual(status.getIn(['pleroma', 'quote'])); + expect(result.pleroma.get('quote')).toBe(undefined); }); it('normalizes GoToSocial status', () => { @@ -119,7 +120,7 @@ describe('normalizeStatus', () => { quote: null, }; - expect(result.toJS()).toMatchObject(missing); + expect(result).toMatchObject(missing); }); it('normalizes Friendica status', () => { @@ -132,7 +133,7 @@ describe('normalizeStatus', () => { quote: null, }; - expect(result.toJS()).toMatchObject(missing); + expect(result).toMatchObject(missing); }); it('normalizes poll and poll options', () => { @@ -146,9 +147,22 @@ describe('normalizeStatus', () => { multiple: false, voters_count: 0, votes_count: 0, + own_votes: [], + voted: false, }; - expect(result.get('poll').toJS()).toMatchObject(expected); - expect(result.getIn(['poll', 'expires_at']) instanceof Date).toBe(true); + expect(ImmutableRecord.isRecord(result.poll)).toBe(true); + expect(ImmutableRecord.isRecord(result.poll.options.get(0))).toBe(true); + expect(result.poll.toJS()).toMatchObject(expected); + expect(result.poll.expires_at instanceof Date).toBe(true); + }); + + it('normalizes a Pleroma logged-out poll', () => { + const status = fromJS(require('soapbox/__fixtures__/pleroma-status-with-poll.json')); + const result = normalizeStatus(status); + + // Adds logged-in fields + expect(result.poll.voted).toBe(false); + expect(result.poll.own_votes).toEqual(fromJS([])); }); }); diff --git a/app/soapbox/normalizers/status.ts b/app/soapbox/normalizers/status.ts index 02c9b1f54..71210c502 100644 --- a/app/soapbox/normalizers/status.ts +++ b/app/soapbox/normalizers/status.ts @@ -47,16 +47,22 @@ const StatusRecord = ImmutableRecord({ spoilerHtml: '', }); -const basePollOption = ImmutableMap({ title: '', votes_count: 0 }); +const PollOptionRecord = ImmutableRecord({ + title: '', + votes_count: 0, +}); -const basePoll = ImmutableMap({ +// https://docs.joinmastodon.org/entities/poll/ +const PollRecord = ImmutableRecord({ emojis: ImmutableList(), expired: false, - expires_at: new Date(Date.now() + 1000 * (60 * 5)), // 5 minutes + expires_at: new Date(), multiple: false, options: ImmutableList(), voters_count: 0, votes_count: 0, + own_votes: ImmutableList(), + voted: false, }); // Ensure attachments have required fields @@ -100,23 +106,19 @@ const normalizeMentions = (status: ImmutableMap