From 1e4659248f492ba23187810fc5a5c3554dbf29e7 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sun, 20 Feb 2022 01:19:28 -0500 Subject: [PATCH] statusNormalizer: fix mention to self --- app/soapbox/__fixtures__/alex.json | 127 ++++++++++++++++++ .../normalizers/__tests__/status-test.js | 15 +++ app/soapbox/normalizers/status.js | 20 +++ app/soapbox/utils/__tests__/accounts-test.js | 17 +++ app/soapbox/utils/accounts.js | 9 ++ 5 files changed, 188 insertions(+) create mode 100644 app/soapbox/__fixtures__/alex.json diff --git a/app/soapbox/__fixtures__/alex.json b/app/soapbox/__fixtures__/alex.json new file mode 100644 index 000000000..022978fde --- /dev/null +++ b/app/soapbox/__fixtures__/alex.json @@ -0,0 +1,127 @@ +{ + "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": 2378, + "following_count": 1571, + "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-02-20T04:14:49", + "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": 23477, + "url": "https://gleasonator.com/users/alex", + "username": "alex" +} diff --git a/app/soapbox/normalizers/__tests__/status-test.js b/app/soapbox/normalizers/__tests__/status-test.js index 580adc379..654354373 100644 --- a/app/soapbox/normalizers/__tests__/status-test.js +++ b/app/soapbox/normalizers/__tests__/status-test.js @@ -16,6 +16,21 @@ describe('normalizeStatus', () => { expect(result).toEqual(expected); }); + it('adds mention to self in self-reply on Mastodon', () => { + const status = fromJS(require('soapbox/__fixtures__/mastodon-reply-to-self.json')); + + const expected = fromJS([{ + id: '106801667066418367', + username: 'benis911', + acct: 'benis911', + url: 'https://mastodon.social/@benis911', + }]); + + const result = normalizeStatus(status).get('mentions'); + + expect(result).toEqual(expected); + }); + it('normalizes Mitra attachments', () => { const status = fromJS(require('soapbox/__fixtures__/mitra-status-with-attachments.json')); diff --git a/app/soapbox/normalizers/status.js b/app/soapbox/normalizers/status.js index 6b0018328..dc8886e35 100644 --- a/app/soapbox/normalizers/status.js +++ b/app/soapbox/normalizers/status.js @@ -1,5 +1,7 @@ import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; +import { accountToMention } from 'soapbox/utils/accounts'; + // Ensure attachments have required fields // https://docs.joinmastodon.org/entities/attachment/ const normalizeAttachment = attachment => { @@ -41,9 +43,27 @@ const fixMentions = status => { return status.set('mentions', sorted); }; +// Add self to mentions if it's a reply to self +const addSelfMention = status => { + const accountId = status.getIn(['account', 'id']); + + const isSelfReply = accountId === status.get('in_reply_to_account_id'); + const hasSelfMention = accountId === status.getIn(['mentions', 0, 'id']); + + if (isSelfReply && !hasSelfMention) { + const mention = accountToMention(status.get('account')); + return status.update('mentions', ImmutableList(), mentions => ( + ImmutableList([mention]).concat(mentions) + )); + } else { + return status; + } +}; + export const normalizeStatus = status => { return status.withMutations(status => { fixMentions(status); + addSelfMention(status); normalizeAttachments(status); }); }; diff --git a/app/soapbox/utils/__tests__/accounts-test.js b/app/soapbox/utils/__tests__/accounts-test.js index 15a42ec57..d3fd6f9ba 100644 --- a/app/soapbox/utils/__tests__/accounts-test.js +++ b/app/soapbox/utils/__tests__/accounts-test.js @@ -6,6 +6,7 @@ import { isStaff, isAdmin, isModerator, + accountToMention, } from '../accounts'; describe('getDomain', () => { @@ -115,3 +116,19 @@ describe('isModerator', () => { }); }); }); + +describe('accountToMention', () => { + it('converts the account to a mention', () => { + const account = fromJS(require('soapbox/__fixtures__/alex.json')); + + const expected = fromJS({ + id: '9v5bmRalQvjOy0ECcC', + username: 'alex', + acct: 'alex', + url: 'https://gleasonator.com/users/alex', + }); + + const result = accountToMention(account); + expect(result).toEqual(expected); + }); +}); diff --git a/app/soapbox/utils/accounts.js b/app/soapbox/utils/accounts.js index 6970f0050..3cf2c7cd5 100644 --- a/app/soapbox/utils/accounts.js +++ b/app/soapbox/utils/accounts.js @@ -67,3 +67,12 @@ export const isRemote = account => !isLocal(account); export const isVerified = account => ( account.getIn(['pleroma', 'tags'], ImmutableList()).includes('verified') ); + +export const accountToMention = account => { + return ImmutableMap({ + id: account.get('id'), + username: account.get('username'), + acct: account.get('acct'), + url: account.get('url'), + }); +};