From f1ab70649b00e717a00ac295d42ff99160aa713b Mon Sep 17 00:00:00 2001 From: Eugen Rochko <eugen@zeonfederated.com> Date: Fri, 19 May 2017 21:05:32 +0200 Subject: [PATCH] Add buttons to block and unblock domain (#3127) * Add buttons to block and unblock domain * Relationship API now returns "domain_blocking" status for accounts, rename "block entire domain" to "hide entire domain", fix unblocking domain, do not block notifications from domain-blocked-but-followed people, do not send Salmons to domain blocked users * Add test * Personal domain blocks shouldn't affect Salmon after all, since in this direction of communication the control is very thin when it comes to public stuff. Best stay consistent and not affect federation in this way * Ignore followers and follow request from domain blocked folks, ensure account domain blocks are not created for empty domain, and avoid duplicates in validation * Purge followers when blocking domain (without soft-blocks, since they are useless here) * Add tests, fix local timeline being empty when having any domain blocks --- app/controllers/api/v1/accounts_controller.rb | 35 +++--- .../api/v1/domain_blocks_controller.rb | 2 +- .../mastodon/actions/domain_blocks.js | 117 ++++++++++++++++++ .../features/account/components/action_bar.js | 15 ++- .../account_timeline/components/header.js | 22 +++- .../containers/header_container.js | 16 ++- app/javascript/mastodon/locales/ar.json | 5 + app/javascript/mastodon/locales/bg.json | 5 + app/javascript/mastodon/locales/ca.json | 5 + app/javascript/mastodon/locales/de.json | 5 + .../mastodon/locales/defaultMessages.json | 25 ++++ app/javascript/mastodon/locales/en.json | 5 + app/javascript/mastodon/locales/eo.json | 5 + app/javascript/mastodon/locales/es.json | 5 + app/javascript/mastodon/locales/fa.json | 5 + app/javascript/mastodon/locales/fi.json | 5 + app/javascript/mastodon/locales/fr.json | 5 + app/javascript/mastodon/locales/he.json | 5 + app/javascript/mastodon/locales/hr.json | 5 + app/javascript/mastodon/locales/hu.json | 5 + app/javascript/mastodon/locales/id.json | 5 + app/javascript/mastodon/locales/io.json | 5 + app/javascript/mastodon/locales/it.json | 5 + app/javascript/mastodon/locales/ja.json | 5 + app/javascript/mastodon/locales/nl.json | 5 + app/javascript/mastodon/locales/no.json | 5 + app/javascript/mastodon/locales/oc.json | 5 + app/javascript/mastodon/locales/pl.json | 5 + app/javascript/mastodon/locales/pt-BR.json | 5 + app/javascript/mastodon/locales/pt.json | 5 + app/javascript/mastodon/locales/ru.json | 5 + app/javascript/mastodon/locales/tr.json | 5 + app/javascript/mastodon/locales/uk.json | 5 + app/javascript/mastodon/locales/zh-CN.json | 5 + app/javascript/mastodon/locales/zh-HK.json | 5 + .../mastodon/reducers/relationships.js | 8 ++ app/models/account_domain_block.rb | 1 + app/models/concerns/account_interactions.rb | 6 + app/models/status.rb | 14 ++- .../block_domain_from_account_service.rb | 8 ++ app/services/notify_service.rb | 16 +-- app/services/process_interaction_service.rb | 4 +- app/services/send_interaction_service.rb | 14 ++- app/views/api/v1/accounts/relationship.rabl | 11 +- .../block_domain_from_account_service_spec.rb | 19 +++ spec/services/notify_service_spec.rb | 6 + 46 files changed, 436 insertions(+), 43 deletions(-) create mode 100644 app/javascript/mastodon/actions/domain_blocks.js create mode 100644 app/services/block_domain_from_account_service.rb create mode 100644 spec/services/block_domain_from_account_service_spec.rb diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb index 5724dbaea4..12c7dd2b08 100644 --- a/app/controllers/api/v1/accounts_controller.rb +++ b/app/controllers/api/v1/accounts_controller.rb @@ -71,11 +71,12 @@ class Api::V1::AccountsController < ApiController def block BlockService.new.call(current_user.account, @account) - @following = { @account.id => false } - @followed_by = { @account.id => false } - @blocking = { @account.id => true } - @requested = { @account.id => false } - @muting = { @account.id => current_user.account.muting?(@account.id) } + @following = { @account.id => false } + @followed_by = { @account.id => false } + @blocking = { @account.id => true } + @requested = { @account.id => false } + @muting = { @account.id => current_account.muting?(@account.id) } + @domain_blocking = { @account.id => current_account.domain_blocking?(@account.domain) } render :relationship end @@ -107,12 +108,13 @@ class Api::V1::AccountsController < ApiController def relationships ids = params[:id].is_a?(Enumerable) ? params[:id].map(&:to_i) : [params[:id].to_i] - @accounts = Account.where(id: ids).select('id') - @following = Account.following_map(ids, current_user.account_id) - @followed_by = Account.followed_by_map(ids, current_user.account_id) - @blocking = Account.blocking_map(ids, current_user.account_id) - @muting = Account.muting_map(ids, current_user.account_id) - @requested = Account.requested_map(ids, current_user.account_id) + @accounts = Account.where(id: ids).select('id') + @following = Account.following_map(ids, current_user.account_id) + @followed_by = Account.followed_by_map(ids, current_user.account_id) + @blocking = Account.blocking_map(ids, current_user.account_id) + @muting = Account.muting_map(ids, current_user.account_id) + @requested = Account.requested_map(ids, current_user.account_id) + @domain_blocking = Account.domain_blocking_map(ids, current_user.account_id) end def search @@ -128,11 +130,12 @@ class Api::V1::AccountsController < ApiController end def set_relationship - @following = Account.following_map([@account.id], current_user.account_id) - @followed_by = Account.followed_by_map([@account.id], current_user.account_id) - @blocking = Account.blocking_map([@account.id], current_user.account_id) - @muting = Account.muting_map([@account.id], current_user.account_id) - @requested = Account.requested_map([@account.id], current_user.account_id) + @following = Account.following_map([@account.id], current_user.account_id) + @followed_by = Account.followed_by_map([@account.id], current_user.account_id) + @blocking = Account.blocking_map([@account.id], current_user.account_id) + @muting = Account.muting_map([@account.id], current_user.account_id) + @requested = Account.requested_map([@account.id], current_user.account_id) + @domain_blocking = Account.domain_blocking_map([@account.id], current_user.account_id) end def pagination_params(core_params) diff --git a/app/controllers/api/v1/domain_blocks_controller.rb b/app/controllers/api/v1/domain_blocks_controller.rb index e14547911c..f223dd16ee 100644 --- a/app/controllers/api/v1/domain_blocks_controller.rb +++ b/app/controllers/api/v1/domain_blocks_controller.rb @@ -17,7 +17,7 @@ class Api::V1::DomainBlocksController < ApiController end def create - current_account.block_domain!(domain_block_params[:domain]) + BlockDomainFromAccountService.new.call(current_account, domain_block_params[:domain]) render_empty end diff --git a/app/javascript/mastodon/actions/domain_blocks.js b/app/javascript/mastodon/actions/domain_blocks.js new file mode 100644 index 0000000000..c884981176 --- /dev/null +++ b/app/javascript/mastodon/actions/domain_blocks.js @@ -0,0 +1,117 @@ +import api, { getLinks } from '../api' + +export const DOMAIN_BLOCK_REQUEST = 'DOMAIN_BLOCK_REQUEST'; +export const DOMAIN_BLOCK_SUCCESS = 'DOMAIN_BLOCK_SUCCESS'; +export const DOMAIN_BLOCK_FAIL = 'DOMAIN_BLOCK_FAIL'; + +export const DOMAIN_UNBLOCK_REQUEST = 'DOMAIN_UNBLOCK_REQUEST'; +export const DOMAIN_UNBLOCK_SUCCESS = 'DOMAIN_UNBLOCK_SUCCESS'; +export const DOMAIN_UNBLOCK_FAIL = 'DOMAIN_UNBLOCK_FAIL'; + +export const DOMAIN_BLOCKS_FETCH_REQUEST = 'DOMAIN_BLOCKS_FETCH_REQUEST'; +export const DOMAIN_BLOCKS_FETCH_SUCCESS = 'DOMAIN_BLOCKS_FETCH_SUCCESS'; +export const DOMAIN_BLOCKS_FETCH_FAIL = 'DOMAIN_BLOCKS_FETCH_FAIL'; + +export function blockDomain(domain, accountId) { + return (dispatch, getState) => { + dispatch(blockDomainRequest(domain)); + + api(getState).post('/api/v1/domain_blocks', { domain }).then(response => { + dispatch(blockDomainSuccess(domain, accountId)); + }).catch(err => { + dispatch(blockDomainFail(domain, err)); + }); + }; +}; + +export function blockDomainRequest(domain) { + return { + type: DOMAIN_BLOCK_REQUEST, + domain + }; +}; + +export function blockDomainSuccess(domain, accountId) { + return { + type: DOMAIN_BLOCK_SUCCESS, + domain, + accountId + }; +}; + +export function blockDomainFail(domain, error) { + return { + type: DOMAIN_BLOCK_FAIL, + domain, + error + }; +}; + +export function unblockDomain(domain, accountId) { + return (dispatch, getState) => { + dispatch(unblockDomainRequest(domain)); + + api(getState).delete('/api/v1/domain_blocks', { params: { domain } }).then(response => { + dispatch(unblockDomainSuccess(domain, accountId)); + }).catch(err => { + dispatch(unblockDomainFail(domain, err)); + }); + }; +}; + +export function unblockDomainRequest(domain) { + return { + type: DOMAIN_UNBLOCK_REQUEST, + domain + }; +}; + +export function unblockDomainSuccess(domain, accountId) { + return { + type: DOMAIN_UNBLOCK_SUCCESS, + domain, + accountId + }; +}; + +export function unblockDomainFail(domain, error) { + return { + type: DOMAIN_UNBLOCK_FAIL, + domain, + error + }; +}; + +export function fetchDomainBlocks() { + return (dispatch, getState) => { + dispatch(fetchDomainBlocksRequest()); + + api(getState).get().then(response => { + const next = getLinks(response).refs.find(link => link.rel === 'next'); + dispatch(fetchDomainBlocksSuccess(response.data, next ? next.uri : null)); + }).catch(err => { + dispatch(fetchDomainBlocksFail(err)); + }); + }; +}; + +export function fetchDomainBlocksRequest() { + return { + type: DOMAIN_BLOCKS_FETCH_REQUEST + }; +}; + +export function fetchDomainBlocksSuccess(domains, next) { + return { + type: DOMAIN_BLOCKS_FETCH_SUCCESS, + domains, + next + }; +}; + +export function fetchDomainBlocksFail(error) { + return { + type: DOMAIN_BLOCKS_FETCH_FAIL, + error + }; +}; diff --git a/app/javascript/mastodon/features/account/components/action_bar.js b/app/javascript/mastodon/features/account/components/action_bar.js index 44ed8af7d1..1997bf7b73 100644 --- a/app/javascript/mastodon/features/account/components/action_bar.js +++ b/app/javascript/mastodon/features/account/components/action_bar.js @@ -15,7 +15,9 @@ const messages = defineMessages({ mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' }, follow: { id: 'account.follow', defaultMessage: 'Follow' }, report: { id: 'account.report', defaultMessage: 'Report @{name}' }, - disclaimer: { id: 'account.disclaimer', defaultMessage: 'This user is from another instance. This number may be larger.' } + disclaimer: { id: 'account.disclaimer', defaultMessage: 'This user is from another instance. This number may be larger.' }, + blockDomain: { id: 'account.block_domain', defaultMessage: 'Hide everything from {domain}' }, + unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unhide {domain}' }, }); class ActionBar extends React.PureComponent { @@ -28,6 +30,8 @@ class ActionBar extends React.PureComponent { onMention: PropTypes.func.isRequired, onReport: PropTypes.func.isRequired, onMute: PropTypes.func.isRequired, + onBlockDomain: PropTypes.func.isRequired, + onUnblockDomain: PropTypes.func.isRequired, intl: PropTypes.object.isRequired }; @@ -59,7 +63,16 @@ class ActionBar extends React.PureComponent { } if (account.get('acct') !== account.get('username')) { + const domain = account.get('acct').split('@')[1]; extraInfo = <abbr title={intl.formatMessage(messages.disclaimer)}>*</abbr>; + + menu.push(null); + + if (account.getIn(['relationship', 'domain_blocking'])) { + menu.push({ text: intl.formatMessage(messages.unblockDomain, { domain }), action: this.props.onUnblockDomain }); + } else { + menu.push({ text: intl.formatMessage(messages.blockDomain, { domain }), action: this.props.onBlockDomain }); + } } return ( diff --git a/app/javascript/mastodon/features/account_timeline/components/header.js b/app/javascript/mastodon/features/account_timeline/components/header.js index d7226d9b20..f1a0e8d775 100644 --- a/app/javascript/mastodon/features/account_timeline/components/header.js +++ b/app/javascript/mastodon/features/account_timeline/components/header.js @@ -15,7 +15,9 @@ class Header extends ImmutablePureComponent { onBlock: PropTypes.func.isRequired, onMention: PropTypes.func.isRequired, onReport: PropTypes.func.isRequired, - onMute: PropTypes.func.isRequired + onMute: PropTypes.func.isRequired, + onBlockDomain: PropTypes.func.isRequired, + onUnblockDomain: PropTypes.func.isRequired, }; static contextTypes = { @@ -43,6 +45,22 @@ class Header extends ImmutablePureComponent { this.props.onMute(this.props.account); } + handleBlockDomain = () => { + const domain = this.props.account.get('acct').split('@')[1]; + + if (!domain) return; + + this.props.onBlockDomain(domain, this.props.account.get('id')); + } + + handleUnblockDomain = () => { + const domain = this.props.account.get('acct').split('@')[1]; + + if (!domain) return; + + this.props.onUnblockDomain(domain, this.props.account.get('id')); + } + render () { const { account, me } = this.props; @@ -65,6 +83,8 @@ class Header extends ImmutablePureComponent { onMention={this.handleMention} onReport={this.handleReport} onMute={this.handleMute} + onBlockDomain={this.handleBlockDomain} + onUnblockDomain={this.handleUnblockDomain} /> </div> ); diff --git a/app/javascript/mastodon/features/account_timeline/containers/header_container.js b/app/javascript/mastodon/features/account_timeline/containers/header_container.js index 50999d2e0e..0964efdcfe 100644 --- a/app/javascript/mastodon/features/account_timeline/containers/header_container.js +++ b/app/javascript/mastodon/features/account_timeline/containers/header_container.js @@ -13,11 +13,13 @@ import { import { mentionCompose } from '../../../actions/compose'; import { initReport } from '../../../actions/reports'; import { openModal } from '../../../actions/modal'; +import { blockDomain, unblockDomain } from '../../../actions/domain_blocks'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; const messages = defineMessages({ blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' }, - muteConfirm: { id: 'confirmations.mute.confirm', defaultMessage: 'Mute' } + muteConfirm: { id: 'confirmations.mute.confirm', defaultMessage: 'Mute' }, + blockDomainConfirm: { id: 'confirmations.domain_block.confirm', defaultMessage: 'Hide entire domain' }, }); const makeMapStateToProps = () => { @@ -70,6 +72,18 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ onConfirm: () => dispatch(muteAccount(account.get('id'))) })); } + }, + + onBlockDomain (domain, accountId) { + dispatch(openModal('CONFIRM', { + message: <FormattedMessage id='confirmations.domain_block.message' defaultMessage='Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.' values={{ domain: <strong>{domain}</strong> }} />, + confirm: intl.formatMessage(messages.blockDomainConfirm), + onConfirm: () => dispatch(blockDomain(domain, accountId)) + })); + }, + + onUnblockDomain (domain, accountId) { + dispatch(unblockDomain(domain, accountId)); } }); diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json index e30b7e84ae..2a9d00460a 100644 --- a/app/javascript/mastodon/locales/ar.json +++ b/app/javascript/mastodon/locales/ar.json @@ -1,17 +1,20 @@ { "account.block": "Øظر @{name}", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "هذا المستخدم من مثيل خادم آخر. قد يكون هذا الرقم أكبر.", "account.edit_profile": "تعديل المل٠الشخصي", "account.follow": "تابÙع", "account.followers": "المتابعون", "account.follows": "يتبع", "account.follows_you": "يتابعك", + "account.media": "Media", "account.mention": "Ø£ÙذكÙر @{name}", "account.mute": "أكتم @{name}", "account.posts": "المشاركات", "account.report": "أبلغ عن @{name}", "account.requested": "ÙÙŠ انتظار المواÙقة", "account.unblock": "إلغاء الØظر عن @{name}", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "إلغاء المتابعة", "account.unmute": "إلغاء الكتم عن @{name}", "boost_modal.combo": "يمكنك ضغط {combo} لتخطّي هذه ÙÙŠ المرّة القادمة", @@ -40,6 +43,8 @@ "confirmations.block.message": "هل أنت متأكد أنك تريد Øجب {name} ØŸ", "confirmations.delete.confirm": "ØØ°Ù", "confirmations.delete.message": "هل أنت متأكد أنك تريد Øذ٠هذا المنشور ØŸ", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "أكتم", "confirmations.mute.message": "هل أنت متأكد أنك تريد كتم {name} ØŸ", "emoji_button.activity": "الأنشطة", diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json index 3ca2f7775b..a43cd3dabf 100644 --- a/app/javascript/mastodon/locales/bg.json +++ b/app/javascript/mastodon/locales/bg.json @@ -1,17 +1,20 @@ { "account.block": "Блокирай", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "This user is from another instance. This number may be larger.", "account.edit_profile": "Редактирай профила Ñи", "account.follow": "ПоÑледвай", "account.followers": "ПоÑледователи", "account.follows": "Следвам", "account.follows_you": "Твой поÑледовател", + "account.media": "Media", "account.mention": "Споменаване", "account.mute": "Mute @{name}", "account.posts": "Публикации", "account.report": "Report @{name}", "account.requested": "Ð’ очакване на одобрение", "account.unblock": "Ðе блокирай", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "Ðе Ñледвай", "account.unmute": "Unmute @{name}", "boost_modal.combo": "You can press {combo} to skip this next time", @@ -40,6 +43,8 @@ "confirmations.block.message": "Are you sure you want to block {name}?", "confirmations.delete.confirm": "Delete", "confirmations.delete.message": "Are you sure you want to delete this status?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "Are you sure you want to mute {name}?", "emoji_button.activity": "Activity", diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json index f239a3d2fb..61827220e6 100644 --- a/app/javascript/mastodon/locales/ca.json +++ b/app/javascript/mastodon/locales/ca.json @@ -1,17 +1,20 @@ { "account.block": "Bloquejar @{name}", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "Aquest usuari és d'un altra instà ncia. Aquest número podria ser més gran.", "account.edit_profile": "Editar perfil", "account.follow": "Seguir", "account.followers": "Seguidors", "account.follows": "Seguint", "account.follows_you": "et segueix", + "account.media": "Media", "account.mention": "Esmentar @{name}", "account.mute": "Silenciar @{name}", "account.posts": "Publicacions", "account.report": "Informe @{name}", "account.requested": "Esperant aprovació", "account.unblock": "Desbloquejar @{name}", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "Deixar de seguir", "account.unmute": "Treure silenci de @{name}", "boost_modal.combo": "Pots premer {combo} per saltar-te això el proper cop", @@ -40,6 +43,8 @@ "confirmations.block.message": "Està s segur que vols bloquejar {name}?", "confirmations.delete.confirm": "Esborrar", "confirmations.delete.message": "Està s segur que vols esborrar aquest estat?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Silenciar", "confirmations.mute.message": "Està s segur que vols silenciar {name}?", "emoji_button.activity": "Activitat", diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json index 8a5b5e418d..a82bee22d0 100644 --- a/app/javascript/mastodon/locales/de.json +++ b/app/javascript/mastodon/locales/de.json @@ -1,17 +1,20 @@ { "account.block": "@{name} blocken", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "Dieser Benutzer ist von einer anderen Instanz. Diese Zahl könnte größer sein.", "account.edit_profile": "Profil bearbeiten", "account.follow": "Folgen", "account.followers": "Folgende", "account.follows": "Folgt", "account.follows_you": "Folgt dir", + "account.media": "Media", "account.mention": "@{name} erwähnen", "account.mute": "@{name} stummschalten", "account.posts": "Beiträge", "account.report": "@{name} melden", "account.requested": "Warte auf Erlaubnis", "account.unblock": "@{name} entblocken", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "Entfolgen", "account.unmute": "@{name} nicht mehr stummschalten", "boost_modal.combo": "Du kannst {combo} drücken, um dies beim nächsten Mal zu überspringen", @@ -40,6 +43,8 @@ "confirmations.block.message": "Are you sure you want to block {name}?", "confirmations.delete.confirm": "Delete", "confirmations.delete.message": "Are you sure you want to delete this status?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "Are you sure you want to mute {name}?", "emoji_button.activity": "Activity", diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json index 38d76828d4..67c7cc527a 100644 --- a/app/javascript/mastodon/locales/defaultMessages.json +++ b/app/javascript/mastodon/locales/defaultMessages.json @@ -240,6 +240,15 @@ ], "path": "app/javascript/mastodon/containers/status_container.json" }, + { + "descriptors": [ + { + "defaultMessage": "Media", + "id": "account.media" + } + ], + "path": "app/javascript/mastodon/features/account_gallery/index.json" + }, { "descriptors": [ { @@ -250,6 +259,10 @@ "defaultMessage": "Mute", "id": "confirmations.mute.confirm" }, + { + "defaultMessage": "Hide entire domain", + "id": "confirmations.domain_block.confirm" + }, { "defaultMessage": "Are you sure you want to block {name}?", "id": "confirmations.block.message" @@ -257,6 +270,10 @@ { "defaultMessage": "Are you sure you want to mute {name}?", "id": "confirmations.mute.message" + }, + { + "defaultMessage": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", + "id": "confirmations.domain_block.message" } ], "path": "app/javascript/mastodon/features/account_timeline/containers/header_container.json" @@ -303,6 +320,14 @@ "defaultMessage": "This user is from another instance. This number may be larger.", "id": "account.disclaimer" }, + { + "defaultMessage": "Hide everything from {domain}", + "id": "account.block_domain" + }, + { + "defaultMessage": "Unhide {domain}", + "id": "account.unblock_domain" + }, { "defaultMessage": "Posts", "id": "account.posts" diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index f4a6a7512f..6864123aec 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -1,17 +1,20 @@ { "account.block": "Block @{name}", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "This user is from another instance. This number may be larger.", "account.edit_profile": "Edit profile", "account.follow": "Follow", "account.followers": "Followers", "account.follows": "Follows", "account.follows_you": "Follows you", + "account.media": "Media", "account.mention": "Mention @{name}", "account.mute": "Mute @{name}", "account.posts": "Posts", "account.report": "Report @{name}", "account.requested": "Awaiting approval", "account.unblock": "Unblock @{name}", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "Unfollow", "account.unmute": "Unmute @{name}", "boost_modal.combo": "You can press {combo} to skip this next time", @@ -40,6 +43,8 @@ "confirmations.block.message": "Are you sure you want to block {name}?", "confirmations.delete.confirm": "Delete", "confirmations.delete.message": "Are you sure you want to delete this status?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "Are you sure you want to mute {name}?", "emoji_button.activity": "Activity", diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json index 904c08cc93..3437bd9e99 100644 --- a/app/javascript/mastodon/locales/eo.json +++ b/app/javascript/mastodon/locales/eo.json @@ -1,17 +1,20 @@ { "account.block": "Bloki @{name}", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "This user is from another instance. This number may be larger.", "account.edit_profile": "Redakti la profilon", "account.follow": "Sekvi", "account.followers": "Sekvantoj", "account.follows": "Sekvatoj", "account.follows_you": "Sekvas vin", + "account.media": "Media", "account.mention": "Mencii @{name}", "account.mute": "Mute @{name}", "account.posts": "MesaÄoj", "account.report": "Report @{name}", "account.requested": "Atendas aprobon", "account.unblock": "Malbloki @{name}", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "Malsekvi", "account.unmute": "Unmute @{name}", "boost_modal.combo": "You can press {combo} to skip this next time", @@ -40,6 +43,8 @@ "confirmations.block.message": "Are you sure you want to block {name}?", "confirmations.delete.confirm": "Delete", "confirmations.delete.message": "Are you sure you want to delete this status?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "Are you sure you want to mute {name}?", "emoji_button.activity": "Activity", diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json index 605c14a098..14b007a3e0 100644 --- a/app/javascript/mastodon/locales/es.json +++ b/app/javascript/mastodon/locales/es.json @@ -1,17 +1,20 @@ { "account.block": "Bloquear", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "This user is from another instance. This number may be larger.", "account.edit_profile": "Editar perfil", "account.follow": "Seguir", "account.followers": "Seguidores", "account.follows": "Seguir", "account.follows_you": "Te sigue", + "account.media": "Media", "account.mention": "Mencionar", "account.mute": "Silenciar", "account.posts": "Publicaciones", "account.report": "Report @{name}", "account.requested": "Esperando aprobación", "account.unblock": "Desbloquear", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "Dejar de seguir", "account.unmute": "Unmute @{name}", "boost_modal.combo": "You can press {combo} to skip this next time", @@ -40,6 +43,8 @@ "confirmations.block.message": "Are you sure you want to block {name}?", "confirmations.delete.confirm": "Delete", "confirmations.delete.message": "Are you sure you want to delete this status?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "Are you sure you want to mute {name}?", "emoji_button.activity": "Activity", diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json index 72e9386957..59266dcd94 100644 --- a/app/javascript/mastodon/locales/fa.json +++ b/app/javascript/mastodon/locales/fa.json @@ -1,17 +1,20 @@ { "account.block": "مسدودسازی @{name}", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "این کاربر عضو سرور متÙاوتی است. شاید عدد واقعی بیشتر از این باشد.", "account.edit_profile": "ویرایش نمایه", "account.follow": "Ù¾ÛŒ بگیرید", "account.followers": "پیگیران", "account.follows": "Ù¾ÛŒ می‌گیرد", "account.follows_you": "پیگیر شماست", + "account.media": "Media", "account.mention": "نام‌بردن از @{name}", "account.mute": "بی‌صدا کردن @{name}", "account.posts": "نوشته‌ها", "account.report": "گزارش @{name}", "account.requested": "در انتظار پذیرش", "account.unblock": "رÙع انسداد @{name}", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "پایان پیگیری", "account.unmute": "باصدا کردن @{name}", "boost_modal.combo": "دکمهٔ {combo} را بزنید تا دیگر این را نبینید", @@ -40,6 +43,8 @@ "confirmations.block.message": "آیا واقعاً می‌خواهید {name} را مسدود کنید؟", "confirmations.delete.confirm": "پاک Ú©Ù†", "confirmations.delete.message": "آیا واقعاً می‌خواهید این نوشته را پاک کنید؟", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "بی‌صدا Ú©Ù†", "confirmations.mute.message": "آیا واقعاً می‌خواهید {name} را بی‌صدا کنید؟", "emoji_button.activity": "Ùعالیت", diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json index 42b1fbcb0b..c544c955cd 100644 --- a/app/javascript/mastodon/locales/fi.json +++ b/app/javascript/mastodon/locales/fi.json @@ -1,17 +1,20 @@ { "account.block": "Estä @{name}", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "This user is from another instance. This number may be larger.", "account.edit_profile": "Muokkaa", "account.follow": "Seuraa", "account.followers": "Seuraajia", "account.follows": "Seuraa", "account.follows_you": "Seuraa sinua", + "account.media": "Media", "account.mention": "Mainitse @{name}", "account.mute": "Mute @{name}", "account.posts": "Postit", "account.report": "Report @{name}", "account.requested": "Odottaa hyväksyntää", "account.unblock": "Salli @{name}", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "Lopeta seuraaminen", "account.unmute": "Unmute @{name}", "boost_modal.combo": "You can press {combo} to skip this next time", @@ -40,6 +43,8 @@ "confirmations.block.message": "Are you sure you want to block {name}?", "confirmations.delete.confirm": "Delete", "confirmations.delete.message": "Are you sure you want to delete this status?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "Are you sure you want to mute {name}?", "emoji_button.activity": "Activity", diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json index c6665f43c1..d3c292707f 100644 --- a/app/javascript/mastodon/locales/fr.json +++ b/app/javascript/mastodon/locales/fr.json @@ -1,17 +1,20 @@ { "account.block": "Bloquer", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "Ce compte est situé sur une autre instance. Les nombres peuvent être plus grands.", "account.edit_profile": "Modifier le profil", "account.follow": "Suivre", "account.followers": "Abonné⋅eâ‹…s", "account.follows": "Abonnements", "account.follows_you": "Vous suit", + "account.media": "Media", "account.mention": "Mentionner", "account.mute": "Masquer", "account.posts": "Statuts", "account.report": "Signaler", "account.requested": "Invitation envoyée", "account.unblock": "Débloquer", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "Ne plus suivre", "account.unmute": "Ne plus masquer", "boost_modal.combo": "Vous pouvez appuyer sur {combo} pour pouvoir passer ceci, la prochaine fois", @@ -40,6 +43,8 @@ "confirmations.block.message": "Confirmez vous le blocage de {name} ?", "confirmations.delete.confirm": "Supprimer", "confirmations.delete.message": "Confirmez vous la suppression de ce pouet ?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Silencer", "confirmations.mute.message": "Confirmez vous la silenciation {name} ?", "emoji_button.activity": "Activités", diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json index 8e4baa0c5b..0a38065b55 100644 --- a/app/javascript/mastodon/locales/he.json +++ b/app/javascript/mastodon/locales/he.json @@ -1,17 +1,20 @@ { "account.block": "חסימת @{name}", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "משתמש ×–×” מגיע מקהילה ×חרת. המספר ×”×–×” עשוי להיות גדול יותר.", "account.edit_profile": "עריכת פרופיל", "account.follow": "מעקב", "account.followers": "עוקבי×", "account.follows": "× ×¢×§×‘×™×", "account.follows_you": "במעקב ×חריך", + "account.media": "Media", "account.mention": "×זכור של @{name}", "account.mute": "להשתיק ×ת @{name}", "account.posts": "הודעות", "account.report": "לדווח על @{name}", "account.requested": "×‘×”×ž×ª× ×” ל×ישור", "account.unblock": "הסרת חסימה מעל @{name}", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "הפסקת מעקב", "account.unmute": "הפסקת השתקת @{name}", "boost_modal.combo": "× ×™×ª×Ÿ להקיש {combo} כדי לדלג ×‘×¤×¢× ×”×‘××”", @@ -40,6 +43,8 @@ "confirmations.block.message": "×œ×—×¡×•× ×ת {name}?", "confirmations.delete.confirm": "למחוק", "confirmations.delete.message": "למחוק ×ת ההודעה?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "להשתיק", "confirmations.mute.message": "להשתיק ×ת {name}?", "emoji_button.activity": "פעילות", diff --git a/app/javascript/mastodon/locales/hr.json b/app/javascript/mastodon/locales/hr.json index d263a73b90..6d4b43c009 100644 --- a/app/javascript/mastodon/locales/hr.json +++ b/app/javascript/mastodon/locales/hr.json @@ -1,17 +1,20 @@ { "account.block": "Blokiraj @{name}", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "Ovaj korisnik je sa druge instance. Ovaj broj bi mogao biti veći.", "account.edit_profile": "Uredi profil", "account.follow": "Slijedi", "account.followers": "Sljedbenici", "account.follows": "Slijedi", "account.follows_you": "te slijedi", + "account.media": "Media", "account.mention": "Spomeni @{name}", "account.mute": "UtiÅ¡aj @{name}", "account.posts": "Postovi", "account.report": "Prijavi @{name}", "account.requested": "ÄŒeka pristanak", "account.unblock": "Deblokiraj @{name}", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "Prestani slijediti", "account.unmute": "PoniÅ¡ti utiÅ¡avanje @{name}", "boost_modal.combo": "MožeÅ¡ pritisnuti {combo} kako bi ovo preskoÄio sljedeći put", @@ -40,6 +43,8 @@ "confirmations.block.message": "Are you sure you want to block {name}?", "confirmations.delete.confirm": "Delete", "confirmations.delete.message": "Are you sure you want to delete this status?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "Are you sure you want to mute {name}?", "emoji_button.activity": "Activity", diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json index c50501d242..ebe2d41717 100644 --- a/app/javascript/mastodon/locales/hu.json +++ b/app/javascript/mastodon/locales/hu.json @@ -1,17 +1,20 @@ { "account.block": "Blokkolás", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "This user is from another instance. This number may be larger.", "account.edit_profile": "Profil szerkesztése", "account.follow": "Követés", "account.followers": "KövetÅ‘k", "account.follows": "Követve", "account.follows_you": "Követnek téged", + "account.media": "Media", "account.mention": "EmlÃtés", "account.mute": "Mute @{name}", "account.posts": "Posts", "account.report": "Report @{name}", "account.requested": "Awaiting approval", "account.unblock": "Blokkolás levétele", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "Követés abbahagyása", "account.unmute": "Unmute @{name}", "boost_modal.combo": "You can press {combo} to skip this next time", @@ -40,6 +43,8 @@ "confirmations.block.message": "Are you sure you want to block {name}?", "confirmations.delete.confirm": "Delete", "confirmations.delete.message": "Are you sure you want to delete this status?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "Are you sure you want to mute {name}?", "emoji_button.activity": "Activity", diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json index ca821a5d5e..45eea622b3 100644 --- a/app/javascript/mastodon/locales/id.json +++ b/app/javascript/mastodon/locales/id.json @@ -1,17 +1,20 @@ { "account.block": "Blokir @{name}", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "Pengguna ini berasal dari server lain. Angka berikut mungkin lebih besar.", "account.edit_profile": "Ubah profil", "account.follow": "Ikuti", "account.followers": "Pengikut", "account.follows": "Mengikuti", "account.follows_you": "Mengikuti anda", + "account.media": "Media", "account.mention": "Balasan @{name}", "account.mute": "Bisukan @{name}", "account.posts": "Postingan", "account.report": "Laporkan @{name}", "account.requested": "Menunggu persetujuan", "account.unblock": "Hapus blokir @{name}", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "Berhenti mengikuti", "account.unmute": "Berhenti membisukan @{name}", "boost_modal.combo": "Anda dapat menekan {combo} untuk melewati ini", @@ -40,6 +43,8 @@ "confirmations.block.message": "Apa anda yakin ingin memblokir {name}?", "confirmations.delete.confirm": "Hapus", "confirmations.delete.message": "Apa anda yakin akan menghapus status ini?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Bisukan", "confirmations.mute.message": "Apa anda yakin ingin membisukan {name}?", "emoji_button.activity": "Aktivitas", diff --git a/app/javascript/mastodon/locales/io.json b/app/javascript/mastodon/locales/io.json index 34d38868f8..f6791d1809 100644 --- a/app/javascript/mastodon/locales/io.json +++ b/app/javascript/mastodon/locales/io.json @@ -1,17 +1,20 @@ { "account.block": "Blokusar @{name}", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "Ca uzero esas de altra instaluro. Ca nombro forsan esas plu granda.", "account.edit_profile": "Modifikar profilo", "account.follow": "Sequar", "account.followers": "Sequanti", "account.follows": "Sequas", "account.follows_you": "Sequas tu", + "account.media": "Media", "account.mention": "Mencionar @{name}", "account.mute": "Celar @{name}", "account.posts": "Mesaji", "account.report": "Denuncar @{name}", "account.requested": "Vartante aprobo", "account.unblock": "Desblokusar @{name}", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "Ne plus sequar", "account.unmute": "Ne plus celar @{name}", "boost_modal.combo": "Tu povas presar sur {combo} por omisar co en la venonta foyo", @@ -40,6 +43,8 @@ "confirmations.block.message": "Are you sure you want to block {name}?", "confirmations.delete.confirm": "Delete", "confirmations.delete.message": "Are you sure you want to delete this status?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "Are you sure you want to mute {name}?", "emoji_button.activity": "Activity", diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json index 8b92ce86d5..c09b705ebb 100644 --- a/app/javascript/mastodon/locales/it.json +++ b/app/javascript/mastodon/locales/it.json @@ -1,17 +1,20 @@ { "account.block": "Blocca @{name}", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "Questo utente si trova su un altro server. Questo numero potrebbe essere maggiore.", "account.edit_profile": "Modifica profilo", "account.follow": "Segui", "account.followers": "Seguaci", "account.follows": "Segue", "account.follows_you": "Ti segue", + "account.media": "Media", "account.mention": "Menziona @{name}", "account.mute": "Silenzia @{name}", "account.posts": "Posts", "account.report": "Segnala @{name}", "account.requested": "In attesa di approvazione", "account.unblock": "Sblocca @{name}", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "Non seguire", "account.unmute": "Non silenziare @{name}", "boost_modal.combo": "Puoi premere {combo} per saltare questo passaggio la prossima volta", @@ -40,6 +43,8 @@ "confirmations.block.message": "Are you sure you want to block {name}?", "confirmations.delete.confirm": "Delete", "confirmations.delete.message": "Are you sure you want to delete this status?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "Are you sure you want to mute {name}?", "emoji_button.activity": "Activity", diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json index 5f1ac2381d..38745e20ff 100644 --- a/app/javascript/mastodon/locales/ja.json +++ b/app/javascript/mastodon/locales/ja.json @@ -1,17 +1,20 @@ { "account.block": "ブãƒãƒƒã‚¯", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ä»–ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã«æ‰€å±žã—ã¦ã„ã‚‹ãŸã‚ã€æ•°å—ãŒæ£ç¢ºã§ç„¡ã„å ´åˆãŒã‚ã‚Šã¾ã™ã€‚", "account.edit_profile": "プãƒãƒ•ã‚£ãƒ¼ãƒ«ã‚’編集", "account.follow": "フォãƒãƒ¼", "account.followers": "フォãƒãƒ¯ãƒ¼", "account.follows": "フォãƒãƒ¼", "account.follows_you": "フォãƒãƒ¼ã•ã‚Œã¦ã„ã¾ã™", + "account.media": "Media", "account.mention": "返信", "account.mute": "ミュート", "account.posts": "投稿", "account.report": "é€šå ±", "account.requested": "承èªå¾…ã¡", "account.unblock": "ブãƒãƒƒã‚¯è§£é™¤", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "フォãƒãƒ¼è§£é™¤", "account.unmute": "ミュート解除", "boost_modal.combo": "次ã‹ã‚‰ã¯{combo}を押ã›ã°ã€ã“れをスã‚ップã§ãã¾ã™ã€‚", @@ -40,6 +43,8 @@ "confirmations.block.message": "本当ã«{name}をブãƒãƒƒã‚¯ã—ã¾ã™ã‹ï¼Ÿ", "confirmations.delete.confirm": "削除", "confirmations.delete.message": "本当ã«å‰Šé™¤ã—ã¾ã™ã‹ï¼Ÿ", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "ミュート", "confirmations.mute.message": "本当ã«{name}をミュートã—ã¾ã™ã‹ï¼Ÿ", "emoji_button.activity": "活動", diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json index e63f527c10..33e51a6801 100644 --- a/app/javascript/mastodon/locales/nl.json +++ b/app/javascript/mastodon/locales/nl.json @@ -1,17 +1,20 @@ { "account.block": "Blokkeer @{name}", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "Deze gebruiker zit op een andere server. Dit getal kan hoger zijn.", "account.edit_profile": "Profiel bewerken", "account.follow": "Volgen", "account.followers": "Volgers", "account.follows": "Volgt", "account.follows_you": "Volgt jou", + "account.media": "Media", "account.mention": "Vermeld @{name}", "account.mute": "Negeer @{name}", "account.posts": "Berichten", "account.report": "Rapporteer @{name}", "account.requested": "Wacht op goedkeuring", "account.unblock": "Deblokkeer @{name}", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "Ontvolgen", "account.unmute": "Negeer @{name} niet meer", "boost_modal.combo": "Je kunt {combo} klikken om dit de volgende keer over te slaan", @@ -40,6 +43,8 @@ "confirmations.block.message": "Weet je zeker dat je {name} wilt blokkeren?", "confirmations.delete.confirm": "Verwijderen", "confirmations.delete.message": "Weet je zeker dat je deze toot wilt verwijderen?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Negeren", "confirmations.mute.message": "Weet je zeker dat je {name} wilt negeren?", "emoji_button.activity": "Activiteiten", diff --git a/app/javascript/mastodon/locales/no.json b/app/javascript/mastodon/locales/no.json index d3fac55bdb..1fddbaa212 100644 --- a/app/javascript/mastodon/locales/no.json +++ b/app/javascript/mastodon/locales/no.json @@ -1,17 +1,20 @@ { "account.block": "Blokkér @{name}", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "Denne brukeren er fra en annen instans. Dette tallet kan være høyere.", "account.edit_profile": "Rediger profil", "account.follow": "Følg", "account.followers": "Følgere", "account.follows": "Følger", "account.follows_you": "Følger deg", + "account.media": "Media", "account.mention": "Nevn @{name}", "account.mute": "Demp @{name}", "account.posts": "Innlegg", "account.report": "Rapportér @{name}", "account.requested": "Venter pÃ¥ godkjennelse", "account.unblock": "Avblokker @{name}", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "Avfølg", "account.unmute": "Avdemp @{name}", "boost_modal.combo": "You kan trykke {combo} for Ã¥ hoppe over dette neste gang", @@ -40,6 +43,8 @@ "confirmations.block.message": "Are you sure you want to block {name}?", "confirmations.delete.confirm": "Delete", "confirmations.delete.message": "Are you sure you want to delete this status?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "Are you sure you want to mute {name}?", "emoji_button.activity": "Activity", diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json index 8d4911187e..506cf42e5e 100644 --- a/app/javascript/mastodon/locales/oc.json +++ b/app/javascript/mastodon/locales/oc.json @@ -1,17 +1,20 @@ { "account.block": "Blocar", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "Aqueste compte es sus una autra instà ncia. Los nombres pòdon èsser mai grandes.", "account.edit_profile": "Modificar lo perfil", "account.follow": "Sègre", "account.followers": "Abonats", "account.follows": "Abonaments", "account.follows_you": "Vos sèc", + "account.media": "Media", "account.mention": "Mencionar", "account.mute": "Rescondre", "account.posts": "Estatuts", "account.report": "Senhalar", "account.requested": "Invitacion mandada", "account.unblock": "Desblocar", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "Quitar de sègre", "account.unmute": "Quitar de rescondre", "boost_modal.combo": "Podètz butar {combo} per passar aquò lo còp que ven", @@ -40,6 +43,8 @@ "confirmations.block.message": "Sètz segur de voler blocar {name}?", "confirmations.delete.confirm": "Suprimir", "confirmations.delete.message": "Sètz segur de voler suprimir l’estatut ?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Metre en silenci", "confirmations.mute.message": "Sètz segur de voler metre en silenci {name}?", "emoji_button.activity": "Activitat", diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json index 2a18dff8f1..f51d2ee58d 100644 --- a/app/javascript/mastodon/locales/pl.json +++ b/app/javascript/mastodon/locales/pl.json @@ -1,17 +1,20 @@ { "account.block": "Blokuj @{name}", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "Ten użytkownik pochodzi z innej instancji. Ta liczba może być wiÄ™ksza.", "account.edit_profile": "Edytuj profil", "account.follow": "Obserwuj", "account.followers": "ObserwujÄ…cy", "account.follows": "Obserwacje", "account.follows_you": "ObserwujÄ… ciÄ™", + "account.media": "Media", "account.mention": "Wspomnij o @{name}", "account.mute": "Wycisz @{name}", "account.posts": "Posty", "account.report": "ZgÅ‚oÅ› @{name}", "account.requested": "OczekujÄ…ca proÅ›ba", "account.unblock": "Odblokuj @{name}", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "PrzestaÅ„ obserwować", "account.unmute": "Cofnij wyciszenie @{name}", "boost_modal.combo": "NaciÅ›nij {combo}, aby pominąć to nastÄ™pnym razem", @@ -40,6 +43,8 @@ "confirmations.block.message": "Czy na pewno chcesz zablokować {name}?", "confirmations.delete.confirm": "UsuÅ„", "confirmations.delete.message": "Czy na pewno chcesz usunąć ten status?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Wycisz", "confirmations.mute.message": "Czy na pewno chcesz wyciszyć {name}?", "emoji_button.activity": "Aktywność", diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json index 57b31733d2..c5af75d9c0 100644 --- a/app/javascript/mastodon/locales/pt-BR.json +++ b/app/javascript/mastodon/locales/pt-BR.json @@ -1,17 +1,20 @@ { "account.block": "Bloquear @{name}", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "Essa conta está localizado em outra instância. Os nomes podem ser maiores.", "account.edit_profile": "Editar perfil", "account.follow": "Seguir", "account.followers": "Seguidores", "account.follows": "Segue", "account.follows_you": "É teu seguidor", + "account.media": "Media", "account.mention": "Mencionar @{name}", "account.mute": "Silenciar @{name}", "account.posts": "Posts", "account.report": "Denunciar @{name}", "account.requested": "A aguardar aprovação", "account.unblock": "Não bloquear @{name}", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "Deixar de seguir", "account.unmute": "Não silenciar @{name}", "boost_modal.combo": "Pode clicar {combo} para não voltar a ver", @@ -40,6 +43,8 @@ "confirmations.block.message": "Are you sure you want to block {name}?", "confirmations.delete.confirm": "Delete", "confirmations.delete.message": "Are you sure you want to delete this status?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "Are you sure you want to mute {name}?", "emoji_button.activity": "Activity", diff --git a/app/javascript/mastodon/locales/pt.json b/app/javascript/mastodon/locales/pt.json index 57b31733d2..c5af75d9c0 100644 --- a/app/javascript/mastodon/locales/pt.json +++ b/app/javascript/mastodon/locales/pt.json @@ -1,17 +1,20 @@ { "account.block": "Bloquear @{name}", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "Essa conta está localizado em outra instância. Os nomes podem ser maiores.", "account.edit_profile": "Editar perfil", "account.follow": "Seguir", "account.followers": "Seguidores", "account.follows": "Segue", "account.follows_you": "É teu seguidor", + "account.media": "Media", "account.mention": "Mencionar @{name}", "account.mute": "Silenciar @{name}", "account.posts": "Posts", "account.report": "Denunciar @{name}", "account.requested": "A aguardar aprovação", "account.unblock": "Não bloquear @{name}", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "Deixar de seguir", "account.unmute": "Não silenciar @{name}", "boost_modal.combo": "Pode clicar {combo} para não voltar a ver", @@ -40,6 +43,8 @@ "confirmations.block.message": "Are you sure you want to block {name}?", "confirmations.delete.confirm": "Delete", "confirmations.delete.message": "Are you sure you want to delete this status?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "Are you sure you want to mute {name}?", "emoji_button.activity": "Activity", diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json index 83d74c6195..ba4642ab99 100644 --- a/app/javascript/mastodon/locales/ru.json +++ b/app/javascript/mastodon/locales/ru.json @@ -1,17 +1,20 @@ { "account.block": "Блокировать", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "Ðто пользователь Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð³Ð¾ узла. ЧиÑло может быть больше.", "account.edit_profile": "Изменить профиль", "account.follow": "ПодпиÑатьÑÑ", "account.followers": "ПодпиÑаны", "account.follows": "ПодпиÑки", "account.follows_you": "ПодпиÑан(а) на ВаÑ", + "account.media": "Media", "account.mention": "УпомÑнуть", "account.mute": "Заглушить", "account.posts": "ПоÑÑ‚Ñ‹", "account.report": "ПожаловатьÑÑ", "account.requested": "Ожидает подтверждениÑ", "account.unblock": "Разблокировать", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "ОтпиÑатьÑÑ", "account.unmute": "СнÑÑ‚ÑŒ глушение", "boost_modal.combo": "Ðажмите {combo}, чтобы пропуÑтить Ñто в Ñледующий раз", @@ -40,6 +43,8 @@ "confirmations.block.message": "Ð’Ñ‹ уверены, что хотите заблокировать {name}?", "confirmations.delete.confirm": "Удалить", "confirmations.delete.message": "Ð’Ñ‹ уверены, что хотите удалить Ñтот ÑтатуÑ?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Заглушить", "confirmations.mute.message": "Ð’Ñ‹ уверены, что хотите заглушить {name}?", "emoji_button.activity": "ЗанÑтиÑ", diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json index ef9c43d0b7..ebfa95b845 100644 --- a/app/javascript/mastodon/locales/tr.json +++ b/app/javascript/mastodon/locales/tr.json @@ -1,17 +1,20 @@ { "account.block": "Engelle @{name}", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "Bu kullanıcının hesabı farklı sunucuda bulunduÄŸu için bu sayı daha fazla olabilir.", "account.edit_profile": "Profili düzenle", "account.follow": "Takip et", "account.followers": "Takipçiler", "account.follows": "Takip ettikleri", "account.follows_you": "Seni takip ediyor", + "account.media": "Media", "account.mention": "Bahset @{name}", "account.mute": "Sustur @{name}", "account.posts": "Gönderiler", "account.report": "Rapor et @{name}", "account.requested": "Onay bekleniyor", "account.unblock": "Engeli kaldır @{name}", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "Takipten vazgeç", "account.unmute": "Sesi aç @{name}", "boost_modal.combo": "Bir dahaki sefere {combo} tuÅŸuna basabilirsiniz", @@ -40,6 +43,8 @@ "confirmations.block.message": "{name} kullanıcısını engellemek istiyor musunuz?", "confirmations.delete.confirm": "Sil", "confirmations.delete.message": "Bu gönderiyi silmek istiyor musunuz?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Sessize al", "confirmations.mute.message": "{name} kullanıcısını sessize almak istiyor musunuz?", "emoji_button.activity": "Aktivite", diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json index 99df3b4f4e..cd2fa6b11b 100644 --- a/app/javascript/mastodon/locales/uk.json +++ b/app/javascript/mastodon/locales/uk.json @@ -1,17 +1,20 @@ { "account.block": "Заблокувати", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "Це кориÑтувач з іншої інÑтанції. ЧиÑло може бути більше.", "account.edit_profile": "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ñ„Ñ–Ð»ÑŽ", "account.follow": "ПідпиÑатиÑÑ", "account.followers": "ПідпиÑники", "account.follows": "ПідпиÑки", "account.follows_you": "ПідпиÑаний(-а) на ВаÑ", + "account.media": "Media", "account.mention": "Згадати", "account.mute": "Заглушити", "account.posts": "ПоÑти", "account.report": "ПоÑкаржитиÑÑ", "account.requested": "Очікує підтвердженнÑ", "account.unblock": "Розблокувати", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "ВідпиÑатиÑÑ", "account.unmute": "ЗнÑти глушеннÑ", "boost_modal.combo": "Ви можете натиÑнути {combo}, щоб пропуÑтити це наÑтупного разу", @@ -40,6 +43,8 @@ "confirmations.block.message": "Ви впевнені, що хочете заблокувати {name}?", "confirmations.delete.confirm": "Видалити", "confirmations.delete.message": "Ви впевнені, що хочете видалити цей допиÑ?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Заглушить", "confirmations.mute.message": "Ви впевнені, що хочете заглушити {name}?", "emoji_button.activity": "ЗанÑÑ‚Ñ‚Ñ", diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json index fed311cf7c..45eb663a0e 100644 --- a/app/javascript/mastodon/locales/zh-CN.json +++ b/app/javascript/mastodon/locales/zh-CN.json @@ -1,17 +1,20 @@ { "account.block": "å±è”½ @{name}", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "由于这个账户处于å¦ä¸€ä¸ªæœåŠ¡ç«™ä¸Šï¼Œå®žé™…æ•°å—会比这个更多。", "account.edit_profile": "修改个人资料", "account.follow": "关注", "account.followers": "关注者", "account.follows": "æ£å…³æ³¨", "account.follows_you": "å…³æ³¨ä½ ", + "account.media": "Media", "account.mention": "æåŠ @{name}", "account.mute": "å°† @{name} é™éŸ³", "account.posts": "嘟文", "account.report": "举报 @{name}", "account.requested": "ç‰å€™å®¡æ‰¹", "account.unblock": "解除对 @{name} çš„å±è”½", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "å–消关注", "account.unmute": "å–消 @{name} çš„é™éŸ³", "boost_modal.combo": "å¦‚ä½ æƒ³åœ¨ä¸‹æ¬¡è·¯è¿‡æ—¶æ˜¾ç¤ºï¼Œè¯·æŒ‰{combo},", @@ -40,6 +43,8 @@ "confirmations.block.message": "想好了,真的è¦å±è”½ {name}?", "confirmations.delete.confirm": "åˆ é™¤", "confirmations.delete.message": "想好了,真的è¦åˆ 除这æ¡å˜Ÿæ–‡?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "é™éŸ³", "confirmations.mute.message": "想好了,真的è¦é™éŸ³ {name}?", "emoji_button.activity": "活动", diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json index f3637bf740..23611ae97f 100644 --- a/app/javascript/mastodon/locales/zh-HK.json +++ b/app/javascript/mastodon/locales/zh-HK.json @@ -1,17 +1,20 @@ { "account.block": "å°éŽ– @{name}", + "account.block_domain": "Hide everything from {domain}", "account.disclaimer": "由於這個用戶在å¦ä¸€å€‹æœå‹™ç«™ï¼Œå¯¦éš›æ•¸å—會比這個更多。", "account.edit_profile": "修改個人資料", "account.follow": "關注", "account.followers": "關注的人", "account.follows": "æ£åœ¨é—œæ³¨", "account.follows_you": "é—œæ³¨ä½ ", + "account.media": "Media", "account.mention": "æåŠ @{name}", "account.mute": "å°‡ @{name} éœéŸ³", "account.posts": "æ–‡ç« ", "account.report": "èˆ‰å ± @{name}", "account.requested": "ç‰å€™å¯©æ‰¹", "account.unblock": "è§£é™¤å° @{name} çš„å°éŽ–", + "account.unblock_domain": "Unhide {domain}", "account.unfollow": "å–消關注", "account.unmute": "å–消 @{name} çš„éœéŸ³", "boost_modal.combo": "å¦‚ä½ æƒ³åœ¨ä¸‹æ¬¡è·¯éŽé€™é¡¯ç¤ºï¼Œè«‹æŒ‰{combo},", @@ -40,6 +43,8 @@ "confirmations.block.message": "ä½ ç¢ºå®šè¦å°éŽ–{name}嗎?", "confirmations.delete.confirm": "刪除", "confirmations.delete.message": "ä½ ç¢ºå®šè¦åˆªé™¤{name}嗎?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "éœéŸ³", "confirmations.mute.message": "ä½ ç¢ºå®šè¦å°‡{name}éœéŸ³å—Žï¼Ÿ", "emoji_button.activity": "活動", diff --git a/app/javascript/mastodon/reducers/relationships.js b/app/javascript/mastodon/reducers/relationships.js index c65c48b431..f25c0b55a6 100644 --- a/app/javascript/mastodon/reducers/relationships.js +++ b/app/javascript/mastodon/reducers/relationships.js @@ -7,6 +7,10 @@ import { ACCOUNT_UNMUTE_SUCCESS, RELATIONSHIPS_FETCH_SUCCESS } from '../actions/accounts'; +import { + DOMAIN_BLOCK_SUCCESS, + DOMAIN_UNBLOCK_SUCCESS +} from '../actions/domain_blocks'; import Immutable from 'immutable'; const normalizeRelationship = (state, relationship) => state.set(relationship.id, Immutable.fromJS(relationship)); @@ -32,6 +36,10 @@ export default function relationships(state = initialState, action) { return normalizeRelationship(state, action.relationship); case RELATIONSHIPS_FETCH_SUCCESS: return normalizeRelationships(state, action.relationships); + case DOMAIN_BLOCK_SUCCESS: + return state.setIn([action.accountId, 'domain_blocking'], true); + case DOMAIN_UNBLOCK_SUCCESS: + return state.setIn([action.accountId, 'domain_blocking'], false); default: return state; } diff --git a/app/models/account_domain_block.rb b/app/models/account_domain_block.rb index 9241d97205..bdd64c01a0 100644 --- a/app/models/account_domain_block.rb +++ b/app/models/account_domain_block.rb @@ -14,6 +14,7 @@ class AccountDomainBlock < ApplicationRecord include Paginable belongs_to :account, required: true + validates :domain, presence: true, uniqueness: { scope: :account_id } after_create :remove_blocking_cache after_destroy :remove_blocking_cache diff --git a/app/models/concerns/account_interactions.rb b/app/models/concerns/account_interactions.rb index c8006bd0b5..0ef7512e29 100644 --- a/app/models/concerns/account_interactions.rb +++ b/app/models/concerns/account_interactions.rb @@ -23,6 +23,12 @@ module AccountInteractions def requested_map(target_account_ids, account_id) follow_mapping(FollowRequest.where(target_account_id: target_account_ids, account_id: account_id), :target_account_id) end + + def domain_blocking_map(target_account_ids, account_id) + accounts_map = Account.where(id: target_account_ids).select('id, domain').map { |a| [a.id, a.domain] }.to_h + blocked_domains = AccountDomainBlock.where(account_id: account_id, domain: accounts_map.values).pluck(:domain) + accounts_map.map { |id, domain| [id, blocked_domains.include?(domain)] }.to_h + end end included do diff --git a/app/models/status.rb b/app/models/status.rb index 70021eb65b..80f33a7c77 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -67,7 +67,8 @@ class Status < ApplicationRecord scope :local_only, -> { left_outer_joins(:account).where(accounts: { domain: nil }) } scope :excluding_silenced_accounts, -> { left_outer_joins(:account).where(accounts: { silenced: false }) } scope :including_silenced_accounts, -> { left_outer_joins(:account).where(accounts: { silenced: true }) } - scope :not_excluded_by_account, ->(account) { where.not(account_id: account.excluded_from_timeline_account_ids, accounts: { domain: account.excluded_from_timeline_domains }) } + scope :not_excluded_by_account, ->(account) { where.not(account_id: account.excluded_from_timeline_account_ids) } + scope :not_domain_blocked_by_account, ->(account) { left_outer_joins(:account).where.not(accounts: { domain: account.excluded_from_timeline_domains }) } cache_associated :account, :application, :media_attachments, :tags, :stream_entry, mentions: :account, reblog: [:account, :application, :stream_entry, :tags, :media_attachments, mentions: :account], thread: :account @@ -152,13 +153,13 @@ class Status < ApplicationRecord def as_public_timeline(account = nil, local_only = false) query = timeline_scope(local_only).without_replies - apply_timeline_filters(query, account) + apply_timeline_filters(query, account, local_only) end def as_tag_timeline(tag, account = nil, local_only = false) query = timeline_scope(local_only).tagged_with(tag) - apply_timeline_filters(query, account) + apply_timeline_filters(query, account, local_only) end def as_outbox_timeline(account) @@ -222,16 +223,17 @@ class Status < ApplicationRecord .without_reblogs end - def apply_timeline_filters(query, account) + def apply_timeline_filters(query, account, local_only) if account.nil? filter_timeline_default(query) else - filter_timeline_for_account(query, account) + filter_timeline_for_account(query, account, local_only) end end - def filter_timeline_for_account(query, account) + def filter_timeline_for_account(query, account, local_only) query = query.not_excluded_by_account(account) + query = query.not_domain_blocked_by_account(account) unless local_only query = query.in_allowed_languages(account) if account.allowed_languages.present? query.merge(account_silencing_filter(account)) end diff --git a/app/services/block_domain_from_account_service.rb b/app/services/block_domain_from_account_service.rb new file mode 100644 index 0000000000..cae7abcbdc --- /dev/null +++ b/app/services/block_domain_from_account_service.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +class BlockDomainFromAccountService < BaseService + def call(account, domain) + account.block_domain!(domain) + account.passive_relationships.where(account: Account.where(domain: domain)).delete_all + end +end diff --git a/app/services/notify_service.rb b/app/services/notify_service.rb index 150ffe6b28..ce22b65059 100644 --- a/app/services/notify_service.rb +++ b/app/services/notify_service.rb @@ -37,15 +37,15 @@ class NotifyService < BaseService end def blocked? - blocked = @recipient.suspended? # Skip if the recipient account is suspended anyway - blocked ||= @recipient.id == @notification.from_account.id # Skip for interactions with self - blocked ||= @recipient.domain_blocking?(@notification.from_account.domain) # Skip for domain blocked accounts - blocked ||= @recipient.blocking?(@notification.from_account) # Skip for blocked accounts - blocked ||= (@notification.from_account.silenced? && !@recipient.following?(@notification.from_account)) # Hellban - blocked ||= (@recipient.user.settings.interactions['must_be_follower'] && !@notification.from_account.following?(@recipient)) # Options - blocked ||= (@recipient.user.settings.interactions['must_be_following'] && !@recipient.following?(@notification.from_account)) # Options + blocked = @recipient.suspended? # Skip if the recipient account is suspended anyway + blocked ||= @recipient.id == @notification.from_account.id # Skip for interactions with self + blocked ||= @recipient.domain_blocking?(@notification.from_account.domain) && !@recipient.following?(@notification.from_account) # Skip for domain blocked accounts + blocked ||= @recipient.blocking?(@notification.from_account) # Skip for blocked accounts + blocked ||= (@notification.from_account.silenced? && !@recipient.following?(@notification.from_account)) # Hellban + blocked ||= (@recipient.user.settings.interactions['must_be_follower'] && !@notification.from_account.following?(@recipient)) # Options + blocked ||= (@recipient.user.settings.interactions['must_be_following'] && !@recipient.following?(@notification.from_account)) # Options blocked ||= conversation_muted? - blocked ||= send("blocked_#{@notification.type}?") # Type-dependent filters + blocked ||= send("blocked_#{@notification.type}?") # Type-dependent filters blocked end diff --git a/app/services/process_interaction_service.rb b/app/services/process_interaction_service.rb index bc8361510c..e9c01103d5 100644 --- a/app/services/process_interaction_service.rb +++ b/app/services/process_interaction_service.rb @@ -21,9 +21,9 @@ class ProcessInteractionService < BaseService case verb(xml) when :follow - follow!(account, target_account) unless target_account.locked? || target_account.blocking?(account) + follow!(account, target_account) unless target_account.locked? || target_account.blocking?(account) || target_account.domain_blocking?(account.domain) when :request_friend - follow_request!(account, target_account) unless !target_account.locked? || target_account.blocking?(account) + follow_request!(account, target_account) unless !target_account.locked? || target_account.blocking?(account) || target_account.domain_blocking?(account.domain) when :authorize authorize_follow_request!(account, target_account) when :reject diff --git a/app/services/send_interaction_service.rb b/app/services/send_interaction_service.rb index 99113eecaf..504f41c727 100644 --- a/app/services/send_interaction_service.rb +++ b/app/services/send_interaction_service.rb @@ -6,12 +6,22 @@ class SendInteractionService < BaseService # @param [Account] source_account # @param [Account] target_account def call(xml, source_account, target_account) - envelope = salmon.pack(xml, source_account.keypair) - salmon.post(target_account.salmon_url, envelope) + @xml = xml + @source_account = source_account + @target_account = target_account + + return if block_notification? + + envelope = salmon.pack(@xml, @source_account.keypair) + salmon.post(@target_account.salmon_url, envelope) end private + def block_notification? + DomainBlock.blocked?(@target_account.domain) + end + def salmon @salmon ||= OStatus2::Salmon.new end diff --git a/app/views/api/v1/accounts/relationship.rabl b/app/views/api/v1/accounts/relationship.rabl index d6f1dd48ab..4f7763d9d0 100644 --- a/app/views/api/v1/accounts/relationship.rabl +++ b/app/views/api/v1/accounts/relationship.rabl @@ -1,8 +1,9 @@ object @account attribute :id -node(:following) { |account| @following[account.id] || false } -node(:followed_by) { |account| @followed_by[account.id] || false } -node(:blocking) { |account| @blocking[account.id] || false } -node(:muting) { |account| @muting[account.id] || false } -node(:requested) { |account| @requested[account.id] || false } +node(:following) { |account| @following[account.id] || false } +node(:followed_by) { |account| @followed_by[account.id] || false } +node(:blocking) { |account| @blocking[account.id] || false } +node(:muting) { |account| @muting[account.id] || false } +node(:requested) { |account| @requested[account.id] || false } +node(:domain_blocking) { |account| @domain_blocking[account.id] || false } diff --git a/spec/services/block_domain_from_account_service_spec.rb b/spec/services/block_domain_from_account_service_spec.rb new file mode 100644 index 0000000000..e7ee343723 --- /dev/null +++ b/spec/services/block_domain_from_account_service_spec.rb @@ -0,0 +1,19 @@ +require 'rails_helper' + +RSpec.describe BlockDomainFromAccountService do + let!(:wolf) { Fabricate(:account, username: 'wolf', domain: 'evil.org') } + let!(:alice) { Fabricate(:account, username: 'alice') } + + subject { BlockDomainFromAccountService.new } + + it 'creates domain block' do + subject.call(alice, 'evil.org') + expect(alice.domain_blocking?('evil.org')).to be true + end + + it 'purge followers from blocked domain' do + wolf.follow!(alice) + subject.call(alice, 'evil.org') + expect(wolf.following?(alice)).to be false + end +end diff --git a/spec/services/notify_service_spec.rb b/spec/services/notify_service_spec.rb index 29bd741aa6..7a66bd0fe4 100644 --- a/spec/services/notify_service_spec.rb +++ b/spec/services/notify_service_spec.rb @@ -22,6 +22,12 @@ RSpec.describe NotifyService do is_expected.to_not change(Notification, :count) end + it 'does still notify when sender\'s domain is blocked but sender is followed' do + recipient.block_domain!(sender.domain) + recipient.follow!(sender) + is_expected.to change(Notification, :count) + end + it 'does not notify when sender is silenced and not followed' do sender.update(silenced: true) is_expected.to_not change(Notification, :count) -- GitLab