2016-08-17 11:56:23 -04:00
class Account < ApplicationRecord
2016-03-24 21:13:30 -04:00
include Targetable
2016-09-12 12:22:43 -04:00
MENTION_RE = / (?:^| \ s| \ .|>)@([a-z0-9_]+(?:@[a-z0-9 \ . \ -]+)?) /i
IMAGE_MIME_TYPES = [ 'image/jpeg' , 'image/png' , 'image/gif' ]
2016-02-22 10:00:20 -05:00
# Local users
has_one :user , inverse_of : :account
2016-09-10 03:43:45 -04:00
validates :username , presence : true , format : { with : / \ A[a-z0-9_]+ \ z /i , message : 'only letters, numbers and underscores' } , uniqueness : { scope : :domain , case_sensitive : false } , if : 'local?'
validates :username , presence : true , uniqueness : { scope : :domain , case_sensitive : true } , unless : 'local?'
2016-02-22 10:00:20 -05:00
2016-02-27 18:02:59 -05:00
# Avatar upload
2016-09-08 12:23:59 -04:00
has_attached_file :avatar , styles : { large : '300x300#' , medium : '96x96#' , small : '48x48#' }
2016-09-12 12:22:43 -04:00
validates_attachment_content_type :avatar , content_type : IMAGE_MIME_TYPES
2016-09-10 03:43:45 -04:00
validates_attachment_size :avatar , less_than : 2 . megabytes
2016-02-27 18:02:59 -05:00
2016-03-12 14:47:22 -05:00
# Header upload
has_attached_file :header , styles : { medium : '700x335#' }
2016-09-12 12:22:43 -04:00
validates_attachment_content_type :header , content_type : IMAGE_MIME_TYPES
2016-09-10 03:43:45 -04:00
validates_attachment_size :header , less_than : 2 . megabytes
2016-03-12 14:47:22 -05:00
2016-03-16 06:18:09 -04:00
# Local user profile validations
validates :display_name , length : { maximum : 30 } , if : 'local?'
validates :note , length : { maximum : 124 } , if : 'local?'
2016-02-22 10:00:20 -05:00
# Timelines
has_many :stream_entries , inverse_of : :account
2016-02-20 16:53:20 -05:00
has_many :statuses , inverse_of : :account
2016-02-23 13:17:37 -05:00
has_many :favourites , inverse_of : :account
2016-02-28 15:22:56 -05:00
has_many :mentions , inverse_of : :account
2016-02-20 16:53:20 -05:00
2016-02-22 10:00:20 -05:00
# Follow relations
has_many :active_relationships , class_name : 'Follow' , foreign_key : 'account_id' , dependent : :destroy
has_many :passive_relationships , class_name : 'Follow' , foreign_key : 'target_account_id' , dependent : :destroy
has_many :following , through : :active_relationships , source : :target_account
has_many :followers , through : :passive_relationships , source : :account
2016-09-05 11:46:36 -04:00
has_many :media_attachments , dependent : :destroy
2016-02-22 10:00:20 -05:00
def follow! ( other_account )
2016-03-07 06:42:33 -05:00
self . active_relationships . where ( target_account : other_account ) . first_or_create! ( target_account : other_account )
2016-02-22 10:00:20 -05:00
end
def unfollow! ( other_account )
2016-03-16 16:23:40 -04:00
follow = self . active_relationships . find_by ( target_account : other_account )
follow . destroy unless follow . nil?
2016-02-22 10:00:20 -05:00
end
def following? ( other_account )
following . include? ( other_account )
end
def local?
self . domain . nil?
end
2016-02-22 12:10:30 -05:00
def acct
local? ? self . username : " #{ self . username } @ #{ self . domain } "
end
def subscribed?
! ( self . secret . blank? || self . verify_token . blank? )
end
2016-03-07 06:42:33 -05:00
def favourited? ( status )
2016-09-03 08:01:10 -04:00
( status . reblog? ? status . reblog : status ) . favourites . where ( account : self ) . count > 0
2016-03-07 06:42:33 -05:00
end
def reblogged? ( status )
2016-09-03 08:01:10 -04:00
( status . reblog? ? status . reblog : status ) . reblogs . where ( account : self ) . count > 0
2016-03-07 06:42:33 -05:00
end
2016-02-22 10:00:20 -05:00
def keypair
self . private_key . nil? ? OpenSSL :: PKey :: RSA . new ( self . public_key ) : OpenSSL :: PKey :: RSA . new ( self . private_key )
end
2016-02-20 16:53:20 -05:00
def subscription ( webhook_url )
@subscription || = OStatus2 :: Subscription . new ( self . remote_url , secret : self . secret , token : self . verify_token , webhook : webhook_url , hub : self . hub_url )
end
2016-02-26 09:28:08 -05:00
2016-02-28 08:33:13 -05:00
def ping! ( atom_url , hubs )
2016-09-01 07:21:48 -04:00
return unless local? && ! Rails . env . development?
2016-02-28 08:33:13 -05:00
OStatus2 :: Publication . new ( atom_url , hubs ) . publish
end
2016-02-27 18:51:05 -05:00
def avatar_remote_url = ( url )
2016-03-22 16:05:23 -04:00
unless self [ :avatar_remote_url ] == url
self . avatar = URI . parse ( url )
end
self [ :avatar_remote_url ] = url
2016-02-27 18:51:05 -05:00
end
2016-03-24 21:13:30 -04:00
def object_type
:person
end
2016-02-29 13:42:08 -05:00
def to_param
self . username
end
2016-03-16 13:29:52 -04:00
def self . find_local! ( username )
2016-09-04 15:06:04 -04:00
self . find_remote! ( username , nil )
end
def self . find_remote! ( username , domain )
2016-03-16 13:29:52 -04:00
table = self . arel_table
2016-09-04 15:06:04 -04:00
self . where ( table [ :username ] . matches ( username ) ) . where ( domain : domain ) . take!
2016-03-16 13:29:52 -04:00
end
2016-03-18 18:23:19 -04:00
def self . find_local ( username )
self . find_local! ( username )
rescue ActiveRecord :: RecordNotFound
nil
end
2016-09-04 15:06:04 -04:00
def self . find_remote ( username , domain )
self . find_remote! ( username , domain )
rescue ActiveRecord :: RecordNotFound
nil
end
2016-02-26 09:28:08 -05:00
before_create do
if local?
2016-02-28 15:22:56 -05:00
keypair = OpenSSL :: PKey :: RSA . new ( Rails . env . test? ? 1024 : 2048 )
2016-02-26 09:28:08 -05:00
self . private_key = keypair . to_pem
self . public_key = keypair . public_key . to_pem
end
end
2016-02-20 16:53:20 -05:00
end