Improve code style

This commit is contained in:
Eugen Rochko 2016-09-29 21:28:21 +02:00
parent e4aebad35a
commit 927333f4f8
41 changed files with 126 additions and 122 deletions

14
.rubocop.yml Normal file
View File

@ -0,0 +1,14 @@
Rails:
Enabled: true
Metrics/LineLength:
Enabled: false
Style/PerlBackrefs:
AutoCorrect: false
Style/ClassAndModuleChildren:
Enabled: false
Documentation:
Enabled: false

View File

@ -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

View File

@ -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

View File

@ -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}"

View File

@ -7,7 +7,7 @@ class AccountsController < ApplicationController
def show def show
respond_to do |format| respond_to do |format|
format.html do format.html do
@statuses = @account.statuses.order('id desc').with_includes.with_counters.paginate(page: params[:page], per_page: 10) @statuses = @account.statuses.order('id desc').with_includes.with_counters.paginate(page: params[:page], per_page: 10)
if user_signed_in? if user_signed_in?
status_ids = @statuses.collect { |s| [s.id, s.reblog_of_id] }.flatten.uniq status_ids = @statuses.collect { |s| [s.id, s.reblog_of_id] }.flatten.uniq

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -7,7 +7,7 @@ class HomeController < ApplicationController
@mentions = Feed.new(:mentions, current_user.account).get(20) @mentions = Feed.new(:mentions, current_user.account).get(20)
@token = find_or_create_access_token.token @token = find_or_create_access_token.token
end end
private private
def authenticate_user! def authenticate_user!

View File

@ -1,6 +1,6 @@
class SettingsController < ApplicationController class SettingsController < ApplicationController
layout 'auth' layout 'auth'
before_action :authenticate_user! before_action :authenticate_user!
before_action :set_account before_action :set_account

View File

@ -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

View File

@ -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

View File

@ -200,6 +200,6 @@ module AtomBuilderHelper
end end
def single_link_avatar(xml, account, size, px) def single_link_avatar(xml, account, size, px)
xml.link('rel' => 'avatar', 'type' => account.avatar_content_type, 'media:width' => px, 'media:height' =>px, 'href' => full_asset_url(account.avatar.url(size, false))) xml.link('rel' => 'avatar', 'type' => account.avatar_content_type, 'media:width' => px, 'media:height' => px, 'href' => full_asset_url(account.avatar.url(size, false)))
end end
end end

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -11,8 +11,8 @@ class User < ApplicationRecord
scope :prolific, -> { joins('inner join statuses on statuses.account_id = users.account_id').select('users.*, count(statuses.id) as statuses_count').group('users.id').order('statuses_count desc') } scope :prolific, -> { joins('inner join statuses on statuses.account_id = users.account_id').select('users.*, count(statuses.id) as statuses_count').group('users.id').order('statuses_count desc') }
scope :recent, -> { order('created_at desc') } scope :recent, -> { order('created_at desc') }
scope :admins, -> { where(admin: true) } scope :admins, -> { where(admin: true) }
def admin? def admin?
self.admin admin
end end
end end

View File

@ -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'])

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
@ -60,7 +60,7 @@ class ProcessFeedService < BaseService
href_val = mention_link.attribute('href').value href_val = mention_link.attribute('href').value
next if href_val == 'http://activityschema.org/collection/public' next if href_val == 'http://activityschema.org/collection/public'
href = Addressable::URI.parse(href_val) href = Addressable::URI.parse(href_val)
if href.host == Rails.configuration.x.local_domain if href.host == Rails.configuration.x.local_domain
@ -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?
@ -94,7 +94,7 @@ class ProcessFeedService < BaseService
media = MediaAttachment.where(status: status, remote_url: enclosure_link.attribute('href').value).first media = MediaAttachment.where(status: status, remote_url: enclosure_link.attribute('href').value).first
next unless media.nil? next unless media.nil?
media = MediaAttachment.new(account: status.account, status: status, remote_url: enclosure_link.attribute('href').value) media = MediaAttachment.new(account: status.account, status: status, remote_url: enclosure_link.attribute('href').value)
media.file_remote_url = enclosure_link.attribute('href').value media.file_remote_url = enclosure_link.attribute('href').value
media.save media.save
@ -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))

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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