Improve code style
This commit is contained in:
		
					parent
					
						
							
								e4aebad35a
							
						
					
				
			
			
				commit
				
					
						927333f4f8
					
				
			
		
					 41 changed files with 126 additions and 122 deletions
				
			
		
							
								
								
									
										14
									
								
								.rubocop.yml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								.rubocop.yml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,14 @@
 | 
				
			||||||
 | 
					Rails:
 | 
				
			||||||
 | 
					  Enabled: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Metrics/LineLength:
 | 
				
			||||||
 | 
					  Enabled: false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Style/PerlBackrefs:
 | 
				
			||||||
 | 
					  AutoCorrect: false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Style/ClassAndModuleChildren:
 | 
				
			||||||
 | 
					  Enabled: false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Documentation:
 | 
				
			||||||
 | 
					  Enabled: false
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,3 @@
 | 
				
			||||||
# Be sure to restart your server when you modify this file. Action Cable runs in a loop that does not support auto reloading.
 | 
					 | 
				
			||||||
module ApplicationCable
 | 
					module ApplicationCable
 | 
				
			||||||
  class Channel < ActionCable::Channel::Base
 | 
					  class Channel < ActionCable::Channel::Base
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,3 @@
 | 
				
			||||||
# Be sure to restart your server when you modify this file. Action Cable runs in a loop that does not support auto reloading.
 | 
					 | 
				
			||||||
module ApplicationCable
 | 
					module ApplicationCable
 | 
				
			||||||
  class Connection < ActionCable::Connection::Base
 | 
					  class Connection < ActionCable::Connection::Base
 | 
				
			||||||
    identified_by :current_user
 | 
					    identified_by :current_user
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,3 @@
 | 
				
			||||||
# Be sure to restart your server when you modify this file. Action Cable runs in a loop that does not support auto reloading.
 | 
					 | 
				
			||||||
class TimelineChannel < ApplicationCable::Channel
 | 
					class TimelineChannel < ApplicationCable::Channel
 | 
				
			||||||
  def subscribed
 | 
					  def subscribed
 | 
				
			||||||
    stream_from "timeline:#{current_user.account_id}"
 | 
					    stream_from "timeline:#{current_user.account_id}"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@ class Api::SalmonController < ApiController
 | 
				
			||||||
  respond_to :txt
 | 
					  respond_to :txt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def update
 | 
					  def update
 | 
				
			||||||
    ProcessInteractionService.new.(request.body.read, @account)
 | 
					    ProcessInteractionService.new.call(request.body.read, @account)
 | 
				
			||||||
    head 201
 | 
					    head 201
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,7 @@ class Api::SubscriptionsController < ApiController
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def show
 | 
					  def show
 | 
				
			||||||
    if @account.subscription(api_subscription_url(@account.id)).valid?(params['hub.topic'])
 | 
					    if @account.subscription(api_subscription_url(@account.id)).valid?(params['hub.topic'])
 | 
				
			||||||
      @account.update(subscription_expires_at: Time.now + ((params['hub.lease_seconds'] || 86400).to_i).seconds)
 | 
					      @account.update(subscription_expires_at: Time.now.utc + (params['hub.lease_seconds'] || 86_400).to_i.seconds)
 | 
				
			||||||
      render plain: HTMLEntities.new.encode(params['hub.challenge']), status: 200
 | 
					      render plain: HTMLEntities.new.encode(params['hub.challenge']), status: 200
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
      head 404
 | 
					      head 404
 | 
				
			||||||
| 
						 | 
					@ -15,7 +15,7 @@ class Api::SubscriptionsController < ApiController
 | 
				
			||||||
    body = request.body.read
 | 
					    body = request.body.read
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if @account.subscription(api_subscription_url(@account.id)).verify(body, request.headers['HTTP_X_HUB_SIGNATURE'])
 | 
					    if @account.subscription(api_subscription_url(@account.id)).verify(body, request.headers['HTTP_X_HUB_SIGNATURE'])
 | 
				
			||||||
      ProcessFeedService.new.(body, @account)
 | 
					      ProcessFeedService.new.call(body, @account)
 | 
				
			||||||
      head 201
 | 
					      head 201
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
      head 202
 | 
					      head 202
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,19 +19,19 @@ class Api::V1::AccountsController < ApiController
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def follow
 | 
					  def follow
 | 
				
			||||||
    @follow = FollowService.new.(current_user.account, @account.acct)
 | 
					    @follow = FollowService.new.call(current_user.account, @account.acct)
 | 
				
			||||||
    set_relationship
 | 
					    set_relationship
 | 
				
			||||||
    render action: :relationship
 | 
					    render action: :relationship
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def unfollow
 | 
					  def unfollow
 | 
				
			||||||
    @unfollow = UnfollowService.new.(current_user.account, @account)
 | 
					    @unfollow = UnfollowService.new.call(current_user.account, @account)
 | 
				
			||||||
    set_relationship
 | 
					    set_relationship
 | 
				
			||||||
    render action: :relationship
 | 
					    render action: :relationship
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def relationships
 | 
					  def relationships
 | 
				
			||||||
    ids = params[:id].is_a?(Enumerable) ? params[:id].map { |id| id.to_i } : [params[:id].to_i]
 | 
					    ids = params[:id].is_a?(Enumerable) ? params[:id].map(&:to_i) : [params[:id].to_i]
 | 
				
			||||||
    @accounts    = Account.find(ids)
 | 
					    @accounts    = Account.find(ids)
 | 
				
			||||||
    @following   = Account.following_map(ids, current_user.account_id)
 | 
					    @following   = Account.following_map(ids, current_user.account_id)
 | 
				
			||||||
    @followed_by = Account.followed_by_map(ids, current_user.account_id)
 | 
					    @followed_by = Account.followed_by_map(ids, current_user.account_id)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,11 +3,9 @@ class Api::V1::FollowsController < ApiController
 | 
				
			||||||
  respond_to    :json
 | 
					  respond_to    :json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def create
 | 
					  def create
 | 
				
			||||||
    if params[:uri].blank?
 | 
					    raise ActiveRecord::RecordNotFound if params[:uri].blank?
 | 
				
			||||||
      raise ActiveRecord::RecordNotFound
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @account = FollowService.new.(current_user.account, params[:uri]).try(:target_account)
 | 
					    @account = FollowService.new.call(current_user.account, params[:uri]).try(:target_account)
 | 
				
			||||||
    render action: :show
 | 
					    render action: :show
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,34 +13,34 @@ class Api::V1::StatusesController < ApiController
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def create
 | 
					  def create
 | 
				
			||||||
    @status = PostStatusService.new.(current_user.account, params[:status], params[:in_reply_to_id].blank? ? nil : Status.find(params[:in_reply_to_id]), params[:media_ids])
 | 
					    @status = PostStatusService.new.call(current_user.account, params[:status], params[:in_reply_to_id].blank? ? nil : Status.find(params[:in_reply_to_id]), params[:media_ids])
 | 
				
			||||||
    render action: :show
 | 
					    render action: :show
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def destroy
 | 
					  def destroy
 | 
				
			||||||
    @status = Status.where(account_id: current_user.account).find(params[:id])
 | 
					    @status = Status.where(account_id: current_user.account).find(params[:id])
 | 
				
			||||||
    RemoveStatusService.new.(@status)
 | 
					    RemoveStatusService.new.call(@status)
 | 
				
			||||||
    render_empty
 | 
					    render_empty
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def reblog
 | 
					  def reblog
 | 
				
			||||||
    @status = ReblogService.new.(current_user.account, Status.find(params[:id])).reload
 | 
					    @status = ReblogService.new.call(current_user.account, Status.find(params[:id])).reload
 | 
				
			||||||
    render action: :show
 | 
					    render action: :show
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def unreblog
 | 
					  def unreblog
 | 
				
			||||||
    RemoveStatusService.new.(Status.where(account_id: current_user.account, reblog_of_id: params[:id]).first!)
 | 
					    RemoveStatusService.new.call(Status.where(account_id: current_user.account, reblog_of_id: params[:id]).first!)
 | 
				
			||||||
    @status = Status.find(params[:id])
 | 
					    @status = Status.find(params[:id])
 | 
				
			||||||
    render action: :show
 | 
					    render action: :show
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def favourite
 | 
					  def favourite
 | 
				
			||||||
    @status = FavouriteService.new.(current_user.account, Status.find(params[:id])).status.reload
 | 
					    @status = FavouriteService.new.call(current_user.account, Status.find(params[:id])).status.reload
 | 
				
			||||||
    render action: :show
 | 
					    render action: :show
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def unfavourite
 | 
					  def unfavourite
 | 
				
			||||||
    @status = UnfavouriteService.new.(current_user.account, Status.find(params[:id])).status.reload
 | 
					    @status = UnfavouriteService.new.call(current_user.account, Status.find(params[:id])).status.reload
 | 
				
			||||||
    render action: :show
 | 
					    render action: :show
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@ class ApplicationController < ActionController::Base
 | 
				
			||||||
  rescue_from ActiveRecord::RecordNotFound, with: :not_found
 | 
					  rescue_from ActiveRecord::RecordNotFound, with: :not_found
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def raise_not_found
 | 
					  def raise_not_found
 | 
				
			||||||
    raise ActionController::RoutingError.new("No route matches #{params[:unmatched_route]}")
 | 
					    raise ActionController::RoutingError, "No route matches #{params[:unmatched_route]}"
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  protected
 | 
					  protected
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,13 +1,13 @@
 | 
				
			||||||
class Auth::RegistrationsController < Devise::RegistrationsController
 | 
					class Auth::RegistrationsController < Devise::RegistrationsController
 | 
				
			||||||
  layout 'auth'
 | 
					  layout 'auth'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  before_filter :configure_sign_up_params, only: [:create]
 | 
					  before_action :configure_sign_up_params, only: [:create]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  protected
 | 
					  protected
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def build_resource(hash = nil)
 | 
					  def build_resource(hash = nil)
 | 
				
			||||||
    super(hash)
 | 
					    super(hash)
 | 
				
			||||||
    self.resource.build_account if self.resource.account.nil?
 | 
					    resource.build_account if resource.account.nil?
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def configure_sign_up_params
 | 
					  def configure_sign_up_params
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,7 +13,7 @@ class StreamEntriesController < ApplicationController
 | 
				
			||||||
      @descendants = @stream_entry.activity.descendants
 | 
					      @descendants = @stream_entry.activity.descendants
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if user_signed_in?
 | 
					      if user_signed_in?
 | 
				
			||||||
        status_ids  = [@stream_entry.activity_id] + @ancestors.map { |s| s.id } + @descendants.map { |s| s.id }
 | 
					        status_ids  = [@stream_entry.activity_id] + @ancestors.map(&:id) + @descendants.map(&:id)
 | 
				
			||||||
        @favourited = Status.favourites_map(status_ids, current_user.account_id)
 | 
					        @favourited = Status.favourites_map(status_ids, current_user.account_id)
 | 
				
			||||||
        @reblogged  = Status.reblogs_map(status_ids, current_user.account_id)
 | 
					        @reblogged  = Status.reblogs_map(status_ids, current_user.account_id)
 | 
				
			||||||
      else
 | 
					      else
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,9 +31,9 @@ class XrdController < ApplicationController
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def pem_to_magic_key(public_key)
 | 
					  def pem_to_magic_key(public_key)
 | 
				
			||||||
    modulus, exponent = [public_key.n, public_key.e].map do |component|
 | 
					    modulus, exponent = [public_key.n, public_key.e].map do |component|
 | 
				
			||||||
      result = ""
 | 
					      result = ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      until component == 0 do
 | 
					      until component.zero?
 | 
				
			||||||
        result << [component % 256].pack('C')
 | 
					        result << [component % 256].pack('C')
 | 
				
			||||||
        component >>= 8
 | 
					        component >>= 8
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
| 
						 | 
					@ -41,7 +41,7 @@ class XrdController < ApplicationController
 | 
				
			||||||
      result.reverse!
 | 
					      result.reverse!
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    (["RSA"] + [modulus, exponent].map { |n| Base64.urlsafe_encode64(n) }).join('.')
 | 
					    (['RSA'] + [modulus, exponent].map { |n| Base64.urlsafe_encode64(n) }).join('.')
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def resource_param
 | 
					  def resource_param
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,15 +17,15 @@ module StreamEntriesHelper
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def relative_time(date)
 | 
					  def relative_time(date)
 | 
				
			||||||
    date < 5.days.ago ? date.strftime("%d.%m.%Y") : "#{time_ago_in_words(date)} ago"
 | 
					    date < 5.days.ago ? date.strftime('%d.%m.%Y') : "#{time_ago_in_words(date)} ago"
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def reblogged_by_me_class(status)
 | 
					  def reblogged_by_me_class(status)
 | 
				
			||||||
    user_signed_in? && @reblogged.has_key?(status.id) ? 'reblogged' : ''
 | 
					    user_signed_in? && @reblogged.key?(status.id) ? 'reblogged' : ''
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def favourited_by_me_class(status)
 | 
					  def favourited_by_me_class(status)
 | 
				
			||||||
    user_signed_in? && @favourited.has_key?(status.id) ? 'favourited' : ''
 | 
					    user_signed_in? && @favourited.key?(status.id) ? 'favourited' : ''
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def proper_status(status)
 | 
					  def proper_status(status)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,7 +35,7 @@ class Formatter
 | 
				
			||||||
  def link_mentions(html, mentions)
 | 
					  def link_mentions(html, mentions)
 | 
				
			||||||
    html.gsub(Account::MENTION_RE) do |match|
 | 
					    html.gsub(Account::MENTION_RE) do |match|
 | 
				
			||||||
      acct    = Account::MENTION_RE.match(match)[1]
 | 
					      acct    = Account::MENTION_RE.match(match)[1]
 | 
				
			||||||
      mention = mentions.find { |item| item.account.acct.eql?(acct) }
 | 
					      mention = mentions.find { |item| item.account.acct.casecmp(acct).zero? }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      mention.nil? ? match : mention_html(match, mention.account)
 | 
					      mention.nil? ? match : mention_html(match, mention.account)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,7 @@ class Account < ApplicationRecord
 | 
				
			||||||
  include Targetable
 | 
					  include Targetable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  MENTION_RE = /(?:^|\s|\.|>)@([a-z0-9_]+(?:@[a-z0-9\.\-]+)?)/i
 | 
					  MENTION_RE = /(?:^|\s|\.|>)@([a-z0-9_]+(?:@[a-z0-9\.\-]+)?)/i
 | 
				
			||||||
  IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif']
 | 
					  IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif'].freeze
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Local users
 | 
					  # Local users
 | 
				
			||||||
  has_one :user, inverse_of: :account
 | 
					  has_one :user, inverse_of: :account
 | 
				
			||||||
| 
						 | 
					@ -45,11 +45,11 @@ class Account < ApplicationRecord
 | 
				
			||||||
  scope :expiring, -> (time) { where(subscription_expires_at: nil).or(where('subscription_expires_at < ?', time)).remote.with_followers }
 | 
					  scope :expiring, -> (time) { where(subscription_expires_at: nil).or(where('subscription_expires_at < ?', time)).remote.with_followers }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def follow!(other_account)
 | 
					  def follow!(other_account)
 | 
				
			||||||
    self.active_relationships.where(target_account: other_account).first_or_create!(target_account: other_account)
 | 
					    active_relationships.where(target_account: other_account).first_or_create!(target_account: other_account)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def unfollow!(other_account)
 | 
					  def unfollow!(other_account)
 | 
				
			||||||
    follow = self.active_relationships.find_by(target_account: other_account)
 | 
					    follow = active_relationships.find_by(target_account: other_account)
 | 
				
			||||||
    follow.destroy unless follow.nil?
 | 
					    follow.destroy unless follow.nil?
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,15 +58,15 @@ class Account < ApplicationRecord
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def local?
 | 
					  def local?
 | 
				
			||||||
    self.domain.nil?
 | 
					    domain.nil?
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def acct
 | 
					  def acct
 | 
				
			||||||
    local? ? self.username : "#{self.username}@#{self.domain}"
 | 
					    local? ? username : "#{username}@#{domain}"
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def subscribed?
 | 
					  def subscribed?
 | 
				
			||||||
    !self.subscription_expires_at.nil?
 | 
					    !subscription_expires_at.nil?
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def favourited?(status)
 | 
					  def favourited?(status)
 | 
				
			||||||
| 
						 | 
					@ -78,11 +78,11 @@ class Account < ApplicationRecord
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def keypair
 | 
					  def keypair
 | 
				
			||||||
    self.private_key.nil? ? OpenSSL::PKey::RSA.new(self.public_key) : OpenSSL::PKey::RSA.new(self.private_key)
 | 
					    private_key.nil? ? OpenSSL::PKey::RSA.new(public_key) : OpenSSL::PKey::RSA.new(private_key)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def subscription(webhook_url)
 | 
					  def subscription(webhook_url)
 | 
				
			||||||
    OStatus2::Subscription.new(self.remote_url, secret: self.secret, lease_seconds: 86400 * 30, webhook: webhook_url, hub: self.hub_url)
 | 
					    OStatus2::Subscription.new(remote_url, secret: secret, lease_seconds: 86_400 * 30, webhook: webhook_url, hub: hub_url)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def ping!(atom_url, hubs)
 | 
					  def ping!(atom_url, hubs)
 | 
				
			||||||
| 
						 | 
					@ -91,10 +91,7 @@ class Account < ApplicationRecord
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def avatar_remote_url=(url)
 | 
					  def avatar_remote_url=(url)
 | 
				
			||||||
    unless self[:avatar_remote_url] == url
 | 
					    self.avatar = URI.parse(url) unless self[:avatar_remote_url] == url
 | 
				
			||||||
      self.avatar = URI.parse(url)
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    self[:avatar_remote_url] = url
 | 
					    self[:avatar_remote_url] = url
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -103,26 +100,25 @@ class Account < ApplicationRecord
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def to_param
 | 
					  def to_param
 | 
				
			||||||
    self.username
 | 
					    username
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def self.find_local!(username)
 | 
					  def self.find_local!(username)
 | 
				
			||||||
    self.find_remote!(username, nil)
 | 
					    find_remote!(username, nil)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def self.find_remote!(username, domain)
 | 
					  def self.find_remote!(username, domain)
 | 
				
			||||||
    table = self.arel_table
 | 
					    where(arel_table[:username].matches(username)).where(domain: domain).take!
 | 
				
			||||||
    self.where(table[:username].matches(username)).where(domain: domain).take!
 | 
					 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def self.find_local(username)
 | 
					  def self.find_local(username)
 | 
				
			||||||
    self.find_local!(username)
 | 
					    find_local!(username)
 | 
				
			||||||
  rescue ActiveRecord::RecordNotFound
 | 
					  rescue ActiveRecord::RecordNotFound
 | 
				
			||||||
    nil
 | 
					    nil
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def self.find_remote(username, domain)
 | 
					  def self.find_remote(username, domain)
 | 
				
			||||||
    self.find_remote!(username, domain)
 | 
					    find_remote!(username, domain)
 | 
				
			||||||
  rescue ActiveRecord::RecordNotFound
 | 
					  rescue ActiveRecord::RecordNotFound
 | 
				
			||||||
    nil
 | 
					    nil
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,7 +25,7 @@ module Streamable
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    after_create do
 | 
					    after_create do
 | 
				
			||||||
      self.account.stream_entries.create!(activity: self) if self.account.local?
 | 
					      account.stream_entries.create!(activity: self) if account.local?
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@ class Favourite < ApplicationRecord
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def title
 | 
					  def title
 | 
				
			||||||
    "#{self.account.acct} favourited a status by #{self.status.account.acct}"
 | 
					    "#{account.acct} favourited a status by #{status.account.acct}"
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def object_type
 | 
					  def object_type
 | 
				
			||||||
| 
						 | 
					@ -19,7 +19,7 @@ class Favourite < ApplicationRecord
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def thread
 | 
					  def thread
 | 
				
			||||||
    self.status
 | 
					    status
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def target
 | 
					  def target
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,11 +7,11 @@ class Feed
 | 
				
			||||||
  def get(limit, max_id = nil)
 | 
					  def get(limit, max_id = nil)
 | 
				
			||||||
    max_id     = '+inf' if max_id.nil?
 | 
					    max_id     = '+inf' if max_id.nil?
 | 
				
			||||||
    unhydrated = redis.zrevrangebyscore(key, "(#{max_id}", '-inf', limit: [0, limit])
 | 
					    unhydrated = redis.zrevrangebyscore(key, "(#{max_id}", '-inf', limit: [0, limit])
 | 
				
			||||||
    status_map = Hash.new
 | 
					    status_map = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # If we're after most recent items and none are there, we need to precompute the feed
 | 
					    # If we're after most recent items and none are there, we need to precompute the feed
 | 
				
			||||||
    if unhydrated.empty? && max_id == '+inf'
 | 
					    if unhydrated.empty? && max_id == '+inf'
 | 
				
			||||||
      PrecomputeFeedService.new.(@type, @account, limit)
 | 
					      PrecomputeFeedService.new.call(@type, @account, limit)
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
      Status.where(id: unhydrated).with_includes.with_counters.each { |status| status_map[status.id.to_s] = status }
 | 
					      Status.where(id: unhydrated).with_includes.with_counters.each { |status| status_map[status.id.to_s] = status }
 | 
				
			||||||
      unhydrated.map { |id| status_map[id] }.compact
 | 
					      unhydrated.map { |id| status_map[id] }.compact
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,11 +8,11 @@ class Follow < ApplicationRecord
 | 
				
			||||||
  validates :account_id, uniqueness: { scope: :target_account_id }
 | 
					  validates :account_id, uniqueness: { scope: :target_account_id }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def verb
 | 
					  def verb
 | 
				
			||||||
    self.destroyed? ? :unfollow : :follow
 | 
					    destroyed? ? :unfollow : :follow
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def target
 | 
					  def target
 | 
				
			||||||
    self.target_account
 | 
					    target_account
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def object_type
 | 
					  def object_type
 | 
				
			||||||
| 
						 | 
					@ -20,6 +20,6 @@ class Follow < ApplicationRecord
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def title
 | 
					  def title
 | 
				
			||||||
    self.destroyed? ? "#{self.account.acct} is no longer following #{self.target_account.acct}" : "#{self.account.acct} started following #{self.target_account.acct}"
 | 
					    destroyed? ? "#{account.acct} is no longer following #{target_account.acct}" : "#{account.acct} started following #{target_account.acct}"
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,18 +1,18 @@
 | 
				
			||||||
class MediaAttachment < ApplicationRecord
 | 
					class MediaAttachment < ApplicationRecord
 | 
				
			||||||
  IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif']
 | 
					  IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif'].freeze
 | 
				
			||||||
  VIDEO_MIME_TYPES = ['video/webm']
 | 
					  VIDEO_MIME_TYPES = ['video/webm'].freeze
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  belongs_to :account, inverse_of: :media_attachments
 | 
					  belongs_to :account, inverse_of: :media_attachments
 | 
				
			||||||
  belongs_to :status,  inverse_of: :media_attachments
 | 
					  belongs_to :status,  inverse_of: :media_attachments
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  has_attached_file :file, styles: lambda { |f| f.instance.image? ? { small: '510x680>' } : { small: { convert_options: { output: { vf: 'scale="min(510\, iw):min(680\, ih)":force_original_aspect_ratio=decrease' } }, format: 'png', time: 1 } } }, processors: lambda { |f| f.video? ? [:transcoder] : [:thumbnail] }
 | 
					  has_attached_file :file, styles: -> (f) { f.instance.image? ? { small: '510x680>' } : { small: { convert_options: { output: { vf: 'scale="min(510\, iw):min(680\, ih)":force_original_aspect_ratio=decrease' } }, format: 'png', time: 1 } } }, processors: -> (f) { f.video? ? [:transcoder] : [:thumbnail] }
 | 
				
			||||||
  validates_attachment_content_type :file, content_type: IMAGE_MIME_TYPES + VIDEO_MIME_TYPES
 | 
					  validates_attachment_content_type :file, content_type: IMAGE_MIME_TYPES + VIDEO_MIME_TYPES
 | 
				
			||||||
  validates_attachment_size :file, less_than: 4.megabytes
 | 
					  validates_attachment_size :file, less_than: 4.megabytes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  validates :account, presence: true
 | 
					  validates :account, presence: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def local?
 | 
					  def local?
 | 
				
			||||||
    self.remote_url.blank?
 | 
					    remote_url.blank?
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def file_remote_url=(url)
 | 
					  def file_remote_url=(url)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,21 +15,21 @@ class Status < ApplicationRecord
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  validates :account, presence: true
 | 
					  validates :account, presence: true
 | 
				
			||||||
  validates :uri, uniqueness: true, unless: 'local?'
 | 
					  validates :uri, uniqueness: true, unless: 'local?'
 | 
				
			||||||
  validates :text, presence: true, length: { maximum: 500 }, if: Proc.new { |s| s.local? && !s.reblog? }
 | 
					  validates :text, presence: true, length: { maximum: 500 }, if: proc { |s| s.local? && !s.reblog? }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  scope :with_counters, -> { select('statuses.*, (select count(r.id) from statuses as r where r.reblog_of_id = statuses.id) as reblogs_count, (select count(f.id) from favourites as f where f.status_id = statuses.id) as favourites_count') }
 | 
					  scope :with_counters, -> { select('statuses.*, (select count(r.id) from statuses as r where r.reblog_of_id = statuses.id) as reblogs_count, (select count(f.id) from favourites as f where f.status_id = statuses.id) as favourites_count') }
 | 
				
			||||||
  scope :with_includes, -> { includes(:account, :media_attachments, :stream_entry, mentions: :account, reblog: [:account, mentions: :account], thread: :account) }
 | 
					  scope :with_includes, -> { includes(:account, :media_attachments, :stream_entry, mentions: :account, reblog: [:account, mentions: :account], thread: :account) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def local?
 | 
					  def local?
 | 
				
			||||||
    self.uri.nil?
 | 
					    uri.nil?
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def reblog?
 | 
					  def reblog?
 | 
				
			||||||
    !self.reblog_of_id.nil?
 | 
					    !reblog_of_id.nil?
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def reply?
 | 
					  def reply?
 | 
				
			||||||
    !self.in_reply_to_id.nil?
 | 
					    !in_reply_to_id.nil?
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def verb
 | 
					  def verb
 | 
				
			||||||
| 
						 | 
					@ -41,11 +41,11 @@ class Status < ApplicationRecord
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def content
 | 
					  def content
 | 
				
			||||||
    reblog? ? self.reblog.text : self.text
 | 
					    reblog? ? reblog.text : text
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def target
 | 
					  def target
 | 
				
			||||||
    self.reblog
 | 
					    reblog
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def title
 | 
					  def title
 | 
				
			||||||
| 
						 | 
					@ -53,33 +53,33 @@ class Status < ApplicationRecord
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def reblogs_count
 | 
					  def reblogs_count
 | 
				
			||||||
    self.attributes['reblogs_count'] || self.reblogs.count
 | 
					    attributes['reblogs_count'] || reblogs.count
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def favourites_count
 | 
					  def favourites_count
 | 
				
			||||||
    self.attributes['favourites_count'] || self.favourites.count
 | 
					    attributes['favourites_count'] || favourites.count
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def ancestors
 | 
					  def ancestors
 | 
				
			||||||
    ids      = (Status.find_by_sql(['WITH RECURSIVE search_tree(id, in_reply_to_id, path) AS (SELECT id, in_reply_to_id, ARRAY[id] FROM statuses WHERE id = ? UNION ALL SELECT statuses.id, statuses.in_reply_to_id, path || statuses.id FROM search_tree JOIN statuses ON statuses.id = search_tree.in_reply_to_id WHERE NOT statuses.id = ANY(path)) SELECT id FROM search_tree ORDER BY path DESC', self.id]) - [self]).pluck(:id)
 | 
					    ids      = (Status.find_by_sql(['WITH RECURSIVE search_tree(id, in_reply_to_id, path) AS (SELECT id, in_reply_to_id, ARRAY[id] FROM statuses WHERE id = ? UNION ALL SELECT statuses.id, statuses.in_reply_to_id, path || statuses.id FROM search_tree JOIN statuses ON statuses.id = search_tree.in_reply_to_id WHERE NOT statuses.id = ANY(path)) SELECT id FROM search_tree ORDER BY path DESC', id]) - [self]).pluck(:id)
 | 
				
			||||||
    statuses = Status.where(id: ids).with_counters.with_includes.group_by(&:id)
 | 
					    statuses = Status.where(id: ids).with_counters.with_includes.group_by(&:id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ids.map { |id| statuses[id].first }
 | 
					    ids.map { |id| statuses[id].first }
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def descendants
 | 
					  def descendants
 | 
				
			||||||
    ids      = (Status.find_by_sql(['WITH RECURSIVE search_tree(id, path) AS (SELECT id, ARRAY[id] FROM statuses WHERE id = ? UNION ALL SELECT statuses.id, path || statuses.id FROM search_tree JOIN statuses ON statuses.in_reply_to_id = search_tree.id WHERE NOT statuses.id = ANY(path)) SELECT id FROM search_tree ORDER BY path', self.id]) - [self]).pluck(:id)
 | 
					    ids      = (Status.find_by_sql(['WITH RECURSIVE search_tree(id, path) AS (SELECT id, ARRAY[id] FROM statuses WHERE id = ? UNION ALL SELECT statuses.id, path || statuses.id FROM search_tree JOIN statuses ON statuses.in_reply_to_id = search_tree.id WHERE NOT statuses.id = ANY(path)) SELECT id FROM search_tree ORDER BY path', id]) - [self]).pluck(:id)
 | 
				
			||||||
    statuses = Status.where(id: ids).with_counters.with_includes.group_by(&:id)
 | 
					    statuses = Status.where(id: ids).with_counters.with_includes.group_by(&:id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ids.map { |id| statuses[id].first }
 | 
					    ids.map { |id| statuses[id].first }
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def self.as_home_timeline(account)
 | 
					  def self.as_home_timeline(account)
 | 
				
			||||||
    self.where(account: [account] + account.following).with_includes.with_counters
 | 
					    where(account: [account] + account.following).with_includes.with_counters
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def self.as_mentions_timeline(account)
 | 
					  def self.as_mentions_timeline(account)
 | 
				
			||||||
    self.where(id: Mention.where(account: account).pluck(:status_id)).with_includes.with_counters
 | 
					    where(id: Mention.where(account: account).pluck(:status_id)).with_includes.with_counters
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def self.favourites_map(status_ids, account_id)
 | 
					  def self.favourites_map(status_ids, account_id)
 | 
				
			||||||
| 
						 | 
					@ -87,10 +87,10 @@ class Status < ApplicationRecord
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def self.reblogs_map(status_ids, account_id)
 | 
					  def self.reblogs_map(status_ids, account_id)
 | 
				
			||||||
    self.where(reblog_of_id: status_ids).where(account_id: account_id).map { |s| [s.reblog_of_id, true] }.to_h
 | 
					    where(reblog_of_id: status_ids).where(account_id: account_id).map { |s| [s.reblog_of_id, true] }.to_h
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  before_validation do
 | 
					  before_validation do
 | 
				
			||||||
    self.text.strip!
 | 
					    text.strip!
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,16 +10,16 @@ class StreamEntry < ApplicationRecord
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  validates :account, :activity, presence: true
 | 
					  validates :account, :activity, presence: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  STATUS_INCLUDES = [:account, :stream_entry, :media_attachments, mentions: :account, reblog: [:stream_entry, :account, mentions: :account], thread: [:stream_entry, :account]]
 | 
					  STATUS_INCLUDES = [:account, :stream_entry, :media_attachments, mentions: :account, reblog: [:stream_entry, :account, mentions: :account], thread: [:stream_entry, :account]].freeze
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  scope :with_includes, -> { includes(:account, status: STATUS_INCLUDES, favourite: [:account, :stream_entry, status: STATUS_INCLUDES], follow: [:target_account, :stream_entry]) }
 | 
					  scope :with_includes, -> { includes(:account, status: STATUS_INCLUDES, favourite: [:account, :stream_entry, status: STATUS_INCLUDES], follow: [:target_account, :stream_entry]) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def object_type
 | 
					  def object_type
 | 
				
			||||||
    orphaned? ? :activity : (targeted? ? :activity : self.activity.object_type)
 | 
					    orphaned? ? :activity : (targeted? ? :activity : activity.object_type)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def verb
 | 
					  def verb
 | 
				
			||||||
    orphaned? ? :delete : self.activity.verb
 | 
					    orphaned? ? :delete : activity.verb
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def targeted?
 | 
					  def targeted?
 | 
				
			||||||
| 
						 | 
					@ -27,15 +27,15 @@ class StreamEntry < ApplicationRecord
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def target
 | 
					  def target
 | 
				
			||||||
    orphaned? ? nil : self.activity.target
 | 
					    orphaned? ? nil : activity.target
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def title
 | 
					  def title
 | 
				
			||||||
    orphaned? ? nil : self.activity.title
 | 
					    orphaned? ? nil : activity.title
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def content
 | 
					  def content
 | 
				
			||||||
    orphaned? ? nil : self.activity.content
 | 
					    orphaned? ? nil : activity.content
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def threaded?
 | 
					  def threaded?
 | 
				
			||||||
| 
						 | 
					@ -43,20 +43,20 @@ class StreamEntry < ApplicationRecord
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def thread
 | 
					  def thread
 | 
				
			||||||
    orphaned? ? nil : self.activity.thread
 | 
					    orphaned? ? nil : activity.thread
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def mentions
 | 
					  def mentions
 | 
				
			||||||
    self.activity.respond_to?(:mentions) ? self.activity.mentions.map { |x| x.account } : []
 | 
					    activity.respond_to?(:mentions) ? activity.mentions.map { |x| x.account } : []
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def activity
 | 
					  def activity
 | 
				
			||||||
    self.send(self.activity_type.downcase.to_sym)
 | 
					    send(activity_type.downcase.to_sym)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def orphaned?
 | 
					  def orphaned?
 | 
				
			||||||
    self.activity.nil?
 | 
					    activity.nil?
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,6 +13,6 @@ class User < ApplicationRecord
 | 
				
			||||||
  scope :admins,   -> { where(admin: true) }
 | 
					  scope :admins,   -> { where(admin: true) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def admin?
 | 
					  def admin?
 | 
				
			||||||
    self.admin
 | 
					    admin
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +17,7 @@ class FetchAtomService < BaseService
 | 
				
			||||||
  private
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def process_html(body)
 | 
					  def process_html(body)
 | 
				
			||||||
    Rails.logger.debug "Processing HTML"
 | 
					    Rails.logger.debug 'Processing HTML'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    page = Nokogiri::HTML(body)
 | 
					    page = Nokogiri::HTML(body)
 | 
				
			||||||
    alternate_link = page.xpath('//link[@rel="alternate"]').find { |link| link['type'] == 'application/atom+xml' }
 | 
					    alternate_link = page.xpath('//link[@rel="alternate"]').find { |link| link['type'] == 'application/atom+xml' }
 | 
				
			||||||
| 
						 | 
					@ -27,7 +27,7 @@ class FetchAtomService < BaseService
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def process_headers(url, response)
 | 
					  def process_headers(url, response)
 | 
				
			||||||
    Rails.logger.debug "Processing link header"
 | 
					    Rails.logger.debug 'Processing link header'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    link_header    = LinkHeader.parse(response['Link'].is_a?(Array) ? response['Link'].first : response['Link'])
 | 
					    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(['rel', 'alternate'], ['type', 'application/atom+xml'])
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
class FetchRemoteAccountService < BaseService
 | 
					class FetchRemoteAccountService < BaseService
 | 
				
			||||||
  def call(url)
 | 
					  def call(url)
 | 
				
			||||||
    atom_url, body = FetchAtomService.new.(url)
 | 
					    atom_url, body = FetchAtomService.new.call(url)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return nil if atom_url.nil?
 | 
					    return nil if atom_url.nil?
 | 
				
			||||||
    return process_atom(atom_url, body)
 | 
					    return process_atom(atom_url, body)
 | 
				
			||||||
| 
						 | 
					@ -18,6 +18,6 @@ class FetchRemoteAccountService < BaseService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Rails.logger.debug "Going to webfinger #{username}@#{domain}"
 | 
					    Rails.logger.debug "Going to webfinger #{username}@#{domain}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return FollowRemoteAccountService.new.("#{username}@#{domain}")
 | 
					    return FollowRemoteAccountService.new.call("#{username}@#{domain}")
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
class FetchRemoteStatusService < BaseService
 | 
					class FetchRemoteStatusService < BaseService
 | 
				
			||||||
  def call(url)
 | 
					  def call(url)
 | 
				
			||||||
    atom_url, body = FetchAtomService.new.(url)
 | 
					    atom_url, body = FetchAtomService.new.call(url)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return nil if atom_url.nil?
 | 
					    return nil if atom_url.nil?
 | 
				
			||||||
    return process_atom(atom_url, body)
 | 
					    return process_atom(atom_url, body)
 | 
				
			||||||
| 
						 | 
					@ -9,14 +9,14 @@ class FetchRemoteStatusService < BaseService
 | 
				
			||||||
  private
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def process_atom(url, body)
 | 
					  def process_atom(url, body)
 | 
				
			||||||
    Rails.logger.debug "Processing Atom for remote status"
 | 
					    Rails.logger.debug 'Processing Atom for remote status'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    xml     = Nokogiri::XML(body)
 | 
					    xml     = Nokogiri::XML(body)
 | 
				
			||||||
    account = extract_author(url, xml)
 | 
					    account = extract_author(url, xml)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return nil if account.nil?
 | 
					    return nil if account.nil?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    statuses = ProcessFeedService.new.(body, account)
 | 
					    statuses = ProcessFeedService.new.call(body, account)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return statuses.first
 | 
					    return statuses.first
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
| 
						 | 
					@ -30,6 +30,6 @@ class FetchRemoteStatusService < BaseService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Rails.logger.debug "Going to webfinger #{username}@#{domain}"
 | 
					    Rails.logger.debug "Going to webfinger #{username}@#{domain}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return FollowRemoteAccountService.new.("#{username}@#{domain}")
 | 
					    return FollowRemoteAccountService.new.call("#{username}@#{domain}")
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,11 +28,11 @@ class FollowRemoteAccountService < BaseService
 | 
				
			||||||
    hubs = feed.xpath('//xmlns:link[@rel="hub"]')
 | 
					    hubs = feed.xpath('//xmlns:link[@rel="hub"]')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if hubs.empty? || hubs.first.attribute('href').nil?
 | 
					    if hubs.empty? || hubs.first.attribute('href').nil?
 | 
				
			||||||
      raise Goldfinger::Error, "No PubSubHubbub hubs found"
 | 
					      raise Goldfinger::Error, 'No PubSubHubbub hubs found'
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if feed.at_xpath('/xmlns:feed/xmlns:author/xmlns:uri').nil?
 | 
					    if feed.at_xpath('/xmlns:feed/xmlns:author/xmlns:uri').nil?
 | 
				
			||||||
      raise Goldfinger::Error, "No author URI found"
 | 
					      raise Goldfinger::Error, 'No author URI found'
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    account.uri     = feed.at_xpath('/xmlns:feed/xmlns:author/xmlns:uri').content
 | 
					    account.uri     = feed.at_xpath('/xmlns:feed/xmlns:author/xmlns:uri').content
 | 
				
			||||||
| 
						 | 
					@ -53,12 +53,12 @@ class FollowRemoteAccountService < BaseService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def get_profile(xml, account)
 | 
					  def get_profile(xml, account)
 | 
				
			||||||
    author = xml.at_xpath('/xmlns:feed/xmlns:author')
 | 
					    author = xml.at_xpath('/xmlns:feed/xmlns:author')
 | 
				
			||||||
    update_remote_profile_service.(author, account)
 | 
					    update_remote_profile_service.call(author, account)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def magic_key_to_pem(magic_key)
 | 
					  def magic_key_to_pem(magic_key)
 | 
				
			||||||
    _, modulus, exponent = magic_key.split('.')
 | 
					    _, modulus, exponent = magic_key.split('.')
 | 
				
			||||||
    modulus, exponent = [modulus, exponent].map { |n| Base64.urlsafe_decode64(n).bytes.inject(0) { |num, byte| (num << 8) | byte } }
 | 
					    modulus, exponent = [modulus, exponent].map { |n| Base64.urlsafe_decode64(n).bytes.inject(0) { |a, e| (a << 8) | e } }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    key   = OpenSSL::PKey::RSA.new
 | 
					    key   = OpenSSL::PKey::RSA.new
 | 
				
			||||||
    key.n = modulus
 | 
					    key.n = modulus
 | 
				
			||||||
| 
						 | 
					@ -75,4 +75,3 @@ class FollowRemoteAccountService < BaseService
 | 
				
			||||||
    HTTP.timeout(:per_operation, write: 20, connect: 20, read: 50)
 | 
					    HTTP.timeout(:per_operation, write: 20, connect: 20, read: 50)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@ class FollowService < BaseService
 | 
				
			||||||
  # @param [Account] source_account From which to follow
 | 
					  # @param [Account] source_account From which to follow
 | 
				
			||||||
  # @param [String] uri User URI to follow in the form of username@domain
 | 
					  # @param [String] uri User URI to follow in the form of username@domain
 | 
				
			||||||
  def call(source_account, uri)
 | 
					  def call(source_account, uri)
 | 
				
			||||||
    target_account = follow_remote_account_service.(uri)
 | 
					    target_account = follow_remote_account_service.call(uri)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return nil if target_account.nil? || target_account.id == source_account.id
 | 
					    return nil if target_account.nil? || target_account.id == source_account.id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@ class FollowService < BaseService
 | 
				
			||||||
    if target_account.local?
 | 
					    if target_account.local?
 | 
				
			||||||
      NotificationMailer.follow(target_account, source_account).deliver_later
 | 
					      NotificationMailer.follow(target_account, source_account).deliver_later
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
      subscribe_service.(target_account)
 | 
					      subscribe_service.call(target_account)
 | 
				
			||||||
      NotificationWorker.perform_async(follow.stream_entry.id, target_account.id)
 | 
					      NotificationWorker.perform_async(follow.stream_entry.id, target_account.id)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,7 +8,7 @@ class PostStatusService < BaseService
 | 
				
			||||||
  def call(account, text, in_reply_to = nil, media_ids = nil)
 | 
					  def call(account, text, in_reply_to = nil, media_ids = nil)
 | 
				
			||||||
    status = account.statuses.create!(text: text, thread: in_reply_to)
 | 
					    status = account.statuses.create!(text: text, thread: in_reply_to)
 | 
				
			||||||
    attach_media(status, media_ids)
 | 
					    attach_media(status, media_ids)
 | 
				
			||||||
    process_mentions_service.(status)
 | 
					    process_mentions_service.call(status)
 | 
				
			||||||
    DistributionWorker.perform_async(status.id)
 | 
					    DistributionWorker.perform_async(status.id)
 | 
				
			||||||
    account.ping!(account_url(account, format: 'atom'), [Rails.configuration.x.hub_url])
 | 
					    account.ping!(account_url(account, format: 'atom'), [Rails.configuration.x.hub_url])
 | 
				
			||||||
    status
 | 
					    status
 | 
				
			||||||
| 
						 | 
					@ -19,7 +19,7 @@ class PostStatusService < BaseService
 | 
				
			||||||
  def attach_media(status, media_ids)
 | 
					  def attach_media(status, media_ids)
 | 
				
			||||||
    return if media_ids.nil? || !media_ids.is_a?(Enumerable)
 | 
					    return if media_ids.nil? || !media_ids.is_a?(Enumerable)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    media = MediaAttachment.where(status_id: nil).where(id: media_ids.take(4).map { |id| id.to_i })
 | 
					    media = MediaAttachment.where(status_id: nil).where(id: media_ids.take(4).map(&:to_i))
 | 
				
			||||||
    media.update(status_id: status.id)
 | 
					    media.update(status_id: status.id)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,7 +5,7 @@ class ProcessFeedService < BaseService
 | 
				
			||||||
  # @return [Enumerable] created statuses
 | 
					  # @return [Enumerable] created statuses
 | 
				
			||||||
  def call(body, account)
 | 
					  def call(body, account)
 | 
				
			||||||
    xml = Nokogiri::XML(body)
 | 
					    xml = Nokogiri::XML(body)
 | 
				
			||||||
    update_remote_profile_service.(xml.at_xpath('/xmlns:feed/xmlns:author'), account) unless xml.at_xpath('/xmlns:feed').nil?
 | 
					    update_remote_profile_service.call(xml.at_xpath('/xmlns:feed/xmlns:author'), account) unless xml.at_xpath('/xmlns:feed').nil?
 | 
				
			||||||
    xml.xpath('//xmlns:entry').reverse_each.map { |entry| process_entry(account, entry) }.compact
 | 
					    xml.xpath('//xmlns:entry').reverse_each.map { |entry| process_entry(account, entry) }.compact
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -77,7 +77,7 @@ class ProcessFeedService < BaseService
 | 
				
			||||||
        mentioned_account = Account.find_by(url: href.to_s)
 | 
					        mentioned_account = Account.find_by(url: href.to_s)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if mentioned_account.nil?
 | 
					        if mentioned_account.nil?
 | 
				
			||||||
          mentioned_account = FetchRemoteAccountService.new.(href)
 | 
					          mentioned_account = FetchRemoteAccountService.new.call(href)
 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        unless mentioned_account.nil?
 | 
					        unless mentioned_account.nil?
 | 
				
			||||||
| 
						 | 
					@ -128,7 +128,7 @@ class ProcessFeedService < BaseService
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def delete_post!(status)
 | 
					  def delete_post!(status)
 | 
				
			||||||
    remove_status_service.(status)
 | 
					    remove_status_service.call(status)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def find_original_status(_xml, id)
 | 
					  def find_original_status(_xml, id)
 | 
				
			||||||
| 
						 | 
					@ -148,7 +148,7 @@ class ProcessFeedService < BaseService
 | 
				
			||||||
    account  = Account.find_by(username: username, domain: domain)
 | 
					    account  = Account.find_by(username: username, domain: domain)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if account.nil?
 | 
					    if account.nil?
 | 
				
			||||||
      account = follow_remote_account_service.("#{username}@#{domain}")
 | 
					      account = follow_remote_account_service.call("#{username}@#{domain}")
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    status = Status.new(account: account, uri: target_id(xml), text: target_content(xml), url: target_url(xml), created_at: published(xml), updated_at: updated(xml))
 | 
					    status = Status.new(account: account, uri: target_id(xml), text: target_content(xml), url: target_url(xml), created_at: published(xml), updated_at: updated(xml))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,11 +14,11 @@ class ProcessInteractionService < BaseService
 | 
				
			||||||
    account  = Account.find_by(username: username, domain: domain)
 | 
					    account  = Account.find_by(username: username, domain: domain)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if account.nil?
 | 
					    if account.nil?
 | 
				
			||||||
      account = follow_remote_account_service.("#{username}@#{domain}")
 | 
					      account = follow_remote_account_service.call("#{username}@#{domain}")
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if salmon.verify(envelope, account.keypair)
 | 
					    if salmon.verify(envelope, account.keypair)
 | 
				
			||||||
      update_remote_profile_service.(xml.at_xpath('/xmlns:entry/xmlns:author'), account)
 | 
					      update_remote_profile_service.call(xml.at_xpath('/xmlns:entry/xmlns:author'), account)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      case verb(xml)
 | 
					      case verb(xml)
 | 
				
			||||||
      when :follow
 | 
					      when :follow
 | 
				
			||||||
| 
						 | 
					@ -71,7 +71,7 @@ class ProcessInteractionService < BaseService
 | 
				
			||||||
    return if status.nil?
 | 
					    return if status.nil?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if account.id == status.account_id
 | 
					    if account.id == status.account_id
 | 
				
			||||||
      remove_status_service.(status)
 | 
					      remove_status_service.call(status)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -82,7 +82,7 @@ class ProcessInteractionService < BaseService
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def add_post!(body, account)
 | 
					  def add_post!(body, account)
 | 
				
			||||||
    process_feed_service.(body, account)
 | 
					    process_feed_service.call(body, account)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def status(xml)
 | 
					  def status(xml)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@ class ProcessMentionsService < BaseService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if mentioned_account.nil? && !domain.nil?
 | 
					      if mentioned_account.nil? && !domain.nil?
 | 
				
			||||||
        begin
 | 
					        begin
 | 
				
			||||||
          mentioned_account = follow_remote_account_service.("#{match.first}")
 | 
					          mentioned_account = follow_remote_account_service.call(match.first.to_s)
 | 
				
			||||||
        rescue Goldfinger::Error, HTTP::Error
 | 
					        rescue Goldfinger::Error, HTTP::Error
 | 
				
			||||||
          mentioned_account = nil
 | 
					          mentioned_account = nil
 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,7 +39,7 @@ class RemoveStatusService < BaseService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def remove_reblogs(status)
 | 
					  def remove_reblogs(status)
 | 
				
			||||||
    status.reblogs.each do |reblog|
 | 
					    status.reblogs.each do |reblog|
 | 
				
			||||||
      RemoveStatusService.new.(reblog)
 | 
					      RemoveStatusService.new.call(reblog)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,6 @@ class DistributionWorker
 | 
				
			||||||
  include Sidekiq::Worker
 | 
					  include Sidekiq::Worker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def perform(status_id)
 | 
					  def perform(status_id)
 | 
				
			||||||
    FanOutOnWriteService.new.(Status.find(status_id))
 | 
					    FanOutOnWriteService.new.call(Status.find(status_id))
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,6 @@ class NotificationWorker
 | 
				
			||||||
  include Sidekiq::Worker
 | 
					  include Sidekiq::Worker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def perform(stream_entry_id, target_account_id)
 | 
					  def perform(stream_entry_id, target_account_id)
 | 
				
			||||||
    SendInteractionService.new.(StreamEntry.find(stream_entry_id), Account.find(target_account_id))
 | 
					    SendInteractionService.new.call(StreamEntry.find(stream_entry_id), Account.find(target_account_id))
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@ class ThreadResolveWorker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def perform(child_status_id, parent_url)
 | 
					  def perform(child_status_id, parent_url)
 | 
				
			||||||
    child_status  = Status.find(child_status_id)
 | 
					    child_status  = Status.find(child_status_id)
 | 
				
			||||||
    parent_status = FetchRemoteStatusService.new.(parent_url)
 | 
					    parent_status = FetchRemoteStatusService.new.call(parent_url)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    unless parent_status.nil?
 | 
					    unless parent_status.nil?
 | 
				
			||||||
      child_status.thread = parent_status
 | 
					      child_status.thread = parent_status
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue