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