Fix rubocop issues, introduce usage of frozen literal to improve performance
This commit is contained in:
		
							parent
							
								
									a91c3ef6ce
								
							
						
					
					
						commit
						fdc17bea58
					
				
					 96 changed files with 329 additions and 126 deletions
				
			
		
							
								
								
									
										36
									
								
								.rubocop.yml
									
										
									
									
									
								
							
							
						
						
									
										36
									
								
								.rubocop.yml
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -18,9 +18,29 @@ Metrics/MethodLength:
 | 
			
		|||
  CountComments: false
 | 
			
		||||
  Max: 10
 | 
			
		||||
 | 
			
		||||
Metrics/ModuleLength:
 | 
			
		||||
Metrics/AbcSize:
 | 
			
		||||
  Max: 100
 | 
			
		||||
 | 
			
		||||
Metrics/BlockNesting:
 | 
			
		||||
  Max: 3
 | 
			
		||||
 | 
			
		||||
Metrics/ClassLength:
 | 
			
		||||
  CountComments: false
 | 
			
		||||
  Max: 200
 | 
			
		||||
 | 
			
		||||
Metrics/CyclomaticComplexity:
 | 
			
		||||
  Max: 15
 | 
			
		||||
 | 
			
		||||
Metrics/MethodLength:
 | 
			
		||||
  Max: 55
 | 
			
		||||
 | 
			
		||||
Metrics/ModuleLength:
 | 
			
		||||
  CountComments: false
 | 
			
		||||
  Max: 200
 | 
			
		||||
 | 
			
		||||
Metrics/PerceivedComplexity:
 | 
			
		||||
  Max: 10
 | 
			
		||||
 | 
			
		||||
Metrics/ParameterLists:
 | 
			
		||||
  Max: 4
 | 
			
		||||
  CountKeywordArgs: true
 | 
			
		||||
| 
						 | 
				
			
			@ -37,10 +57,10 @@ Style/Documentation:
 | 
			
		|||
  Enabled: false
 | 
			
		||||
 | 
			
		||||
Style/DoubleNegation:
 | 
			
		||||
  Enabled: false
 | 
			
		||||
  Enabled: true
 | 
			
		||||
 | 
			
		||||
Style/FrozenStringLiteralComment:
 | 
			
		||||
  Enabled: false
 | 
			
		||||
  Enabled: true
 | 
			
		||||
 | 
			
		||||
Style/SpaceInsideHashLiteralBraces:
 | 
			
		||||
  EnforcedStyle: space
 | 
			
		||||
| 
						 | 
				
			
			@ -51,10 +71,18 @@ Style/TrailingCommaInLiteral:
 | 
			
		|||
Style/RegexpLiteral:
 | 
			
		||||
  Enabled: false
 | 
			
		||||
 | 
			
		||||
Style/Lambda:
 | 
			
		||||
  Enabled: false
 | 
			
		||||
 | 
			
		||||
Rails/HasAndBelongsToMany:
 | 
			
		||||
  Enabled: false
 | 
			
		||||
 | 
			
		||||
AllCops:
 | 
			
		||||
  TargetRubyVersion: 2.2
 | 
			
		||||
  TargetRubyVersion: 2.3
 | 
			
		||||
  Exclude:
 | 
			
		||||
  - 'spec/**/*'
 | 
			
		||||
  - 'db/**/*'
 | 
			
		||||
  - 'app/views/**/*'
 | 
			
		||||
  - 'config/**/*'
 | 
			
		||||
  - 'bin/*'
 | 
			
		||||
  - 'Rakefile'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								Gemfile
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								Gemfile
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
source 'https://rubygems.org'
 | 
			
		||||
 | 
			
		||||
gem 'rails', '5.0.0.1'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module ApplicationCable
 | 
			
		||||
  class Channel < ActionCable::Channel::Base
 | 
			
		||||
    protected
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module ApplicationCable
 | 
			
		||||
  class Connection < ActionCable::Connection::Base
 | 
			
		||||
    identified_by :current_user
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class HashtagChannel < ApplicationCable::Channel
 | 
			
		||||
  def subscribed
 | 
			
		||||
    tag = params[:tag].downcase
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class PublicChannel < ApplicationCable::Channel
 | 
			
		||||
  def subscribed
 | 
			
		||||
    stream_from 'timeline:public', lambda { |encoded_message|
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class TimelineChannel < ApplicationCable::Channel
 | 
			
		||||
  def subscribed
 | 
			
		||||
    stream_from "timeline:#{current_user.account_id}"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class AboutController < ApplicationController
 | 
			
		||||
  before_action :set_body_classes
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class AccountsController < ApplicationController
 | 
			
		||||
  layout 'public'
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -41,10 +43,7 @@ class AccountsController < ApplicationController
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def set_link_headers
 | 
			
		||||
    response.headers['Link'] = LinkHeader.new([
 | 
			
		||||
      [webfinger_account_url, [['rel', 'lrdd'], ['type', 'application/xrd+xml']]],
 | 
			
		||||
      [account_url(@account, format: 'atom'), [['rel', 'alternate'], ['type', 'application/atom+xml']]]
 | 
			
		||||
    ])
 | 
			
		||||
    response.headers['Link'] = LinkHeader.new([[webfinger_account_url, [%w(rel lrdd), %w(type application/xrd+xml)]], [account_url(@account, format: 'atom'), [%w(rel alternate), %w(type application/atom+xml)]]])
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def webfinger_account_url
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Api::SalmonController < ApiController
 | 
			
		||||
  before_action :set_account
 | 
			
		||||
  respond_to :txt
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Api::SubscriptionsController < ApiController
 | 
			
		||||
  before_action :set_account
 | 
			
		||||
  respond_to :txt
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Api::V1::AccountsController < ApiController
 | 
			
		||||
  before_action -> { doorkeeper_authorize! :read }, except: [:follow, :unfollow, :block, :unblock]
 | 
			
		||||
  before_action -> { doorkeeper_authorize! :follow }, only: [:follow, :unfollow, :block, :unblock]
 | 
			
		||||
| 
						 | 
				
			
			@ -20,7 +22,7 @@ class Api::V1::AccountsController < ApiController
 | 
			
		|||
    @accounts = results.map { |f| accounts[f.target_account_id] }
 | 
			
		||||
 | 
			
		||||
    next_path = following_api_v1_account_url(max_id: results.last.id)    if results.size == DEFAULT_ACCOUNTS_LIMIT
 | 
			
		||||
    prev_path = following_api_v1_account_url(since_id: results.first.id) if results.size > 0
 | 
			
		||||
    prev_path = following_api_v1_account_url(since_id: results.first.id) unless results.empty?
 | 
			
		||||
 | 
			
		||||
    set_pagination_headers(next_path, prev_path)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -33,7 +35,7 @@ class Api::V1::AccountsController < ApiController
 | 
			
		|||
    @accounts = results.map { |f| accounts[f.account_id] }
 | 
			
		||||
 | 
			
		||||
    next_path = followers_api_v1_account_url(max_id: results.last.id)    if results.size == DEFAULT_ACCOUNTS_LIMIT
 | 
			
		||||
    prev_path = followers_api_v1_account_url(since_id: results.first.id) if results.size > 0
 | 
			
		||||
    prev_path = followers_api_v1_account_url(since_id: results.first.id) unless results.empty?
 | 
			
		||||
 | 
			
		||||
    set_pagination_headers(next_path, prev_path)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -56,7 +58,7 @@ class Api::V1::AccountsController < ApiController
 | 
			
		|||
    set_maps(@statuses)
 | 
			
		||||
 | 
			
		||||
    next_path = statuses_api_v1_account_url(max_id: @statuses.last.id)    if @statuses.size == DEFAULT_STATUSES_LIMIT
 | 
			
		||||
    prev_path = statuses_api_v1_account_url(since_id: @statuses.first.id) if @statuses.size > 0
 | 
			
		||||
    prev_path = statuses_api_v1_account_url(since_id: @statuses.first.id) unless @statuses.empty?
 | 
			
		||||
 | 
			
		||||
    set_pagination_headers(next_path, prev_path)
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Api::V1::AppsController < ApiController
 | 
			
		||||
  respond_to :json
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Api::V1::FollowsController < ApiController
 | 
			
		||||
  before_action -> { doorkeeper_authorize! :follow }
 | 
			
		||||
  before_action :require_user!
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Api::V1::MediaController < ApiController
 | 
			
		||||
  before_action -> { doorkeeper_authorize! :write }
 | 
			
		||||
  before_action :require_user!
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Api::V1::StatusesController < ApiController
 | 
			
		||||
  before_action -> { doorkeeper_authorize! :read }, except: [:create, :destroy, :reblog, :unreblog, :favourite, :unfavourite]
 | 
			
		||||
  before_action -> { doorkeeper_authorize! :write }, only:  [:create, :destroy, :reblog, :unreblog, :favourite, :unfavourite]
 | 
			
		||||
| 
						 | 
				
			
			@ -10,7 +12,7 @@ class Api::V1::StatusesController < ApiController
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def context
 | 
			
		||||
    @context = OpenStruct.new({ ancestors: @status.ancestors, descendants: @status.descendants })
 | 
			
		||||
    @context = OpenStruct.new(ancestors: @status.ancestors, descendants: @status.descendants)
 | 
			
		||||
    set_maps([@status] + @context[:ancestors] + @context[:descendants])
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -20,7 +22,7 @@ class Api::V1::StatusesController < ApiController
 | 
			
		|||
    @accounts = results.map { |r| accounts[r.account_id] }
 | 
			
		||||
 | 
			
		||||
    next_path = reblogged_by_api_v1_status_url(max_id: results.last.id)    if results.size == DEFAULT_ACCOUNTS_LIMIT
 | 
			
		||||
    prev_path = reblogged_by_api_v1_status_url(since_id: results.first.id) if results.size > 0
 | 
			
		||||
    prev_path = reblogged_by_api_v1_status_url(since_id: results.first.id) unless results.empty?
 | 
			
		||||
 | 
			
		||||
    set_pagination_headers(next_path, prev_path)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -33,7 +35,7 @@ class Api::V1::StatusesController < ApiController
 | 
			
		|||
    @accounts = results.map { |f| accounts[f.account_id] }
 | 
			
		||||
 | 
			
		||||
    next_path = favourited_by_api_v1_status_url(max_id: results.last.id)    if results.size == DEFAULT_ACCOUNTS_LIMIT
 | 
			
		||||
    prev_path = favourited_by_api_v1_status_url(since_id: results.first.id) if results.size > 0
 | 
			
		||||
    prev_path = favourited_by_api_v1_status_url(since_id: results.first.id) unless results.empty?
 | 
			
		||||
 | 
			
		||||
    set_pagination_headers(next_path, prev_path)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Api::V1::TimelinesController < ApiController
 | 
			
		||||
  before_action -> { doorkeeper_authorize! :read }
 | 
			
		||||
  before_action :require_user!, only: [:home, :mentions]
 | 
			
		||||
| 
						 | 
				
			
			@ -10,7 +12,7 @@ class Api::V1::TimelinesController < ApiController
 | 
			
		|||
    set_maps(@statuses)
 | 
			
		||||
 | 
			
		||||
    next_path = api_v1_home_timeline_url(max_id: @statuses.last.id)    if @statuses.size == DEFAULT_STATUSES_LIMIT
 | 
			
		||||
    prev_path = api_v1_home_timeline_url(since_id: @statuses.first.id) if @statuses.size > 0
 | 
			
		||||
    prev_path = api_v1_home_timeline_url(since_id: @statuses.first.id) unless @statuses.empty?
 | 
			
		||||
 | 
			
		||||
    set_pagination_headers(next_path, prev_path)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -23,7 +25,7 @@ class Api::V1::TimelinesController < ApiController
 | 
			
		|||
    set_maps(@statuses)
 | 
			
		||||
 | 
			
		||||
    next_path = api_v1_mentions_timeline_url(max_id: @statuses.last.id)    if @statuses.size == DEFAULT_STATUSES_LIMIT
 | 
			
		||||
    prev_path = api_v1_mentions_timeline_url(since_id: @statuses.first.id) if @statuses.size > 0
 | 
			
		||||
    prev_path = api_v1_mentions_timeline_url(since_id: @statuses.first.id) unless @statuses.empty?
 | 
			
		||||
 | 
			
		||||
    set_pagination_headers(next_path, prev_path)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -36,7 +38,7 @@ class Api::V1::TimelinesController < ApiController
 | 
			
		|||
    set_maps(@statuses)
 | 
			
		||||
 | 
			
		||||
    next_path = api_v1_public_timeline_url(max_id: @statuses.last.id)    if @statuses.size == DEFAULT_STATUSES_LIMIT
 | 
			
		||||
    prev_path = api_v1_public_timeline_url(since_id: @statuses.first.id) if @statuses.size > 0
 | 
			
		||||
    prev_path = api_v1_public_timeline_url(since_id: @statuses.first.id) unless @statuses.empty?
 | 
			
		||||
 | 
			
		||||
    set_pagination_headers(next_path, prev_path)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -50,7 +52,7 @@ class Api::V1::TimelinesController < ApiController
 | 
			
		|||
    set_maps(@statuses)
 | 
			
		||||
 | 
			
		||||
    next_path = api_v1_hashtag_timeline_url(params[:id], max_id: @statuses.last.id)    if @statuses.size == DEFAULT_STATUSES_LIMIT
 | 
			
		||||
    prev_path = api_v1_hashtag_timeline_url(params[:id], since_id: @statuses.first.id) if @statuses.size > 0
 | 
			
		||||
    prev_path = api_v1_hashtag_timeline_url(params[:id], since_id: @statuses.first.id) unless @statuses.empty?
 | 
			
		||||
 | 
			
		||||
    set_pagination_headers(next_path, prev_path)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class ApiController < ApplicationController
 | 
			
		||||
  DEFAULT_STATUSES_LIMIT = 20
 | 
			
		||||
  DEFAULT_ACCOUNTS_LIMIT = 40
 | 
			
		||||
| 
						 | 
				
			
			@ -51,8 +53,8 @@ class ApiController < ApplicationController
 | 
			
		|||
 | 
			
		||||
  def set_pagination_headers(next_path = nil, prev_path = nil)
 | 
			
		||||
    links = []
 | 
			
		||||
    links << [next_path, [['rel', 'next']]] if next_path
 | 
			
		||||
    links << [prev_path, [['rel', 'prev']]] if prev_path
 | 
			
		||||
    links << [next_path, [%w(rel next)]] if next_path
 | 
			
		||||
    links << [prev_path, [%w(rel prev)]] if prev_path
 | 
			
		||||
    response.headers['Link'] = LinkHeader.new(links)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -76,7 +78,7 @@ class ApiController < ApplicationController
 | 
			
		|||
    render json: {}, status: 200
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def set_maps(statuses)
 | 
			
		||||
  def set_maps(statuses) # rubocop:disable Style/AccessorMethodName
 | 
			
		||||
    if current_account.nil?
 | 
			
		||||
      @reblogs_map    = {}
 | 
			
		||||
      @favourites_map = {}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class ApplicationController < ActionController::Base
 | 
			
		||||
  # Prevent CSRF attacks by raising an exception.
 | 
			
		||||
  # For APIs, you may want to use :null_session instead.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Auth::ConfirmationsController < Devise::ConfirmationsController
 | 
			
		||||
  layout 'auth'
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Auth::PasswordsController < Devise::PasswordsController
 | 
			
		||||
  layout 'auth'
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Auth::RegistrationsController < Devise::RegistrationsController
 | 
			
		||||
  layout 'auth'
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Auth::SessionsController < Devise::SessionsController
 | 
			
		||||
  include Devise::Controllers::Rememberable
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class HomeController < ApplicationController
 | 
			
		||||
  before_action :authenticate_user!
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class MediaController < ApplicationController
 | 
			
		||||
  before_action :set_media_attachment
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
 | 
			
		||||
  skip_before_action :authenticate_resource_owner!
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Settings::PreferencesController < ApplicationController
 | 
			
		||||
  layout 'auth'
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Settings::ProfilesController < ApplicationController
 | 
			
		||||
  layout 'auth'
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class StreamEntriesController < ApplicationController
 | 
			
		||||
  layout 'public'
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -29,9 +31,7 @@ class StreamEntriesController < ApplicationController
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def set_link_headers
 | 
			
		||||
    response.headers['Link'] = LinkHeader.new([
 | 
			
		||||
      [account_stream_entry_url(@account, @stream_entry, format: 'atom'), [['rel', 'alternate'], ['type', 'application/atom+xml']]]
 | 
			
		||||
    ])
 | 
			
		||||
    response.headers['Link'] = LinkHeader.new([[account_stream_entry_url(@account, @stream_entry, format: 'atom'), [%w(rel alternate), %w(type application/atom+xml)]]])
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def set_stream_entry
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class TagsController < ApplicationController
 | 
			
		||||
  layout 'public'
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class XrdController < ApplicationController
 | 
			
		||||
  before_action :set_default_format_json, only: :webfinger
 | 
			
		||||
  before_action :set_default_format_xml, only: :host_meta
 | 
			
		||||
| 
						 | 
				
			
			@ -26,11 +28,11 @@ class XrdController < ApplicationController
 | 
			
		|||
  private
 | 
			
		||||
 | 
			
		||||
  def set_default_format_xml
 | 
			
		||||
    request.format = 'xml' if request.headers["HTTP_ACCEPT"].nil? && params[:format].nil?
 | 
			
		||||
    request.format = 'xml' if request.headers['HTTP_ACCEPT'].nil? && params[:format].nil?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def set_default_format_json
 | 
			
		||||
    request.format = 'json' if request.headers["HTTP_ACCEPT"].nil? && params[:format].nil?
 | 
			
		||||
    request.format = 'json' if request.headers['HTTP_ACCEPT'].nil? && params[:format].nil?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def username_from_resource
 | 
			
		||||
| 
						 | 
				
			
			@ -44,14 +46,14 @@ class XrdController < ApplicationController
 | 
			
		|||
 | 
			
		||||
  def pem_to_magic_key(public_key)
 | 
			
		||||
    modulus, exponent = [public_key.n, public_key.e].map do |component|
 | 
			
		||||
      result = ''
 | 
			
		||||
      result = []
 | 
			
		||||
 | 
			
		||||
      until component.zero?
 | 
			
		||||
        result << [component % 256].pack('C')
 | 
			
		||||
        component >>= 8
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      result.reverse!
 | 
			
		||||
      result.reverse.join
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    (['RSA'] + [modulus, exponent].map { |n| Base64.urlsafe_encode64(n) }).join('.')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,2 +1,4 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module AboutHelper
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,10 +1,12 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module AccountsHelper
 | 
			
		||||
  def pagination_options
 | 
			
		||||
    {
 | 
			
		||||
      previous_label: "#{fa_icon('chevron-left')} Prev".html_safe,
 | 
			
		||||
      next_label: "Next #{fa_icon('chevron-right')}".html_safe,
 | 
			
		||||
      previous_label: safe_join([fa_icon('chevron-left'), 'Prev'], ' '),
 | 
			
		||||
      next_label: safe_join(['Next', fa_icon('chevron-right')], ' '),
 | 
			
		||||
      inner_window: 1,
 | 
			
		||||
      outer_window: 0
 | 
			
		||||
      outer_window: 0,
 | 
			
		||||
    }
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module ApplicationHelper
 | 
			
		||||
  def active_nav_class(path)
 | 
			
		||||
    current_page?(path) ? 'active' : ''
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,12 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module AtomBuilderHelper
 | 
			
		||||
  def stream_updated_at
 | 
			
		||||
    @account.stream_entries.last ? (@account.updated_at > @account.stream_entries.last.created_at ? @account.updated_at : @account.stream_entries.last.created_at) : @account.updated_at
 | 
			
		||||
    if @account.stream_entries.last
 | 
			
		||||
      (@account.updated_at > @account.stream_entries.last.created_at ? @account.updated_at : @account.stream_entries.last.created_at)
 | 
			
		||||
    else
 | 
			
		||||
      @account.updated_at
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def entry(xml, is_root = false, &block)
 | 
			
		||||
| 
						 | 
				
			
			@ -98,7 +104,7 @@ module AtomBuilderHelper
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def in_reply_to(xml, uri, url)
 | 
			
		||||
    xml['thr'].send('in-reply-to', { ref: uri, href: url, type: 'text/html' })
 | 
			
		||||
    xml['thr'].send('in-reply-to', ref: uri, href: url, type: 'text/html')
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def link_mention(xml, account)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,10 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module HomeHelper
 | 
			
		||||
  def default_props
 | 
			
		||||
    {
 | 
			
		||||
      token: @token,
 | 
			
		||||
      account: render(file: 'api/v1/accounts/show', locals: { account: current_user.account }, formats: :json)
 | 
			
		||||
      account: render(file: 'api/v1/accounts/show', locals: { account: current_user.account }, formats: :json),
 | 
			
		||||
    }
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module RoutingHelper
 | 
			
		||||
  extend ActiveSupport::Concern
 | 
			
		||||
  include Rails.application.routes.url_helpers
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module StreamEntriesHelper
 | 
			
		||||
  def display_name(account)
 | 
			
		||||
    account.display_name.blank? ? account.username : account.display_name
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,2 +1,4 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module TagsHelper
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,2 +1,4 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module XrdHelper
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require 'singleton'
 | 
			
		||||
 | 
			
		||||
class FeedManager
 | 
			
		||||
| 
						 | 
				
			
			@ -60,7 +62,7 @@ class FeedManager
 | 
			
		|||
  private
 | 
			
		||||
 | 
			
		||||
  def redis
 | 
			
		||||
    $redis
 | 
			
		||||
    Redis.current
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def filter_from_home?(status, receiver)
 | 
			
		||||
| 
						 | 
				
			
			@ -68,8 +70,8 @@ class FeedManager
 | 
			
		|||
 | 
			
		||||
    if status.reply? && !status.thread.account.nil?                      # Filter out if it's a reply
 | 
			
		||||
      should_filter   = !receiver.following?(status.thread.account)      # and I'm not following the person it's a reply to
 | 
			
		||||
      should_filter = should_filter && !(receiver.id == status.thread.account_id)       # and it's not a reply to me
 | 
			
		||||
      should_filter = should_filter && !(status.account_id == status.thread.account_id) # and it's not a self-reply
 | 
			
		||||
      should_filter &&= !(receiver.id == status.thread.account_id)       # and it's not a reply to me
 | 
			
		||||
      should_filter &&= !(status.account_id == status.thread.account_id) # and it's not a self-reply
 | 
			
		||||
    elsif status.reblog?                                                 # Filter out a reblog
 | 
			
		||||
      should_filter = receiver.blocking?(status.reblog.account)          # if I'm blocking the reblogged person
 | 
			
		||||
    end
 | 
			
		||||
| 
						 | 
				
			
			@ -79,10 +81,10 @@ class FeedManager
 | 
			
		|||
 | 
			
		||||
  def filter_from_mentions?(status, receiver)
 | 
			
		||||
    should_filter   = receiver.id == status.account_id            # Filter if I'm mentioning myself
 | 
			
		||||
    should_filter = should_filter || receiver.blocking?(status.account)          # or it's from someone I blocked
 | 
			
		||||
    should_filter ||= receiver.blocking?(status.account)          # or it's from someone I blocked
 | 
			
		||||
 | 
			
		||||
    if status.reply? && !status.thread.account.nil?               # or it's a reply
 | 
			
		||||
      should_filter = should_filter || receiver.blocking?(status.thread.account) # to a user I blocked
 | 
			
		||||
      should_filter ||= receiver.blocking?(status.thread.account) # to a user I blocked
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    should_filter
 | 
			
		||||
| 
						 | 
				
			
			@ -92,9 +94,9 @@ class FeedManager
 | 
			
		|||
    should_filter = receiver.blocking?(status.account)
 | 
			
		||||
 | 
			
		||||
    if status.reply? && !status.thread.account.nil?
 | 
			
		||||
      should_filter = should_filter || receiver.blocking?(status.thread.account)
 | 
			
		||||
      should_filter ||= receiver.blocking?(status.thread.account)
 | 
			
		||||
    elsif status.reblog?
 | 
			
		||||
      should_filter = should_filter || receiver.blocking?(status.reblog.account)
 | 
			
		||||
      should_filter ||= receiver.blocking?(status.reblog.account)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    should_filter
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require 'singleton'
 | 
			
		||||
 | 
			
		||||
class Formatter
 | 
			
		||||
| 
						 | 
				
			
			@ -17,7 +19,7 @@ class Formatter
 | 
			
		|||
    html = link_mentions(html, status.mentions)
 | 
			
		||||
    html = link_hashtags(html)
 | 
			
		||||
 | 
			
		||||
    html.html_safe
 | 
			
		||||
    html.html_safe # rubocop:disable Rails/OutputSafety
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def reformat(html)
 | 
			
		||||
| 
						 | 
				
			
			@ -30,7 +32,7 @@ class Formatter
 | 
			
		|||
    html = encode(account.note)
 | 
			
		||||
    html = link_urls(html)
 | 
			
		||||
 | 
			
		||||
    html.html_safe
 | 
			
		||||
    html.html_safe # rubocop:disable Rails/OutputSafety
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require 'singleton'
 | 
			
		||||
 | 
			
		||||
class TagManager
 | 
			
		||||
| 
						 | 
				
			
			@ -18,7 +20,7 @@ class TagManager
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def local_domain?(domain)
 | 
			
		||||
    domain.nil? || domain.gsub(/[\/]/, '').downcase == Rails.configuration.x.local_domain.downcase
 | 
			
		||||
    domain.nil? || domain.gsub(/[\/]/, '').casecmp(Rails.configuration.x.local_domain).zero?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def uri_for(target)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class ApplicationMailer < ActionMailer::Base
 | 
			
		||||
  default from: (ENV['SMTP_FROM_ADDRESS'] || 'notifications@localhost')
 | 
			
		||||
  layout 'mailer'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class NotificationMailer < ApplicationMailer
 | 
			
		||||
  helper StreamEntriesHelper
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Account < ApplicationRecord
 | 
			
		||||
  include Targetable
 | 
			
		||||
  include PgSearch
 | 
			
		||||
| 
						 | 
				
			
			@ -92,11 +94,11 @@ class Account < ApplicationRecord
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def favourited?(status)
 | 
			
		||||
    (status.reblog? ? status.reblog : status).favourites.where(account: self).count > 0
 | 
			
		||||
    (status.reblog? ? status.reblog : status).favourites.where(account: self).count.positive?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def reblogged?(status)
 | 
			
		||||
    (status.reblog? ? status.reblog : status).reblogs.where(account: self).count > 0
 | 
			
		||||
    (status.reblog? ? status.reblog : status).reblogs.where(account: self).count.positive?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def keypair
 | 
			
		||||
| 
						 | 
				
			
			@ -115,8 +117,8 @@ class Account < ApplicationRecord
 | 
			
		|||
  def avatar_remote_url=(url)
 | 
			
		||||
    self.avatar = URI.parse(url) unless self[:avatar_remote_url] == url
 | 
			
		||||
    self[:avatar_remote_url] = url
 | 
			
		||||
  rescue OpenURI::HTTPError
 | 
			
		||||
    #
 | 
			
		||||
  rescue OpenURI::HTTPError => e
 | 
			
		||||
    Rails.logger.debug "Error fetching remote avatar: #{e}"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def object_type
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class ApplicationRecord < ActiveRecord::Base
 | 
			
		||||
  self.abstract_class = true
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Block < ApplicationRecord
 | 
			
		||||
  belongs_to :account
 | 
			
		||||
  belongs_to :target_account, class_name: 'Account'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module Paginable
 | 
			
		||||
  extend ActiveSupport::Concern
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module Streamable
 | 
			
		||||
  extend ActiveSupport::Concern
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module Targetable
 | 
			
		||||
  extend ActiveSupport::Concern
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class DomainBlock < ApplicationRecord
 | 
			
		||||
  validates :domain, presence: true, uniqueness: true
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Favourite < ApplicationRecord
 | 
			
		||||
  include Paginable
 | 
			
		||||
  include Streamable
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Feed
 | 
			
		||||
  def initialize(type, account)
 | 
			
		||||
    @type    = type
 | 
			
		||||
| 
						 | 
				
			
			@ -28,6 +30,6 @@ class Feed
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def redis
 | 
			
		||||
    $redis
 | 
			
		||||
    Redis.current
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Follow < ApplicationRecord
 | 
			
		||||
  include Paginable
 | 
			
		||||
  include Streamable
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class FollowSuggestion
 | 
			
		||||
  class << self
 | 
			
		||||
    def get(for_account_id, limit = 10)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class MediaAttachment < ApplicationRecord
 | 
			
		||||
  IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif'].freeze
 | 
			
		||||
  VIDEO_MIME_TYPES = ['video/webm', 'video/mp4'].freeze
 | 
			
		||||
| 
						 | 
				
			
			@ -8,7 +10,7 @@ class MediaAttachment < ApplicationRecord
 | 
			
		|||
  has_attached_file :file,
 | 
			
		||||
                    styles: -> (f) { file_styles f },
 | 
			
		||||
                    processors: -> (f) { f.video? ? [:transcoder] : [:thumbnail] },
 | 
			
		||||
    convert_options: { all: "-strip" }
 | 
			
		||||
                    convert_options: { all: '-strip' }
 | 
			
		||||
  validates_attachment_content_type :file, content_type: IMAGE_MIME_TYPES + VIDEO_MIME_TYPES
 | 
			
		||||
  validates_attachment_size :file, less_than: 4.megabytes
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -20,8 +22,8 @@ class MediaAttachment < ApplicationRecord
 | 
			
		|||
 | 
			
		||||
  def file_remote_url=(url)
 | 
			
		||||
    self.file = URI.parse(url)
 | 
			
		||||
  rescue OpenURI::HTTPError
 | 
			
		||||
    #
 | 
			
		||||
  rescue OpenURI::HTTPError => e
 | 
			
		||||
    Rails.logger.debug "Error fetching remote attachment: #{e}"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def image?
 | 
			
		||||
| 
						 | 
				
			
			@ -43,19 +45,19 @@ class MediaAttachment < ApplicationRecord
 | 
			
		|||
      if f.instance.image?
 | 
			
		||||
        {
 | 
			
		||||
          original: '100%',
 | 
			
		||||
          small: '510x680>'
 | 
			
		||||
          small: '510x680>',
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          small: {
 | 
			
		||||
            convert_options: {
 | 
			
		||||
              output: {
 | 
			
		||||
                vf: 'scale=\'min(510\, iw):min(680\, ih)\':force_original_aspect_ratio=decrease'
 | 
			
		||||
              }
 | 
			
		||||
                vf: 'scale=\'min(510\, iw):min(680\, ih)\':force_original_aspect_ratio=decrease',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            format: 'png',
 | 
			
		||||
            time: 1
 | 
			
		||||
          }
 | 
			
		||||
            time: 1,
 | 
			
		||||
          },
 | 
			
		||||
        }
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Mention < ApplicationRecord
 | 
			
		||||
  belongs_to :account, inverse_of: :mentions
 | 
			
		||||
  belongs_to :status
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Status < ApplicationRecord
 | 
			
		||||
  include Paginable
 | 
			
		||||
  include Streamable
 | 
			
		||||
| 
						 | 
				
			
			@ -89,10 +91,7 @@ class Status < ApplicationRecord
 | 
			
		|||
 | 
			
		||||
    def as_public_timeline(account = nil)
 | 
			
		||||
      query = joins('LEFT OUTER JOIN accounts ON statuses.account_id = accounts.id').where('accounts.silenced = FALSE')
 | 
			
		||||
 | 
			
		||||
      unless account.nil?
 | 
			
		||||
        query = filter_timeline(query, account)
 | 
			
		||||
      end
 | 
			
		||||
      query = filter_timeline(query, account) unless account.nil?
 | 
			
		||||
 | 
			
		||||
      query.with_includes.with_counters
 | 
			
		||||
    end
 | 
			
		||||
| 
						 | 
				
			
			@ -102,9 +101,7 @@ class Status < ApplicationRecord
 | 
			
		|||
                 .joins('LEFT OUTER JOIN accounts ON statuses.account_id = accounts.id')
 | 
			
		||||
                 .where('accounts.silenced = FALSE')
 | 
			
		||||
 | 
			
		||||
      unless account.nil?
 | 
			
		||||
        query = filter_timeline(query, account)
 | 
			
		||||
      end
 | 
			
		||||
      query = filter_timeline(query, account) unless account.nil?
 | 
			
		||||
 | 
			
		||||
      query.with_includes.with_counters
 | 
			
		||||
    end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class StreamEntry < ApplicationRecord
 | 
			
		||||
  include Paginable
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -15,7 +17,11 @@ class StreamEntry < ApplicationRecord
 | 
			
		|||
  scope :with_includes, -> { includes(:account, status: STATUS_INCLUDES, favourite: [:account, :stream_entry, status: STATUS_INCLUDES], follow: [:target_account, :stream_entry]) }
 | 
			
		||||
 | 
			
		||||
  def object_type
 | 
			
		||||
    orphaned? ? :activity : (targeted? ? :activity : activity.object_type)
 | 
			
		||||
    if orphaned?
 | 
			
		||||
      :activity
 | 
			
		||||
    else
 | 
			
		||||
      targeted? ? :activity : activity.object_type
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def verb
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Tag < ApplicationRecord
 | 
			
		||||
  has_and_belongs_to_many :statuses
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class User < ApplicationRecord
 | 
			
		||||
  devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class BaseService
 | 
			
		||||
  include ActionView::Helpers::TextHelper
 | 
			
		||||
  include ActionView::Helpers::SanitizeHelper
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class BlockDomainService < BaseService
 | 
			
		||||
  def call(domain)
 | 
			
		||||
    DomainBlock.find_or_create_by!(domain: domain)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class BlockService < BaseService
 | 
			
		||||
  def call(account, target_account)
 | 
			
		||||
    return if account.id == target_account.id
 | 
			
		||||
| 
						 | 
				
			
			@ -20,6 +22,6 @@ class BlockService < BaseService
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def redis
 | 
			
		||||
    $redis
 | 
			
		||||
    Redis.current
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class FanOutOnWriteService < BaseService
 | 
			
		||||
  # Push a status into home and mentions feeds
 | 
			
		||||
  # @param [Status] status
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class FavouriteService < BaseService
 | 
			
		||||
  # Favourite a status and notify remote user
 | 
			
		||||
  # @param [Account] account
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class FetchAtomService < BaseService
 | 
			
		||||
  def call(url)
 | 
			
		||||
    response = http_client.head(url)
 | 
			
		||||
| 
						 | 
				
			
			@ -9,15 +11,9 @@ class FetchAtomService < BaseService
 | 
			
		|||
    Rails.logger.debug "Remote status GET request returned code #{response.code}"
 | 
			
		||||
 | 
			
		||||
    return nil if response.code != 200
 | 
			
		||||
 | 
			
		||||
    if response.mime_type == 'application/atom+xml'
 | 
			
		||||
      return [url, fetch(url)]
 | 
			
		||||
    elsif !response['Link'].blank?
 | 
			
		||||
      return process_headers(url, response)
 | 
			
		||||
    else
 | 
			
		||||
      return process_html(fetch(url))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    return [url, fetch(url)] if response.mime_type == 'application/atom+xml'
 | 
			
		||||
    return process_headers(url, response) unless response['Link'].blank?
 | 
			
		||||
    process_html(fetch(url))
 | 
			
		||||
  rescue OpenSSL::SSL::SSLError => e
 | 
			
		||||
    Rails.logger.debug "SSL error: #{e}"
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			@ -31,17 +27,17 @@ class FetchAtomService < BaseService
 | 
			
		|||
    alternate_link = page.xpath('//link[@rel="alternate"]').find { |link| link['type'] == 'application/atom+xml' }
 | 
			
		||||
 | 
			
		||||
    return nil if alternate_link.nil?
 | 
			
		||||
    return [alternate_link['href'], fetch(alternate_link['href'])]
 | 
			
		||||
    [alternate_link['href'], fetch(alternate_link['href'])]
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def process_headers(url, response)
 | 
			
		||||
    Rails.logger.debug 'Processing link header'
 | 
			
		||||
 | 
			
		||||
    link_header    = LinkHeader.parse(response['Link'].is_a?(Array) ? response['Link'].first : response['Link'])
 | 
			
		||||
    alternate_link = link_header.find_link(['rel', 'alternate'], ['type', 'application/atom+xml'])
 | 
			
		||||
    alternate_link = link_header.find_link(%w(rel alternate), %w(type application/atom+xml))
 | 
			
		||||
 | 
			
		||||
    return process_html(fetch(url)) if alternate_link.nil?
 | 
			
		||||
    return [alternate_link.href, fetch(alternate_link.href)]
 | 
			
		||||
    [alternate_link.href, fetch(alternate_link.href)]
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def fetch(url)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,11 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class FetchRemoteAccountService < BaseService
 | 
			
		||||
  def call(url)
 | 
			
		||||
    atom_url, body = FetchAtomService.new.call(url)
 | 
			
		||||
 | 
			
		||||
    return nil if atom_url.nil?
 | 
			
		||||
    return process_atom(atom_url, body)
 | 
			
		||||
    process_atom(atom_url, body)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
| 
						 | 
				
			
			@ -25,7 +27,7 @@ class FetchRemoteAccountService < BaseService
 | 
			
		|||
    Rails.logger.debug "Unparseable URL given: #{url}"
 | 
			
		||||
    nil
 | 
			
		||||
  rescue Nokogiri::XML::XPath::SyntaxError
 | 
			
		||||
    Rails.logger.debug "Invalid XML or missing namespace"
 | 
			
		||||
    Rails.logger.debug 'Invalid XML or missing namespace'
 | 
			
		||||
    nil
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,11 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class FetchRemoteStatusService < BaseService
 | 
			
		||||
  def call(url)
 | 
			
		||||
    atom_url, body = FetchAtomService.new.call(url)
 | 
			
		||||
 | 
			
		||||
    return nil if atom_url.nil?
 | 
			
		||||
    return process_atom(atom_url, body)
 | 
			
		||||
    process_atom(atom_url, body)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
| 
						 | 
				
			
			@ -20,7 +22,7 @@ class FetchRemoteStatusService < BaseService
 | 
			
		|||
 | 
			
		||||
    statuses = ProcessFeedService.new.call(body, account)
 | 
			
		||||
 | 
			
		||||
    return statuses.first
 | 
			
		||||
    statuses.first
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def extract_author(url, xml)
 | 
			
		||||
| 
						 | 
				
			
			@ -34,7 +36,7 @@ class FetchRemoteStatusService < BaseService
 | 
			
		|||
 | 
			
		||||
    return FollowRemoteAccountService.new.call("#{username}@#{domain}")
 | 
			
		||||
  rescue Nokogiri::XML::XPath::SyntaxError
 | 
			
		||||
    Rails.logger.debug "Invalid XML or missing namespace"
 | 
			
		||||
    Rails.logger.debug 'Invalid XML or missing namespace'
 | 
			
		||||
    nil
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,9 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class FollowRemoteAccountService < BaseService
 | 
			
		||||
  include OStatus2::MagicKey
 | 
			
		||||
 | 
			
		||||
  DFRN_NS = 'http://purl.org/macgirvin/dfrn/1.0'.freeze
 | 
			
		||||
  DFRN_NS = 'http://purl.org/macgirvin/dfrn/1.0'
 | 
			
		||||
 | 
			
		||||
  # Find or create a local account for a remote user.
 | 
			
		||||
  # When creating, look up the user's webfinger and fetch all
 | 
			
		||||
| 
						 | 
				
			
			@ -49,7 +51,7 @@ class FollowRemoteAccountService < BaseService
 | 
			
		|||
    get_profile(xml, account)
 | 
			
		||||
    account.save!
 | 
			
		||||
 | 
			
		||||
    return account
 | 
			
		||||
    account
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class FollowService < BaseService
 | 
			
		||||
  # Follow a remote user, notify remote user about the follow
 | 
			
		||||
  # @param [Account] source_account From which to follow
 | 
			
		||||
| 
						 | 
				
			
			@ -35,7 +37,7 @@ class FollowService < BaseService
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def redis
 | 
			
		||||
    $redis
 | 
			
		||||
    Redis.current
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def follow_remote_account_service
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class PostStatusService < BaseService
 | 
			
		||||
  # Post a text status update, fetch and notify remote users mentioned
 | 
			
		||||
  # @param [Account] account Account from which to post
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,10 +1,10 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class PrecomputeFeedService < BaseService
 | 
			
		||||
  # Fill up a user's home/mentions feed from DB and return a subset
 | 
			
		||||
  # @param [Symbol] type :home or :mentions
 | 
			
		||||
  # @param [Account] account
 | 
			
		||||
  def call(type, account)
 | 
			
		||||
    instant_return = []
 | 
			
		||||
 | 
			
		||||
    Status.send("as_#{type}_timeline", account).limit(FeedManager::MAX_ITEMS).each do |status|
 | 
			
		||||
      next if FeedManager.instance.filter?(type, status, account)
 | 
			
		||||
      redis.zadd(FeedManager.instance.key(type, account.id), status.id, status.reblog? ? status.reblog_of_id : status.id)
 | 
			
		||||
| 
						 | 
				
			
			@ -14,6 +14,6 @@ class PrecomputeFeedService < BaseService
 | 
			
		|||
  private
 | 
			
		||||
 | 
			
		||||
  def redis
 | 
			
		||||
    $redis
 | 
			
		||||
    Redis.current
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,8 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class ProcessFeedService < BaseService
 | 
			
		||||
  ACTIVITY_NS = 'http://activitystrea.ms/spec/1.0/'.freeze
 | 
			
		||||
  THREAD_NS   = 'http://purl.org/syndication/thread/1.0'.freeze
 | 
			
		||||
  ACTIVITY_NS = 'http://activitystrea.ms/spec/1.0/'
 | 
			
		||||
  THREAD_NS   = 'http://purl.org/syndication/thread/1.0'
 | 
			
		||||
 | 
			
		||||
  def call(body, account)
 | 
			
		||||
    xml = Nokogiri::XML(body)
 | 
			
		||||
| 
						 | 
				
			
			@ -89,13 +91,13 @@ class ProcessFeedService < BaseService
 | 
			
		|||
        account = @account
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      status = Status.create!({
 | 
			
		||||
      status = Status.create!(
 | 
			
		||||
        uri: id(entry),
 | 
			
		||||
        url: url(entry),
 | 
			
		||||
        account: account,
 | 
			
		||||
        text: content(entry),
 | 
			
		||||
        created_at: published(entry),
 | 
			
		||||
      })
 | 
			
		||||
        created_at: published(entry)
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
      if thread?(entry)
 | 
			
		||||
        Rails.logger.debug "Trying to attach #{status.id} (#{id(entry)}) to #{thread(entry).first}"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,8 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class ProcessHashtagsService < BaseService
 | 
			
		||||
  def call(status, tags = [])
 | 
			
		||||
    if status.local?
 | 
			
		||||
      tags = status.text.scan(Tag::HASHTAG_RE).map(&:first)
 | 
			
		||||
    end
 | 
			
		||||
    tags = status.text.scan(Tag::HASHTAG_RE).map(&:first) if status.local?
 | 
			
		||||
 | 
			
		||||
    tags.map(&:downcase).uniq.each do |tag|
 | 
			
		||||
      status.tags << Tag.where(name: tag).first_or_initialize(name: tag)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,7 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class ProcessInteractionService < BaseService
 | 
			
		||||
  ACTIVITY_NS = 'http://activitystrea.ms/spec/1.0/'.freeze
 | 
			
		||||
  ACTIVITY_NS = 'http://activitystrea.ms/spec/1.0/'
 | 
			
		||||
 | 
			
		||||
  # Record locally the remote interaction with our user
 | 
			
		||||
  # @param [String] envelope Salmon envelope
 | 
			
		||||
| 
						 | 
				
			
			@ -76,9 +78,7 @@ class ProcessInteractionService < BaseService
 | 
			
		|||
 | 
			
		||||
    return if status.nil?
 | 
			
		||||
 | 
			
		||||
    if account.id == status.account_id
 | 
			
		||||
      remove_status_service.call(status)
 | 
			
		||||
    end
 | 
			
		||||
    remove_status_service.call(status) if account.id == status.account_id
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def favourite!(xml, from_account)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class ProcessMentionsService < BaseService
 | 
			
		||||
  # Scan status for mentions and fetch remote mentioned users, create
 | 
			
		||||
  # local mention pointers, send Salmon notifications to mentioned
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class ReblogService < BaseService
 | 
			
		||||
  # Reblog a status and notify its remote author
 | 
			
		||||
  # @param [Account] account Account to reblog from
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class RemoveStatusService < BaseService
 | 
			
		||||
  def call(status)
 | 
			
		||||
    remove_from_self(status) if status.account.local?
 | 
			
		||||
| 
						 | 
				
			
			@ -62,6 +64,6 @@ class RemoveStatusService < BaseService
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def redis
 | 
			
		||||
    $redis
 | 
			
		||||
    Redis.current
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class SearchService < BaseService
 | 
			
		||||
  def call(query, limit, resolve = false)
 | 
			
		||||
    return if query.blank?
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class SendInteractionService < BaseService
 | 
			
		||||
  # Send an Atom representation of an interaction to a remote Salmon endpoint
 | 
			
		||||
  # @param [StreamEntry] stream_entry
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class SubscribeService < BaseService
 | 
			
		||||
  def call(account)
 | 
			
		||||
    account.secret = SecureRandom.hex
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class UnblockService < BaseService
 | 
			
		||||
  def call(account, target_account)
 | 
			
		||||
    account.unblock!(target_account) if account.blocking?(target_account)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class UnfavouriteService < BaseService
 | 
			
		||||
  def call(account, status)
 | 
			
		||||
    favourite = Favourite.find_by!(account: account, status: status)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class UnfollowService < BaseService
 | 
			
		||||
  # Unfollow and notify the remote user
 | 
			
		||||
  # @param [Account] source_account Where to unfollow from
 | 
			
		||||
| 
						 | 
				
			
			@ -21,6 +23,6 @@ class UnfollowService < BaseService
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def redis
 | 
			
		||||
    $redis
 | 
			
		||||
    Redis.current
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,13 +1,15 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class UpdateRemoteProfileService < BaseService
 | 
			
		||||
  POCO_NS = 'http://portablecontacts.net/spec/1.0'
 | 
			
		||||
 | 
			
		||||
  def call(author_xml, account)
 | 
			
		||||
    return if author_xml.nil?
 | 
			
		||||
 | 
			
		||||
    if author_xml.at_xpath('./poco:displayName', poco: POCO_NS).nil?
 | 
			
		||||
      account.display_name = account.username
 | 
			
		||||
    account.display_name = if author_xml.at_xpath('./poco:displayName', poco: POCO_NS).nil?
 | 
			
		||||
                             account.username
 | 
			
		||||
                           else
 | 
			
		||||
      account.display_name = author_xml.at_xpath('./poco:displayName', poco: POCO_NS).content
 | 
			
		||||
                             author_xml.at_xpath('./poco:displayName', poco: POCO_NS).content
 | 
			
		||||
                           end
 | 
			
		||||
 | 
			
		||||
    unless author_xml.at_xpath('./poco:note').nil?
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class DistributionWorker
 | 
			
		||||
  include Sidekiq::Worker
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class HubPingWorker
 | 
			
		||||
  include Sidekiq::Worker
 | 
			
		||||
  include RoutingHelper
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class NotificationWorker
 | 
			
		||||
  include Sidekiq::Worker
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class ProcessingWorker
 | 
			
		||||
  include Sidekiq::Worker
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class RegenerationWorker
 | 
			
		||||
  include Sidekiq::Worker
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class ThreadResolveWorker
 | 
			
		||||
  include Sidekiq::Worker
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,4 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
# This file is used by Rack-based servers to start the application.
 | 
			
		||||
 | 
			
		||||
require ::File.expand_path('../config/environment', __FILE__)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,7 @@
 | 
			
		|||
$redis = Redis.new({
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
Redis.current = Redis.new(
 | 
			
		||||
  host: ENV.fetch('REDIS_HOST') { 'localhost' },
 | 
			
		||||
  port: ENV.fetch('REDIS_PORT') { 6379 },
 | 
			
		||||
  driver: :hiredis
 | 
			
		||||
})
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
namespace :mastodon do
 | 
			
		||||
  namespace :media do
 | 
			
		||||
    desc 'Removes media attachments that have not been assigned to any status for longer than a day'
 | 
			
		||||
| 
						 | 
				
			
			@ -28,7 +30,7 @@ namespace :mastodon do
 | 
			
		|||
    task refresh: :environment do
 | 
			
		||||
      Account.expiring(1.day.from_now).find_each do |a|
 | 
			
		||||
        Rails.logger.debug "PuSH re-subscribing to #{a.acct}"
 | 
			
		||||
        SubscribeService.new.(a)
 | 
			
		||||
        SubscribeService.new.call(a)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			@ -36,7 +38,7 @@ namespace :mastodon do
 | 
			
		|||
  namespace :feeds do
 | 
			
		||||
    desc 'Clears all timelines so that they would be regenerated on next hit'
 | 
			
		||||
    task clear: :environment do
 | 
			
		||||
      $redis.keys('feed:*').each { |key| $redis.del(key) }
 | 
			
		||||
      Redis.current.keys('feed:*').each { |key| Redis.current.del(key) }
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue