Merge branch 'master' into glitch-soc/merge-upstream
Conflicts: - `app/javascript/mastodon/actions/compose.js`: Not a “real” conflict, but change too close to a change we made to fix the vanilla WebUI locally pushing authored local-only toots in the public TL view.
This commit is contained in:
		
						commit
						b9f351d845
					
				
					 90 changed files with 414 additions and 144 deletions
				
			
		| 
						 | 
				
			
			@ -1,4 +1,3 @@
 | 
			
		|||
https://github.com/heroku/heroku-buildpack-apt
 | 
			
		||||
https://github.com/Scalingo/ffmpeg-buildpack
 | 
			
		||||
https://github.com/Scalingo/nodejs-buildpack
 | 
			
		||||
https://github.com/Scalingo/ruby-buildpack
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -72,11 +72,12 @@ aliases:
 | 
			
		|||
        - run:
 | 
			
		||||
            name: Set bundler settings
 | 
			
		||||
            command: |
 | 
			
		||||
              bundle config clean 'true'
 | 
			
		||||
              bundle config deployment 'true'
 | 
			
		||||
              bundle config with 'pam_authentication'
 | 
			
		||||
              bundle config without 'development production'
 | 
			
		||||
              bundle config frozen 'true'
 | 
			
		||||
              bundle config --local clean 'true'
 | 
			
		||||
              bundle config --local deployment 'true'
 | 
			
		||||
              bundle config --local with 'pam_authentication'
 | 
			
		||||
              bundle config --local without 'development production'
 | 
			
		||||
              bundle config --local frozen 'true'
 | 
			
		||||
              bundle config --local path $BUNDLE_PATH
 | 
			
		||||
        - run:
 | 
			
		||||
            name: Install bundler dependencies
 | 
			
		||||
            command: bundle check || (bundle install && bundle clean)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										3
									
								
								app.json
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								app.json
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -88,9 +88,6 @@
 | 
			
		|||
    {
 | 
			
		||||
      "url": "https://github.com/heroku/heroku-buildpack-apt"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "url": "heroku/nodejs"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "url": "heroku/ruby"
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,6 +58,7 @@ class Api::V1::StatusesController < Api::BaseController
 | 
			
		|||
 | 
			
		||||
    @status.discard
 | 
			
		||||
    RemovalWorker.perform_async(@status.id, redraft: true)
 | 
			
		||||
    @status.account.statuses_count = @status.account.statuses_count - 1
 | 
			
		||||
 | 
			
		||||
    render json: @status, serializer: REST::StatusSerializer, source_requested: true
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,7 +56,7 @@ class ApplicationController < ActionController::Base
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def store_current_location
 | 
			
		||||
    store_location_for(:user, request.url) unless request.format == :json
 | 
			
		||||
    store_location_for(:user, request.url) unless [:json, :rss].include?(request.format&.to_sym)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def require_admin!
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -163,7 +163,6 @@ export function submitCompose(routerHistory) {
 | 
			
		|||
 | 
			
		||||
      // To make the app more responsive, immediately push the status
 | 
			
		||||
      // into the columns
 | 
			
		||||
 | 
			
		||||
      const insertIfOnline = timelineId => {
 | 
			
		||||
        const timeline = getState().getIn(['timelines', timelineId]);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -181,6 +180,7 @@ export function submitCompose(routerHistory) {
 | 
			
		|||
        if (!response.data.local_only) {
 | 
			
		||||
          insertIfOnline('public');
 | 
			
		||||
        }
 | 
			
		||||
        insertIfOnline(`account:${response.data.account.id}`);
 | 
			
		||||
      }
 | 
			
		||||
    }).catch(function (error) {
 | 
			
		||||
      dispatch(submitComposeFail(error));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,7 @@ import openDB from '../storage/db';
 | 
			
		|||
import { evictStatus } from '../storage/modifier';
 | 
			
		||||
 | 
			
		||||
import { deleteFromTimelines } from './timelines';
 | 
			
		||||
import { importFetchedStatus, importFetchedStatuses, importAccount, importStatus } from './importer';
 | 
			
		||||
import { importFetchedStatus, importFetchedStatuses, importAccount, importStatus, importFetchedAccount } from './importer';
 | 
			
		||||
import { ensureComposeIsVisible } from './compose';
 | 
			
		||||
 | 
			
		||||
export const STATUS_FETCH_REQUEST = 'STATUS_FETCH_REQUEST';
 | 
			
		||||
| 
						 | 
				
			
			@ -155,6 +155,7 @@ export function deleteStatus(id, routerHistory, withRedraft = false) {
 | 
			
		|||
      evictStatus(id);
 | 
			
		||||
      dispatch(deleteStatusSuccess(id));
 | 
			
		||||
      dispatch(deleteFromTimelines(id));
 | 
			
		||||
      dispatch(importFetchedAccount(response.data.account));
 | 
			
		||||
 | 
			
		||||
      if (withRedraft) {
 | 
			
		||||
        dispatch(redraft(status, response.data.text));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -72,6 +72,7 @@ const refreshHomeTimelineAndNotification = (dispatch, done) => {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
export const connectUserStream         = () => connectTimelineStream('home', 'user', refreshHomeTimelineAndNotification);
 | 
			
		||||
export const connectUserTimelineStream = (accountId) => connectTimelineStream(`account:${accountId}`, 'user');
 | 
			
		||||
export const connectCommunityStream    = ({ onlyMedia } = {}) => connectTimelineStream(`community${onlyMedia ? ':media' : ''}`, `public:local${onlyMedia ? ':media' : ''}`);
 | 
			
		||||
export const connectPublicStream       = ({ onlyMedia, onlyRemote } = {}) => connectTimelineStream(`public${onlyRemote ? ':remote' : ''}${onlyMedia ? ':media' : ''}`, `public${onlyRemote ? ':remote' : ''}${onlyMedia ? ':media' : ''}`);
 | 
			
		||||
export const connectHashtagStream      = (id, tag, local, accept) => connectTimelineStream(`hashtag:${id}${local ? ':local' : ''}`, `hashtag${local ? ':local' : ''}&tag=${tag}`, null, accept);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,7 +37,7 @@ export function counterRenderer(counterType, isBold = true) {
 | 
			
		|||
    return (displayNumber, pluralReady) => (
 | 
			
		||||
      <FormattedMessage
 | 
			
		||||
        id='account.following_counter'
 | 
			
		||||
        defaultMessage='{count, plural, other {{counter} Following}}'
 | 
			
		||||
        defaultMessage='{count, plural, one {{counter} Following} other {{counter} Following}}'
 | 
			
		||||
        values={{
 | 
			
		||||
          count: pluralReady,
 | 
			
		||||
          counter: renderCounter(displayNumber),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,7 +20,7 @@ const mapStateToProps = (state, { scrollKey }) => {
 | 
			
		|||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default @connect(mapStateToProps)
 | 
			
		||||
export default @connect(mapStateToProps, null, null, { forwardRef: true })
 | 
			
		||||
class ScrollableList extends PureComponent {
 | 
			
		||||
 | 
			
		||||
  static contextTypes = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,6 +15,8 @@ import { FormattedMessage } from 'react-intl';
 | 
			
		|||
import { fetchAccountIdentityProofs } from '../../actions/identity_proofs';
 | 
			
		||||
import MissingIndicator from 'mastodon/components/missing_indicator';
 | 
			
		||||
import TimelineHint from 'mastodon/components/timeline_hint';
 | 
			
		||||
import { me } from 'mastodon/initial_state';
 | 
			
		||||
import { connectUserTimelineStream } from '../../actions/streaming';
 | 
			
		||||
 | 
			
		||||
const emptyList = ImmutableList();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -73,6 +75,12 @@ class AccountTimeline extends ImmutablePureComponent {
 | 
			
		|||
    this.props.dispatch(expandAccountTimeline(accountId, { withReplies }));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  componentDidMount () {
 | 
			
		||||
    if (this.props.params.accountId === me) {
 | 
			
		||||
      this.disconnect = this.props.dispatch(connectUserTimelineStream(me));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  componentWillReceiveProps (nextProps) {
 | 
			
		||||
    if ((nextProps.params.accountId !== this.props.params.accountId && nextProps.params.accountId) || nextProps.withReplies !== this.props.withReplies) {
 | 
			
		||||
      this.props.dispatch(fetchAccount(nextProps.params.accountId));
 | 
			
		||||
| 
						 | 
				
			
			@ -86,6 +94,13 @@ class AccountTimeline extends ImmutablePureComponent {
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  componentWillUnmount () {
 | 
			
		||||
    if (this.disconnect) {
 | 
			
		||||
      this.disconnect();
 | 
			
		||||
      this.disconnect = null;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  handleLoadMore = maxId => {
 | 
			
		||||
    this.props.dispatch(expandAccountTimeline(this.props.params.accountId, { maxId, withReplies: this.props.withReplies }));
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "مُتابِعون",
 | 
			
		||||
  "account.followers.empty": "لا أحد يتبع هذا الحساب بعد.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "هذا الحساب لا يتبع أحدًا بعد.",
 | 
			
		||||
  "account.follows_you": "يتابعك",
 | 
			
		||||
  "account.hide_reblogs": "إخفاء ترقيات @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Siguidores",
 | 
			
		||||
  "account.followers.empty": "Naide sigue a esti usuariu entá.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "Esti usuariu entá nun sigue a naide.",
 | 
			
		||||
  "account.follows_you": "Síguete",
 | 
			
		||||
  "account.hide_reblogs": "Anubrir les comparticiones de @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Последователи",
 | 
			
		||||
  "account.followers.empty": "Все още никой не следва този потребител.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "Този потребител все още не следва никого.",
 | 
			
		||||
  "account.follows_you": "Твой последовател",
 | 
			
		||||
  "account.hide_reblogs": "Hide boosts from @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "অনুসরণকারী",
 | 
			
		||||
  "account.followers.empty": "এই সদস্যকে এখনো কেউ অনুসরণ করে না।.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "এই সদস্য কাওকে এখনো অনুসরণ করেন না.",
 | 
			
		||||
  "account.follows_you": "আপনাকে অনুসরণ করে",
 | 
			
		||||
  "account.hide_reblogs": "@{name}'র সমর্থনগুলি লুকিয়ে ফেলুন",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Sledující",
 | 
			
		||||
  "account.followers.empty": "Tohoto uživatele ještě nikdo nesleduje.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "Tento uživatel ještě nikoho nesleduje.",
 | 
			
		||||
  "account.follows_you": "Sleduje vás",
 | 
			
		||||
  "account.hide_reblogs": "Skrýt boosty od uživatele @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Dilynwyr",
 | 
			
		||||
  "account.followers.empty": "Nid oes neb yn dilyn y defnyddiwr hwn eto.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "Nid yw'r defnyddiwr hwn yn dilyn unrhyw un eto.",
 | 
			
		||||
  "account.follows_you": "Yn eich dilyn chi",
 | 
			
		||||
  "account.hide_reblogs": "Cuddio bwstiau o @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Følgere",
 | 
			
		||||
  "account.followers.empty": "Der er endnu ingen der følger denne bruger.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "Denne bruger følger endnu ikke nogen.",
 | 
			
		||||
  "account.follows_you": "Følger dig",
 | 
			
		||||
  "account.hide_reblogs": "Skjul fremhævelserne fra @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -146,7 +146,7 @@
 | 
			
		|||
        "id": "account.statuses_counter"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "defaultMessage": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
        "defaultMessage": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
        "id": "account.following_counter"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
| 
						 | 
				
			
			@ -2659,6 +2659,22 @@
 | 
			
		|||
        "defaultMessage": "Boost",
 | 
			
		||||
        "id": "status.reblog"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "defaultMessage": "Public",
 | 
			
		||||
        "id": "privacy.public.short"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "defaultMessage": "Unlisted",
 | 
			
		||||
        "id": "privacy.unlisted.short"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "defaultMessage": "Followers-only",
 | 
			
		||||
        "id": "privacy.private.short"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "defaultMessage": "Direct",
 | 
			
		||||
        "id": "privacy.direct.short"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "defaultMessage": "You can press {combo} to skip this next time",
 | 
			
		||||
        "id": "boost_modal.combo"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Followers",
 | 
			
		||||
  "account.followers.empty": "No one follows this user yet.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "This user doesn't follow anyone yet.",
 | 
			
		||||
  "account.follows_you": "Follows you",
 | 
			
		||||
  "account.hide_reblogs": "Hide boosts from @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Jälgijad",
 | 
			
		||||
  "account.followers.empty": "Keegi ei jälgi seda kasutajat veel.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "See kasutaja ei jälgi veel kedagi.",
 | 
			
		||||
  "account.follows_you": "Jälgib Teid",
 | 
			
		||||
  "account.hide_reblogs": "Peida upitused kasutajalt @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Jarraitzaileak",
 | 
			
		||||
  "account.followers.empty": "Ez du inork erabiltzaile hau jarraitzen oraindik.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "Erabiltzaile honek ez du inor jarraitzen oraindik.",
 | 
			
		||||
  "account.follows_you": "Jarraitzen dizu",
 | 
			
		||||
  "account.hide_reblogs": "Ezkutatu @{name}(r)en bultzadak",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Seuraajaa",
 | 
			
		||||
  "account.followers.empty": "Tällä käyttäjällä ei ole vielä seuraajia.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "Tämä käyttäjä ei vielä seuraa ketään.",
 | 
			
		||||
  "account.follows_you": "Seuraa sinua",
 | 
			
		||||
  "account.hide_reblogs": "Piilota buustaukset käyttäjältä @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Followers",
 | 
			
		||||
  "account.followers.empty": "No one follows this user yet.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "This user doesn't follow anyone yet.",
 | 
			
		||||
  "account.follows_you": "Follows you",
 | 
			
		||||
  "account.hide_reblogs": "Hide boosts from @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "עוקבים",
 | 
			
		||||
  "account.followers.empty": "אף אחד לא עוקב אחר המשתמש הזה עדיין.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "משתמש זה לא עוקב אחר אף אחד עדיין.",
 | 
			
		||||
  "account.follows_you": "במעקב אחריך",
 | 
			
		||||
  "account.hide_reblogs": "להסתיר הידהודים מאת @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "फॉलोवर",
 | 
			
		||||
  "account.followers.empty": "कोई भी इस यूज़र् को फ़ॉलो नहीं करता है",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "यह यूज़र् अभी तक किसी को फॉलो नहीं करता है।",
 | 
			
		||||
  "account.follows_you": "आपको फॉलो करता है",
 | 
			
		||||
  "account.hide_reblogs": "@{name} के बूस्ट छुपाएं",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Sljedbenici",
 | 
			
		||||
  "account.followers.empty": "No one follows this user yet.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "This user doesn't follow anyone yet.",
 | 
			
		||||
  "account.follows_you": "te slijedi",
 | 
			
		||||
  "account.hide_reblogs": "Hide boosts from @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Pengikut",
 | 
			
		||||
  "account.followers.empty": "Tidak ada satupun yang mengkuti pengguna ini saat ini.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "Pengguna ini belum mengikuti siapapun.",
 | 
			
		||||
  "account.follows_you": "Mengikuti anda",
 | 
			
		||||
  "account.hide_reblogs": "Sembunyikan boosts dari @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Sequanti",
 | 
			
		||||
  "account.followers.empty": "No one follows this user yet.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "This user doesn't follow anyone yet.",
 | 
			
		||||
  "account.follows_you": "Sequas tu",
 | 
			
		||||
  "account.hide_reblogs": "Hide boosts from @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Fylgjendur",
 | 
			
		||||
  "account.followers.empty": "Ennþá fylgist enginn með þessum notanda.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "Þessi notandi fylgist ennþá ekki með neinum.",
 | 
			
		||||
  "account.follows_you": "Fylgir þér",
 | 
			
		||||
  "account.hide_reblogs": "Fela endurbirtingar fyrir @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "მიმდევრები",
 | 
			
		||||
  "account.followers.empty": "No one follows this user yet.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "This user doesn't follow anyone yet.",
 | 
			
		||||
  "account.follows_you": "მოგყვებათ",
 | 
			
		||||
  "account.hide_reblogs": "დაიმალოს ბუსტები @{name}-სგან",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Imeḍfaren",
 | 
			
		||||
  "account.followers.empty": "Ar tura, ulac yiwen i yeṭṭafaṛen amseqdac-agi.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{count} n umeḍfar} other {{count} n imeḍfaren}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "Ar tura, amseqdac-agi ur yeṭṭafaṛ yiwen.",
 | 
			
		||||
  "account.follows_you": "Yeṭṭafaṛ-ik",
 | 
			
		||||
  "account.hide_reblogs": "Ffer ayen i ibeṭṭu @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Оқырмандар",
 | 
			
		||||
  "account.followers.empty": "Әлі ешкім жазылмаған.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "Ешкімге жазылмапты.",
 | 
			
		||||
  "account.follows_you": "Сізге жазылыпты",
 | 
			
		||||
  "account.hide_reblogs": "@{name} атты қолданушының әрекеттерін жасыру",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Followers",
 | 
			
		||||
  "account.followers.empty": "No one follows this user yet.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "This user doesn't follow anyone yet.",
 | 
			
		||||
  "account.follows_you": "Follows you",
 | 
			
		||||
  "account.hide_reblogs": "Hide boosts from @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Followers",
 | 
			
		||||
  "account.followers.empty": "No one follows this user yet.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "This user doesn't follow anyone yet.",
 | 
			
		||||
  "account.follows_you": "Follows you",
 | 
			
		||||
  "account.hide_reblogs": "Hide boosts from @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Followers",
 | 
			
		||||
  "account.followers.empty": "No one follows this user yet.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "This user doesn't follow anyone yet.",
 | 
			
		||||
  "account.follows_you": "Follows you",
 | 
			
		||||
  "account.hide_reblogs": "Hide boosts from @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Sekotāji",
 | 
			
		||||
  "account.followers.empty": "Šim lietotājam nav sekotāju.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "Šis lietotājs pagaidām nevienam neseko.",
 | 
			
		||||
  "account.follows_you": "Seko tev",
 | 
			
		||||
  "account.hide_reblogs": "Paslēpt paceltos ierakstus no lietotāja @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Следбеници",
 | 
			
		||||
  "account.followers.empty": "Никој не го следи овој корисник сеуште.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "Корисникот не следи никој сеуште.",
 | 
			
		||||
  "account.follows_you": "Те следи тебе",
 | 
			
		||||
  "account.hide_reblogs": "Сокриј буст од @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "പിന്തുടരുന്നവർ",
 | 
			
		||||
  "account.followers.empty": "ഈ ഉപയോക്താവിനെ ആരും ഇതുവരെ പിന്തുടരുന്നില്ല.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "ഈ ഉപയോക്താവ് ആരേയും ഇതുവരെ പിന്തുടരുന്നില്ല.",
 | 
			
		||||
  "account.follows_you": "നിങ്ങളെ പിന്തുടരുന്നു",
 | 
			
		||||
  "account.hide_reblogs": "@{name} ബൂസ്റ്റ് ചെയ്തവ മറയ്കുക",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "अनुयायी",
 | 
			
		||||
  "account.followers.empty": "ह्या वापरकर्त्याचा आतापर्यंत कोणी अनुयायी नाही.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "हा वापरकर्ता अजूनपर्यंत कोणाचा अनुयायी नाही.",
 | 
			
		||||
  "account.follows_you": "तुमचा अनुयायी आहे",
 | 
			
		||||
  "account.hide_reblogs": "@{name} पासून सर्व बूस्ट लपवा",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Followers",
 | 
			
		||||
  "account.followers.empty": "No one follows this user yet.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "This user doesn't follow anyone yet.",
 | 
			
		||||
  "account.follows_you": "Follows you",
 | 
			
		||||
  "account.hide_reblogs": "Hide boosts from @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Volgers",
 | 
			
		||||
  "account.followers.empty": "Niemand volgt nog deze gebruiker.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "Deze gebruiker volgt nog niemand.",
 | 
			
		||||
  "account.follows_you": "Volgt jou",
 | 
			
		||||
  "account.hide_reblogs": "Verberg boosts van @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Fylgjarar",
 | 
			
		||||
  "account.followers.empty": "Ingen fylgjer denne brukaren enno.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "Denne brukaren fylgjer ikkje nokon enno.",
 | 
			
		||||
  "account.follows_you": "Fylgjer deg",
 | 
			
		||||
  "account.hide_reblogs": "Gøym fremhevingar frå @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Følgere",
 | 
			
		||||
  "account.followers.empty": "Ingen følger denne brukeren ennå.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "Denne brukeren følger ikke noen enda.",
 | 
			
		||||
  "account.follows_you": "Følger deg",
 | 
			
		||||
  "account.hide_reblogs": "Skjul fremhevinger fra @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Seguidors",
 | 
			
		||||
  "account.followers.empty": "Degun sèc pas aqueste utilizaire pel moment.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "Aqueste utilizaire sèc pas degun pel moment.",
 | 
			
		||||
  "account.follows_you": "Vos sèc",
 | 
			
		||||
  "account.hide_reblogs": "Rescondre los partatges de @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Śledzący",
 | 
			
		||||
  "account.followers.empty": "Nikt jeszcze nie śledzi tego użytkownika.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "Ten użytkownik nie śledzi jeszcze nikogo.",
 | 
			
		||||
  "account.follows_you": "Śledzi Cię",
 | 
			
		||||
  "account.hide_reblogs": "Ukryj podbicia od @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Urmăritori",
 | 
			
		||||
  "account.followers.empty": "Acest utilizator nu are încă urmăritori.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "Acest utilizator nu urmărește pe nimeni încă.",
 | 
			
		||||
  "account.follows_you": "Te urmărește",
 | 
			
		||||
  "account.hide_reblogs": "Ascunde impulsurile de la @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Sighiduras",
 | 
			
		||||
  "account.followers.empty": "Nemos sighit ancora custa persone.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "Custa persone non sighit ancora a nemos.",
 | 
			
		||||
  "account.follows_you": "Ti sighit",
 | 
			
		||||
  "account.hide_reblogs": "Cua is cumpartziduras de @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Sledujúci",
 | 
			
		||||
  "account.followers.empty": "Tohto používateľa ešte nikto nenásleduje.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "Tento používateľ ešte nikoho nenasleduje.",
 | 
			
		||||
  "account.follows_you": "Nasleduje ťa",
 | 
			
		||||
  "account.hide_reblogs": "Skry vyzdvihnutia od @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Sledilci",
 | 
			
		||||
  "account.followers.empty": "Nihče ne sledi temu uporabniku.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "Ta uporabnik še ne sledi nikomur.",
 | 
			
		||||
  "account.follows_you": "Sledi tebi",
 | 
			
		||||
  "account.hide_reblogs": "Skrij spodbude od @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Pratioca",
 | 
			
		||||
  "account.followers.empty": "No one follows this user yet.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "This user doesn't follow anyone yet.",
 | 
			
		||||
  "account.follows_you": "Prati Vas",
 | 
			
		||||
  "account.hide_reblogs": "Sakrij podrške koje daje korisnika @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Пратиоци",
 | 
			
		||||
  "account.followers.empty": "Тренутно нико не прати овог корисника.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "Корисник тренутно не прати никога.",
 | 
			
		||||
  "account.follows_you": "Прати Вас",
 | 
			
		||||
  "account.hide_reblogs": "Сакриј подршке које даје корисника @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Följare",
 | 
			
		||||
  "account.followers.empty": "Ingen följer denna användare än.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "Denna användare följer inte någon än.",
 | 
			
		||||
  "account.follows_you": "Följer dig",
 | 
			
		||||
  "account.hide_reblogs": "Dölj knuffar från @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Followers",
 | 
			
		||||
  "account.followers.empty": "No one follows this user yet.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "This user doesn't follow anyone yet.",
 | 
			
		||||
  "account.follows_you": "Follows you",
 | 
			
		||||
  "account.hide_reblogs": "Hide boosts from @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "பின்தொடர்பவர்கள்",
 | 
			
		||||
  "account.followers.empty": "இதுவரை யாரும் இந்த பயனரைப் பின்தொடரவில்லை.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "இந்த பயனர் இதுவரை யாரையும் பின்தொடரவில்லை.",
 | 
			
		||||
  "account.follows_you": "உங்களைப் பின்தொடர்கிறார்",
 | 
			
		||||
  "account.hide_reblogs": "இருந்து ஊக்கியாக மறை @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Followers",
 | 
			
		||||
  "account.followers.empty": "No one follows this user yet.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "This user doesn't follow anyone yet.",
 | 
			
		||||
  "account.follows_you": "Follows you",
 | 
			
		||||
  "account.hide_reblogs": "Hide boosts from @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "అనుచరులు",
 | 
			
		||||
  "account.followers.empty": "ఈ వినియోగదారుడిని ఇంకా ఎవరూ అనుసరించడంలేదు.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "ఈ వినియోగదారి ఇంకా ఎవరినీ అనుసరించడంలేదు.",
 | 
			
		||||
  "account.follows_you": "మిమ్మల్ని అనుసరిస్తున్నారు",
 | 
			
		||||
  "account.hide_reblogs": "@{name} నుంచి బూస్ట్ లను దాచిపెట్టు",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "ผู้ติดตาม",
 | 
			
		||||
  "account.followers.empty": "ยังไม่มีใครติดตามผู้ใช้นี้",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "ผู้ใช้นี้ยังไม่ได้ติดตามใคร",
 | 
			
		||||
  "account.follows_you": "ติดตามคุณ",
 | 
			
		||||
  "account.hide_reblogs": "ซ่อนการดันจาก @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Takipçi",
 | 
			
		||||
  "account.followers.empty": "Henüz kimse bu kullanıcıyı takip etmiyor.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "Bu kullanıcı henüz kimseyi takip etmiyor.",
 | 
			
		||||
  "account.follows_you": "Seni takip ediyor",
 | 
			
		||||
  "account.hide_reblogs": "@{name} kişisinin yinelemelerini gizle",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Followers",
 | 
			
		||||
  "account.followers.empty": "No one follows this user yet.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "This user doesn't follow anyone yet.",
 | 
			
		||||
  "account.follows_you": "Follows you",
 | 
			
		||||
  "account.hide_reblogs": "Hide boosts from @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "Підписники",
 | 
			
		||||
  "account.followers.empty": "Ніхто ще не підписався на цього користувача.",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "Цей користувач ще ні на кого не підписався.",
 | 
			
		||||
  "account.follows_you": "Підписаний(-а) на вас",
 | 
			
		||||
  "account.hide_reblogs": "Сховати передмухи від @{name}",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "پیروکار",
 | 
			
		||||
  "account.followers.empty": "\"ہنوز اس صارف کی کوئی پیروی نہیں کرتا\".",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "\"یہ صارف ہنوز کسی کی پیروی نہیں کرتا ہے\".",
 | 
			
		||||
  "account.follows_you": "آپ کا پیروکار ہے",
 | 
			
		||||
  "account.hide_reblogs": "@{name} سے فروغ چھپائیں",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "關注的人",
 | 
			
		||||
  "account.followers.empty": "尚沒有人關注這位使用者。",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "這位使用者尚未關注任何使用者。",
 | 
			
		||||
  "account.follows_you": "關注你",
 | 
			
		||||
  "account.hide_reblogs": "隱藏 @{name} 的轉推",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@
 | 
			
		|||
  "account.followers": "關注者",
 | 
			
		||||
  "account.followers.empty": "尚沒有人關注這位使用者。",
 | 
			
		||||
  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, other {{counter} Following}}",
 | 
			
		||||
  "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}",
 | 
			
		||||
  "account.follows.empty": "這位使用者尚未關注任何使用者。",
 | 
			
		||||
  "account.follows_you": "關注了你",
 | 
			
		||||
  "account.hide_reblogs": "隱藏來自 @{name} 的轉推",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -767,10 +767,3 @@ html {
 | 
			
		|||
.compose-form .compose-form__warning {
 | 
			
		||||
  box-shadow: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.audio-player .video-player__controls button,
 | 
			
		||||
.audio-player .video-player__time-sep,
 | 
			
		||||
.audio-player .video-player__time-current,
 | 
			
		||||
.audio-player .video-player__time-total {
 | 
			
		||||
  color: $primary-text-color;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -157,6 +157,34 @@ class ActivityPub::Activity
 | 
			
		|||
    fetch_remote_original_status
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def dereference_object!
 | 
			
		||||
    return unless @object.is_a?(String)
 | 
			
		||||
    return if invalid_origin?(@object)
 | 
			
		||||
 | 
			
		||||
    object = fetch_resource(@object, true, signed_fetch_account)
 | 
			
		||||
    return unless object.present? && object.is_a?(Hash) && supported_context?(object)
 | 
			
		||||
 | 
			
		||||
    @object = object
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def signed_fetch_account
 | 
			
		||||
    first_mentioned_local_account || first_local_follower
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def first_mentioned_local_account
 | 
			
		||||
    audience = (as_array(@json['to']) + as_array(@json['cc'])).uniq
 | 
			
		||||
    local_usernames = audience.select { |uri| ActivityPub::TagManager.instance.local_uri?(uri) }
 | 
			
		||||
                              .map { |uri| ActivityPub::TagManager.instance.uri_to_local_id(uri, :username) }
 | 
			
		||||
 | 
			
		||||
    return if local_usernames.empty?
 | 
			
		||||
 | 
			
		||||
    Account.local.where(username: local_usernames).first
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def first_local_follower
 | 
			
		||||
    @account.followers.local.first
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def follow_request_from_object
 | 
			
		||||
    @follow_request ||= FollowRequest.find_by(target_account: @account, uri: object_uri) unless object_uri.nil?
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,15 +4,17 @@ class ActivityPub::Activity::Announce < ActivityPub::Activity
 | 
			
		|||
  def perform
 | 
			
		||||
    return reject_payload! if delete_arrived_first?(@json['id']) || !related_to_local_activity?
 | 
			
		||||
 | 
			
		||||
    RedisLock.acquire(lock_options) do |lock|
 | 
			
		||||
      if lock.acquired?
 | 
			
		||||
        original_status = status_from_object
 | 
			
		||||
 | 
			
		||||
        return reject_payload! if original_status.nil? || !announceable?(original_status)
 | 
			
		||||
 | 
			
		||||
    status = Status.find_by(account: @account, reblog: original_status)
 | 
			
		||||
        @status = Status.find_by(account: @account, reblog: original_status)
 | 
			
		||||
 | 
			
		||||
    return status unless status.nil?
 | 
			
		||||
        return @status unless @status.nil?
 | 
			
		||||
 | 
			
		||||
    status = Status.create!(
 | 
			
		||||
        @status = Status.create!(
 | 
			
		||||
          account: @account,
 | 
			
		||||
          reblog: original_status,
 | 
			
		||||
          uri: @json['id'],
 | 
			
		||||
| 
						 | 
				
			
			@ -21,8 +23,13 @@ class ActivityPub::Activity::Announce < ActivityPub::Activity
 | 
			
		|||
          visibility: visibility_from_audience
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    distribute(status)
 | 
			
		||||
    status
 | 
			
		||||
        distribute(@status)
 | 
			
		||||
      else
 | 
			
		||||
        raise Mastodon::RaceConditionError
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    @status
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
| 
						 | 
				
			
			@ -54,4 +61,8 @@ class ActivityPub::Activity::Announce < ActivityPub::Activity
 | 
			
		|||
  def reblog_of_local_status?
 | 
			
		||||
    status_from_uri(object_uri)&.account&.local?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def lock_options
 | 
			
		||||
    { redis: Redis.current, key: "announce:#{@object['id']}" }
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,12 @@ class ActivityPub::Activity::Block < ActivityPub::Activity
 | 
			
		|||
  def perform
 | 
			
		||||
    target_account = account_from_uri(object_uri)
 | 
			
		||||
 | 
			
		||||
    return if target_account.nil? || !target_account.local? || @account.blocking?(target_account)
 | 
			
		||||
    return if target_account.nil? || !target_account.local?
 | 
			
		||||
 | 
			
		||||
    if @account.blocking?(target_account)
 | 
			
		||||
      @account.block_relationships.find_by(target_account: target_account).update(uri: @json['id']) if @json['id'].present?
 | 
			
		||||
      return
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    UnfollowService.new.call(target_account, @account) if target_account.following?(@account)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,8 @@
 | 
			
		|||
 | 
			
		||||
class ActivityPub::Activity::Create < ActivityPub::Activity
 | 
			
		||||
  def perform
 | 
			
		||||
    dereference_object!
 | 
			
		||||
 | 
			
		||||
    case @object['type']
 | 
			
		||||
    when 'EncryptedMessage'
 | 
			
		||||
      create_encrypted_message
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,11 +13,62 @@ class ActivityPub::Activity::Undo < ActivityPub::Activity
 | 
			
		|||
      undo_like
 | 
			
		||||
    when 'Block'
 | 
			
		||||
      undo_block
 | 
			
		||||
    when nil
 | 
			
		||||
      handle_reference
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
 | 
			
		||||
  def handle_reference
 | 
			
		||||
    # Some implementations do not inline the object, and as we don't have a
 | 
			
		||||
    # global index, we have to guess what object it is.
 | 
			
		||||
    return if object_uri.nil?
 | 
			
		||||
 | 
			
		||||
    try_undo_announce || try_undo_accept || try_undo_follow || try_undo_like || try_undo_block || delete_later!(object_uri)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def try_undo_announce
 | 
			
		||||
    status = Status.where.not(reblog_of_id: nil).find_by(uri: object_uri, account: @account)
 | 
			
		||||
    if status.present?
 | 
			
		||||
      RemoveStatusService.new.call(status)
 | 
			
		||||
      true
 | 
			
		||||
    else
 | 
			
		||||
      false
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def try_undo_accept
 | 
			
		||||
    # We can't currently handle `Undo Accept` as we don't record `Accept`'s uri
 | 
			
		||||
    false
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def try_undo_follow
 | 
			
		||||
    follow = @account.follow_requests.find_by(uri: object_uri) || @account.active_relationships.find_by(uri: object_uri)
 | 
			
		||||
 | 
			
		||||
    if follow.present?
 | 
			
		||||
      follow.destroy
 | 
			
		||||
      true
 | 
			
		||||
    else
 | 
			
		||||
      false
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def try_undo_like
 | 
			
		||||
    # There is an index on accounts, but an account may have *many* favs, so this may be too costly
 | 
			
		||||
    false
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def try_undo_block
 | 
			
		||||
    block = @account.block_relationships.find_by(uri: object_uri)
 | 
			
		||||
    if block.present?
 | 
			
		||||
      UnblockService.new.call(@account, block.target_account)
 | 
			
		||||
      true
 | 
			
		||||
    else
 | 
			
		||||
      false
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def undo_announce
 | 
			
		||||
    return if object_uri.nil?
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,8 @@ class ActivityPub::Activity::Update < ActivityPub::Activity
 | 
			
		|||
  SUPPORTED_TYPES = %w(Application Group Organization Person Service).freeze
 | 
			
		||||
 | 
			
		||||
  def perform
 | 
			
		||||
    dereference_object!
 | 
			
		||||
 | 
			
		||||
    if equals_or_includes_any?(@object['type'], SUPPORTED_TYPES)
 | 
			
		||||
      update_account
 | 
			
		||||
    elsif equals_or_includes_any?(@object['type'], %w(Question))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,7 @@ module Mastodon
 | 
			
		|||
  class HostValidationError < ValidationError; end
 | 
			
		||||
  class LengthValidationError < ValidationError; end
 | 
			
		||||
  class DimensionsValidationError < ValidationError; end
 | 
			
		||||
  class StreamValidationError < ValidationError; end
 | 
			
		||||
  class RaceConditionError < Error; end
 | 
			
		||||
  class RateLimitExceededError < Error; end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -139,9 +139,15 @@ class FeedManager
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def clear_from_timeline(account, target_account)
 | 
			
		||||
    # Clear from timeline all statuses from or mentionning target_account
 | 
			
		||||
    timeline_key        = key(:home, account.id)
 | 
			
		||||
    timeline_status_ids = redis.zrange(timeline_key, 0, -1)
 | 
			
		||||
    target_statuses     = Status.where(id: timeline_status_ids, account: target_account)
 | 
			
		||||
    statuses            = Status.where(id: timeline_status_ids).select(:id, :reblog_of_id, :account_id).to_a
 | 
			
		||||
    reblogged_ids       = Status.where(id: statuses.map(&:reblog_of_id).compact, account: target_account).pluck(:id)
 | 
			
		||||
    with_mentions_ids   = Mention.active.where(status_id: statuses.flat_map { |s| [s.id, s.reblog_of_id] }.compact, account: target_account).pluck(:status_id)
 | 
			
		||||
    target_statuses     = statuses.filter do |status|
 | 
			
		||||
      status.account_id == target_account.id || reblogged_ids.include?(status.reblog_of_id) || with_mentions_ids.include?(status.id) || with_mentions_ids.include?(status.reblog_of_id)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    target_statuses.each do |status|
 | 
			
		||||
      unpush_from_home(account, status)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,7 +29,7 @@ module Remotable
 | 
			
		|||
        rescue Mastodon::UnexpectedResponseError, HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError => e
 | 
			
		||||
          Rails.logger.debug "Error fetching remote #{attachment_name}: #{e}"
 | 
			
		||||
          raise e unless suppress_errors
 | 
			
		||||
        rescue Paperclip::Errors::NotIdentifiedByImageMagickError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, Paperclip::Error, Mastodon::DimensionsValidationError => e
 | 
			
		||||
        rescue Paperclip::Errors::NotIdentifiedByImageMagickError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, Paperclip::Error, Mastodon::DimensionsValidationError, Mastodon::StreamValidationError => e
 | 
			
		||||
          Rails.logger.debug "Error fetching remote #{attachment_name}: #{e}"
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -336,6 +336,7 @@ class MediaAttachment < ApplicationRecord
 | 
			
		|||
 | 
			
		||||
    return unless movie.valid?
 | 
			
		||||
 | 
			
		||||
    raise Mastodon::StreamValidationError, 'Video has no video stream' if movie.width.nil? || movie.frame_rate.nil?
 | 
			
		||||
    raise Mastodon::DimensionsValidationError, "#{movie.width}x#{movie.height} videos are not supported" if movie.width * movie.height > MAX_VIDEO_MATRIX_LIMIT
 | 
			
		||||
    raise Mastodon::DimensionsValidationError, "#{movie.frame_rate.to_i}fps videos are not supported" if movie.frame_rate > MAX_VIDEO_FRAME_RATE
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,7 @@ class REST::MediaAttachmentSerializer < ActiveModel::Serializer
 | 
			
		|||
  include RoutingHelper
 | 
			
		||||
 | 
			
		||||
  attributes :id, :type, :url, :preview_url,
 | 
			
		||||
             :remote_url, :text_url, :meta,
 | 
			
		||||
             :remote_url, :preview_remote_url, :text_url, :meta,
 | 
			
		||||
             :description, :blurhash
 | 
			
		||||
 | 
			
		||||
  def id
 | 
			
		||||
| 
						 | 
				
			
			@ -35,6 +35,10 @@ class REST::MediaAttachmentSerializer < ActiveModel::Serializer
 | 
			
		|||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def preview_remote_url
 | 
			
		||||
    object.thumbnail_remote_url.presence
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def text_url
 | 
			
		||||
    object.local? ? medium_url(object) : nil
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,7 +12,7 @@ class UpdateAccountService < BaseService
 | 
			
		|||
      check_links(account)
 | 
			
		||||
      process_hashtags(account)
 | 
			
		||||
    end
 | 
			
		||||
  rescue Mastodon::DimensionsValidationError => de
 | 
			
		||||
  rescue Mastodon::DimensionsValidationError, Mastodon::StreamValidationError => de
 | 
			
		||||
    account.errors.add(:avatar, de.message)
 | 
			
		||||
    false
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
class ActivityPub::ProcessingWorker
 | 
			
		||||
  include Sidekiq::Worker
 | 
			
		||||
 | 
			
		||||
  sidekiq_options backtrace: true
 | 
			
		||||
  sidekiq_options backtrace: true, retry: 8
 | 
			
		||||
 | 
			
		||||
  def perform(account_id, body, delivered_to_account_id = nil)
 | 
			
		||||
    ActivityPub::ProcessCollectionService.new.call(body, Account.find(account_id), override_timestamps: true, delivered_to_account_id: delivered_to_account_id, delivery: true)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,6 +16,12 @@ ingress:
 | 
			
		|||
    kubernetes.io/ingress.class: nginx
 | 
			
		||||
    kubernetes.io/tls-acme: "true"
 | 
			
		||||
    # cert-manager.io/cluster-issuer: "letsencrypt"
 | 
			
		||||
    #
 | 
			
		||||
    # ensure that NGINX's upload size matches Mastodon's
 | 
			
		||||
    #   for the K8s ingress controller:
 | 
			
		||||
    # nginx.ingress.kubernetes.io/proxy-body-size: 40m
 | 
			
		||||
    #   for the NGINX ingress controller:
 | 
			
		||||
    # nginx.org/client-max-body-size: 40m
 | 
			
		||||
  # this value is used for LOCAL_DOMAIN
 | 
			
		||||
  hostname: mastodon.local
 | 
			
		||||
  tls:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,7 +18,7 @@ module Paperclip
 | 
			
		|||
      @type_from_mime_magic ||= begin
 | 
			
		||||
        begin
 | 
			
		||||
          File.open(@file.path) do |file|
 | 
			
		||||
            MimeMagic.by_magic(file)&.type
 | 
			
		||||
            MimeMagic.by_magic(file)&.type || ''
 | 
			
		||||
          end
 | 
			
		||||
        rescue Errno::ENOENT
 | 
			
		||||
          ''
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -110,7 +110,7 @@
 | 
			
		|||
    "intl-relativeformat": "^6.4.3",
 | 
			
		||||
    "is-nan": "^1.3.0",
 | 
			
		||||
    "js-yaml": "^3.13.1",
 | 
			
		||||
    "lodash": "^4.17.14",
 | 
			
		||||
    "lodash": "^4.17.19",
 | 
			
		||||
    "mark-loader": "^0.1.6",
 | 
			
		||||
    "marky": "^1.2.1",
 | 
			
		||||
    "mini-css-extract-plugin": "^0.9.0",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,21 @@ RSpec.describe AccountsController, type: :controller do
 | 
			
		|||
 | 
			
		||||
  let(:account) { Fabricate(:user).account }
 | 
			
		||||
 | 
			
		||||
  shared_examples 'cachable response' do
 | 
			
		||||
    it 'does not set cookies' do
 | 
			
		||||
      expect(response.cookies).to be_empty
 | 
			
		||||
      expect(response.headers['Set-Cookies']).to be nil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'does not set sessions' do
 | 
			
		||||
      expect(session).to be_empty
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns public Cache-Control header' do
 | 
			
		||||
      expect(response.headers['Cache-Control']).to include 'public'
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'GET #show' do
 | 
			
		||||
    let(:format) { 'html' }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -323,9 +338,7 @@ RSpec.describe AccountsController, type: :controller do
 | 
			
		|||
          expect(response.content_type).to eq 'application/activity+json'
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        it 'returns public Cache-Control header' do
 | 
			
		||||
          expect(response.headers['Cache-Control']).to include 'public'
 | 
			
		||||
        end
 | 
			
		||||
        it_behaves_like 'cachable response'
 | 
			
		||||
 | 
			
		||||
        it 'renders account' do
 | 
			
		||||
          json = body_as_json
 | 
			
		||||
| 
						 | 
				
			
			@ -343,9 +356,7 @@ RSpec.describe AccountsController, type: :controller do
 | 
			
		|||
            expect(response.content_type).to eq 'application/activity+json'
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          it 'returns public Cache-Control header' do
 | 
			
		||||
            expect(response.headers['Cache-Control']).to include 'public'
 | 
			
		||||
          end
 | 
			
		||||
          it_behaves_like 'cachable response'
 | 
			
		||||
 | 
			
		||||
          it 'returns Vary header with Signature' do
 | 
			
		||||
            expect(response.headers['Vary']).to include 'Signature'
 | 
			
		||||
| 
						 | 
				
			
			@ -401,9 +412,7 @@ RSpec.describe AccountsController, type: :controller do
 | 
			
		|||
          expect(response.content_type).to eq 'application/activity+json'
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        it 'returns public Cache-Control header' do
 | 
			
		||||
          expect(response.headers['Cache-Control']).to include 'public'
 | 
			
		||||
        end
 | 
			
		||||
        it_behaves_like 'cachable response'
 | 
			
		||||
 | 
			
		||||
        it 'renders account' do
 | 
			
		||||
          json = body_as_json
 | 
			
		||||
| 
						 | 
				
			
			@ -447,9 +456,7 @@ RSpec.describe AccountsController, type: :controller do
 | 
			
		|||
          expect(response).to have_http_status(200)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        it 'returns public Cache-Control header' do
 | 
			
		||||
          expect(response.headers['Cache-Control']).to include 'public'
 | 
			
		||||
        end
 | 
			
		||||
        it_behaves_like 'cachable response'
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      context do
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,21 @@ RSpec.describe ActivityPub::CollectionsController, type: :controller do
 | 
			
		|||
  let!(:account) { Fabricate(:account) }
 | 
			
		||||
  let(:remote_account) { nil }
 | 
			
		||||
 | 
			
		||||
  shared_examples 'cachable response' do
 | 
			
		||||
    it 'does not set cookies' do
 | 
			
		||||
      expect(response.cookies).to be_empty
 | 
			
		||||
      expect(response.headers['Set-Cookies']).to be nil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'does not set sessions' do
 | 
			
		||||
      expect(session).to be_empty
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns public Cache-Control header' do
 | 
			
		||||
      expect(response.headers['Cache-Control']).to include 'public'
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  before do
 | 
			
		||||
    allow(controller).to receive(:signed_request_account).and_return(remote_account)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -31,9 +46,7 @@ RSpec.describe ActivityPub::CollectionsController, type: :controller do
 | 
			
		|||
          expect(response.content_type).to eq 'application/activity+json'
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        it 'returns public Cache-Control header' do
 | 
			
		||||
          expect(response.headers['Cache-Control']).to include 'public'
 | 
			
		||||
        end
 | 
			
		||||
        it_behaves_like 'cachable response'
 | 
			
		||||
 | 
			
		||||
        it 'returns orderedItems with pinned statuses' do
 | 
			
		||||
          json = body_as_json
 | 
			
		||||
| 
						 | 
				
			
			@ -58,9 +71,7 @@ RSpec.describe ActivityPub::CollectionsController, type: :controller do
 | 
			
		|||
            expect(response.content_type).to eq 'application/activity+json'
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          it 'returns public Cache-Control header' do
 | 
			
		||||
            expect(response.headers['Cache-Control']).to include 'public'
 | 
			
		||||
          end
 | 
			
		||||
          it_behaves_like 'cachable response'
 | 
			
		||||
 | 
			
		||||
          it 'returns orderedItems with pinned statuses' do
 | 
			
		||||
            json = body_as_json
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,21 @@ require 'rails_helper'
 | 
			
		|||
RSpec.describe ActivityPub::OutboxesController, type: :controller do
 | 
			
		||||
  let!(:account) { Fabricate(:account) }
 | 
			
		||||
 | 
			
		||||
  shared_examples 'cachable response' do
 | 
			
		||||
    it 'does not set cookies' do
 | 
			
		||||
      expect(response.cookies).to be_empty
 | 
			
		||||
      expect(response.headers['Set-Cookies']).to be nil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'does not set sessions' do
 | 
			
		||||
      expect(session).to be_empty
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns public Cache-Control header' do
 | 
			
		||||
      expect(response.headers['Cache-Control']).to include 'public'
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  before do
 | 
			
		||||
    Fabricate(:status, account: account, visibility: :public)
 | 
			
		||||
    Fabricate(:status, account: account, visibility: :unlisted)
 | 
			
		||||
| 
						 | 
				
			
			@ -39,9 +54,7 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do
 | 
			
		|||
          expect(json[:totalItems]).to eq 4
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        it 'returns public Cache-Control header' do
 | 
			
		||||
          expect(response.headers['Cache-Control']).to include 'public'
 | 
			
		||||
        end
 | 
			
		||||
        it_behaves_like 'cachable response'
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      context 'with page requested' do
 | 
			
		||||
| 
						 | 
				
			
			@ -62,9 +75,7 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do
 | 
			
		|||
          expect(json[:orderedItems].all? { |item| item[:to].include?(ActivityPub::TagManager::COLLECTIONS[:public]) || item[:cc].include?(ActivityPub::TagManager::COLLECTIONS[:public]) }).to be true
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        it 'returns public Cache-Control header' do
 | 
			
		||||
          expect(response.headers['Cache-Control']).to include 'public'
 | 
			
		||||
        end
 | 
			
		||||
        it_behaves_like 'cachable response'
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,21 @@ RSpec.describe ActivityPub::RepliesController, type: :controller do
 | 
			
		|||
  let(:remote_reply_id) { nil }
 | 
			
		||||
  let(:remote_account) { nil }
 | 
			
		||||
 | 
			
		||||
  shared_examples 'cachable response' do
 | 
			
		||||
    it 'does not set cookies' do
 | 
			
		||||
      expect(response.cookies).to be_empty
 | 
			
		||||
      expect(response.headers['Set-Cookies']).to be nil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'does not set sessions' do
 | 
			
		||||
      expect(session).to be_empty
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns public Cache-Control header' do
 | 
			
		||||
      expect(response.headers['Cache-Control']).to include 'public'
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  before do
 | 
			
		||||
    allow(controller).to receive(:signed_request_account).and_return(remote_account)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -36,9 +51,7 @@ RSpec.describe ActivityPub::RepliesController, type: :controller do
 | 
			
		|||
          expect(response.content_type).to eq 'application/activity+json'
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        it 'returns public Cache-Control header' do
 | 
			
		||||
          expect(response.headers['Cache-Control']).to include 'public'
 | 
			
		||||
        end
 | 
			
		||||
        it_behaves_like 'cachable response'
 | 
			
		||||
 | 
			
		||||
        it 'returns items with account\'s own replies' do
 | 
			
		||||
          json = body_as_json
 | 
			
		||||
| 
						 | 
				
			
			@ -87,9 +100,7 @@ RSpec.describe ActivityPub::RepliesController, type: :controller do
 | 
			
		|||
            expect(response.content_type).to eq 'application/activity+json'
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          it 'returns public Cache-Control header' do
 | 
			
		||||
            expect(response.headers['Cache-Control']).to include 'public'
 | 
			
		||||
          end
 | 
			
		||||
          it_behaves_like 'cachable response'
 | 
			
		||||
 | 
			
		||||
          context 'without only_other_accounts' do
 | 
			
		||||
            it 'returns items with account\'s own replies' do
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,21 @@ require 'rails_helper'
 | 
			
		|||
describe StatusesController do
 | 
			
		||||
  render_views
 | 
			
		||||
 | 
			
		||||
  shared_examples 'cachable response' do
 | 
			
		||||
    it 'does not set cookies' do
 | 
			
		||||
      expect(response.cookies).to be_empty
 | 
			
		||||
      expect(response.headers['Set-Cookies']).to be nil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'does not set sessions' do
 | 
			
		||||
      expect(session).to be_empty
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns public Cache-Control header' do
 | 
			
		||||
      expect(response.headers['Cache-Control']).to include 'public'
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'GET #show' do
 | 
			
		||||
    let(:account) { Fabricate(:account) }
 | 
			
		||||
    let(:status)  { Fabricate(:status, account: account) }
 | 
			
		||||
| 
						 | 
				
			
			@ -80,9 +95,7 @@ describe StatusesController do
 | 
			
		|||
          expect(response.headers['Vary']).to eq 'Accept'
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        it 'returns public Cache-Control header' do
 | 
			
		||||
          expect(response.headers['Cache-Control']).to include 'public'
 | 
			
		||||
        end
 | 
			
		||||
        it_behaves_like 'cachable response'
 | 
			
		||||
 | 
			
		||||
        it 'returns Content-Type header' do
 | 
			
		||||
          expect(response.headers['Content-Type']).to include 'application/activity+json'
 | 
			
		||||
| 
						 | 
				
			
			@ -470,9 +483,7 @@ describe StatusesController do
 | 
			
		|||
            expect(response.headers['Vary']).to eq 'Accept'
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          it 'returns public Cache-Control header' do
 | 
			
		||||
            expect(response.headers['Cache-Control']).to include 'public'
 | 
			
		||||
          end
 | 
			
		||||
          it_behaves_like 'cachable response'
 | 
			
		||||
 | 
			
		||||
          it 'returns Content-Type header' do
 | 
			
		||||
            expect(response.headers['Content-Type']).to include 'application/activity+json'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,6 +28,28 @@ RSpec.describe ActivityPub::Activity::Block do
 | 
			
		|||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  context 'when the recipient is already blocked' do
 | 
			
		||||
    before do
 | 
			
		||||
      sender.block!(recipient, uri: 'old')
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    describe '#perform' do
 | 
			
		||||
      subject { described_class.new(json, sender) }
 | 
			
		||||
 | 
			
		||||
      before do
 | 
			
		||||
        subject.perform
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'creates a block from sender to recipient' do
 | 
			
		||||
        expect(sender.blocking?(recipient)).to be true
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'sets the uri to that of last received block activity' do
 | 
			
		||||
        expect(sender.block_relationships.find_by(target_account: recipient).uri).to eq 'foo'
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  context 'when the recipient follows the sender' do
 | 
			
		||||
    before do
 | 
			
		||||
      recipient.follow!(sender)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,6 +50,19 @@ RSpec.describe ActivityPub::Activity::Undo do
 | 
			
		|||
          expect(sender.reblogged?(status)).to be false
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      context 'with only object uri' do
 | 
			
		||||
        let(:object_json) { 'bar' }
 | 
			
		||||
 | 
			
		||||
        before do
 | 
			
		||||
          Fabricate(:status, reblog: status, account: sender, uri: 'bar')
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        it 'deletes the reblog by uri' do
 | 
			
		||||
          subject.perform
 | 
			
		||||
          expect(sender.reblogged?(status)).to be false
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'with Accept' do
 | 
			
		||||
| 
						 | 
				
			
			@ -91,13 +104,22 @@ RSpec.describe ActivityPub::Activity::Undo do
 | 
			
		|||
      end
 | 
			
		||||
 | 
			
		||||
      before do
 | 
			
		||||
        sender.block!(recipient)
 | 
			
		||||
        sender.block!(recipient, uri: 'bar')
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'deletes block from sender to recipient' do
 | 
			
		||||
        subject.perform
 | 
			
		||||
        expect(sender.blocking?(recipient)).to be false
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      context 'with only object uri' do
 | 
			
		||||
        let(:object_json) { 'bar' }
 | 
			
		||||
 | 
			
		||||
        it 'deletes block from sender to recipient' do
 | 
			
		||||
          subject.perform
 | 
			
		||||
          expect(sender.blocking?(recipient)).to be false
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'with Follow' do
 | 
			
		||||
| 
						 | 
				
			
			@ -113,13 +135,22 @@ RSpec.describe ActivityPub::Activity::Undo do
 | 
			
		|||
      end
 | 
			
		||||
 | 
			
		||||
      before do
 | 
			
		||||
        sender.follow!(recipient)
 | 
			
		||||
        sender.follow!(recipient, uri: 'bar')
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'deletes follow from sender to recipient' do
 | 
			
		||||
        subject.perform
 | 
			
		||||
        expect(sender.following?(recipient)).to be false
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      context 'with only object uri' do
 | 
			
		||||
        let(:object_json) { 'bar' }
 | 
			
		||||
 | 
			
		||||
        it 'deletes follow from sender to recipient' do
 | 
			
		||||
          subject.perform
 | 
			
		||||
          expect(sender.following?(recipient)).to be false
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'with Like' do
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -531,4 +531,29 @@ RSpec.describe FeedManager do
 | 
			
		|||
      expect(Redis.current).to have_received(:publish).with("timeline:#{receiver.id}", deletion)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe '#clear_from_timeline' do
 | 
			
		||||
    let(:account)          { Fabricate(:account) }
 | 
			
		||||
    let(:followed_account) { Fabricate(:account) }
 | 
			
		||||
    let(:target_account)   { Fabricate(:account) }
 | 
			
		||||
    let(:status_1)         { Fabricate(:status, account: followed_account) }
 | 
			
		||||
    let(:status_2)         { Fabricate(:status, account: target_account) }
 | 
			
		||||
    let(:status_3)         { Fabricate(:status, account: followed_account, mentions: [Fabricate(:mention, account: target_account)]) }
 | 
			
		||||
    let(:status_4)         { Fabricate(:status, mentions: [Fabricate(:mention, account: target_account)]) }
 | 
			
		||||
    let(:status_5)         { Fabricate(:status, account: followed_account, reblog: status_4) }
 | 
			
		||||
    let(:status_6)         { Fabricate(:status, account: followed_account, reblog: status_2) }
 | 
			
		||||
    let(:status_7)         { Fabricate(:status, account: followed_account) }
 | 
			
		||||
 | 
			
		||||
    before do
 | 
			
		||||
      [status_1, status_3, status_5, status_6, status_7].each do |status|
 | 
			
		||||
        Redis.current.zadd("feed:home:#{account.id}", status.id, status.id)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'correctly cleans the timeline' do
 | 
			
		||||
      FeedManager.instance.clear_from_timeline(account, target_account)
 | 
			
		||||
 | 
			
		||||
      expect(Redis.current.zrange("feed:home:#{account.id}", 0, -1)).to eq [status_1.id.to_s, status_7.id.to_s]
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6979,10 +6979,10 @@ lodash.uniq@^4.5.0:
 | 
			
		|||
  resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
 | 
			
		||||
  integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
 | 
			
		||||
 | 
			
		||||
lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.3.0, lodash@~4.17.12:
 | 
			
		||||
  version "4.17.15"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
 | 
			
		||||
  integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
 | 
			
		||||
lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.3.0, lodash@~4.17.12:
 | 
			
		||||
  version "4.17.19"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b"
 | 
			
		||||
  integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==
 | 
			
		||||
 | 
			
		||||
loglevel@^1.6.8:
 | 
			
		||||
  version "1.6.8"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue