app/models/remote_subject.rb in social_stream-ostatus-0.0.1 vs app/models/remote_subject.rb in social_stream-ostatus-0.1.0

- old
+ new

@@ -1,43 +1,139 @@ class RemoteSubject < ActiveRecord::Base - attr_accessible :name, :webfinger_id, :origin_node_url + include SocialStream::Models::Subject + # Create absolute routes + include Rails.application.routes.url_helpers + + attr_reader :url_helper + attr_accessible :webfinger_id + + # Save webfinger_info hash into the database + serialize :webfinger_info + + validates_uniqueness_of :webfinger_id + + before_validation :fill_information, + :on => :create + + after_create :subscribe_to_public_feed + after_destroy :unsubscribe_to_public_feed + + scope :webfinger_alias, lambda { |uri| + where('webfinger_info LIKE ?', "%aliases%#{ uri }%") + } #validates_format_of :webfinger_slug, :with => Devise.email_regexp, :allow_blank => true class << self - def find_or_create_using_webfinger_id(id) - subject = RemoteSubject.find_by_webfinger_id(id) + def find_or_create_by_webfinger_uri!(uri) + if uri =~ /^https?:\/\// + records = webfinger_alias(uri) - return subject if subject.present? + # SQL scope is not reliable + if records.present? + return records.find{ |r| r.webfinger_aliases.include?(uri) } + end - RemoteSubject.create! :name => id, - :webfinger_id => id + # TODO: create by http uri? + + raise ::ActiveRecord::RecordNotFound + end + + id = uri.dup + + if id =~ /^acct:/ + id.gsub!('acct:', '') + end + + find_or_create_by_webfinger_id!(id) end end - # Public feed url for this RemoteSubject - # - # TODO: get from webfinger? - # It does not work for every remote user! - def public_feed_url - "http://#{ webfinger_url }/api/user/#{ name }/public.atom" - end - # Return the slug in the webfinger_id def webfinger_slug splitted_webfinger_id.first end # Return the origin url in the webfinger_id def webfinger_url splitted_webfinger_id.last end - protected + # URL of the activity feed from this {RemoteSubject} + def public_feed_url + webfinger_info[:updates_from] + end + # URL of the Salmon endpoint for this {RemoteSubject} + def salmon_url + webfinger_info[:salmon] + end + + # Webfinger Alias + def webfinger_aliases + webfinger_info[:aliases] + end + + # Fetch the webfinger again + def refresh_webfinger! + fill_webfinger_info + + save! + end + + private + def splitted_webfinger_id @splitted_webfinger_id ||= webfinger_id.split('@') end + def fill_information + fill_webfinger_info + self.name = webfinger_id + end + + def fill_webfinger_info + self.webfinger_info = build_webfinger_info + self.rsa_key = finger.magic_key + end + + def build_webfinger_info + { + updates_from: finger.links[:updates_from], + salmon: finger.links[:salmon], + aliases: finger.alias + } + end + + def finger + @finger ||= + fetch_finger + end + + def fetch_finger + finger = + Proudhon::Finger.fetch webfinger_id + + # FIXME custom error + raise ::ActiveRecord::RecordNotFound if finger.blank? + + finger + end + + def subscribe_to_public_feed + return if public_feed_url.blank? + + atom = Proudhon::Atom.from_uri(public_feed_url) + + atom.subscribe(pshb_url(:host => SocialStream::Ostatus.pshb_host)) + end + + def unsubscribe_to_public_feed + return if public_feed_url.blank? + + atom = Proudhon::Atom.from_uri(public_feed_url) + + atom.unsubscribe(pshb_url(:host => SocialStream::Ostatus.pshb_host)) + end end