about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Gemfile1
-rw-r--r--Gemfile.lock9
-rw-r--r--app/helpers/atom_helper.rb6
-rw-r--r--app/models/account.rb3
-rw-r--r--app/models/mention.rb2
-rw-r--r--app/services/process_feed_service.rb36
-rw-r--r--app/services/process_mentions_service.rb12
-rw-r--r--app/views/profile/_status_footer.html.haml8
-rw-r--r--spec/rails_helper.rb2
-rw-r--r--spec/services/reblog_service_spec.rb27
10 files changed, 81 insertions, 25 deletions
diff --git a/Gemfile b/Gemfile
index ee817a0c4..b3a5b7e6d 100644
--- a/Gemfile
+++ b/Gemfile
@@ -40,6 +40,7 @@ end
 
 group :test do
   gem 'simplecov', require: false
+  gem 'webmock'
 end
 
 group :development do
diff --git a/Gemfile.lock b/Gemfile.lock
index c83a5abb1..ae68368da 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -65,6 +65,8 @@ GEM
       execjs
     coffee-script-source (1.10.0)
     concurrent-ruby (1.0.0)
+    crack (0.4.3)
+      safe_yaml (~> 1.0.0)
     debug_inspector (0.0.2)
     descendants_tracker (0.0.4)
       thread_safe (~> 0.3, >= 0.3.1)
@@ -116,6 +118,7 @@ GEM
       haml (>= 4.0.6, < 5.0)
       html2haml (>= 1.0.1)
       railties (>= 4.0.1)
+    hashdiff (0.3.0)
     hashie (3.4.3)
     hashie-forbidden_attributes (0.1.1)
       hashie (>= 3.0)
@@ -255,6 +258,7 @@ GEM
     ruby-progressbar (1.7.5)
     ruby_parser (3.8.1)
       sexp_processor (~> 4.1)
+    safe_yaml (1.0.4)
     sass (3.4.21)
     sass-rails (5.0.4)
       railties (>= 4.0.0, < 5.0)
@@ -306,6 +310,10 @@ GEM
       binding_of_caller (>= 0.7.2)
       railties (>= 4.0)
       sprockets-rails (>= 2.0, < 4.0)
+    webmock (1.24.1)
+      addressable (>= 2.3.6)
+      crack (>= 0.3.2)
+      hashdiff
 
 PLATFORMS
   ruby
@@ -349,6 +357,7 @@ DEPENDENCIES
   therubyracer
   uglifier (>= 1.3.0)
   web-console (~> 2.0)
+  webmock
 
 BUNDLED WITH
    1.11.2
diff --git a/app/helpers/atom_helper.rb b/app/helpers/atom_helper.rb
index 0cba8e964..bd7aee9a0 100644
--- a/app/helpers/atom_helper.rb
+++ b/app/helpers/atom_helper.rb
@@ -1,6 +1,6 @@
 module AtomHelper
   def stream_updated_at
-    @account.stream_entries.last ? @account.stream_entries.last.created_at : @account.updated_at
+    @account.stream_entries.last ? (@account.updated_at > @account.stream_entries.last.created_at ? @account.updated_at : @account.stream_entries.last.created_at) : @account.updated_at
   end
 
   def entry(xml, is_root, &block)
@@ -126,7 +126,9 @@ module AtomHelper
   end
 
   def link_avatar(xml, account)
-    xml.link(rel: 'avatar', type: account.avatar_content_type, href: asset_url(account.avatar.url(:large)))
+    xml.link('rel' => 'avatar', 'type' => account.avatar_content_type, 'media:width' => '300', 'media:height' =>'300', 'href' => asset_url(account.avatar.url(:large)))
+    xml.link('rel' => 'avatar', 'type' => account.avatar_content_type, 'media:width' => '96', 'media:height' =>'96', 'href' => asset_url(account.avatar.url(:medium)))
+    xml.link('rel' => 'avatar', 'type' => account.avatar_content_type, 'media:width' => '48', 'media:height' =>'48', 'href' => asset_url(account.avatar.url(:small)))
   end
 
   def logo(xml, url)
diff --git a/app/models/account.rb b/app/models/account.rb
index e9fc03a10..6cb638b3e 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -11,6 +11,7 @@ class Account < ActiveRecord::Base
   has_many :stream_entries, inverse_of: :account
   has_many :statuses, inverse_of: :account
   has_many :favourites, inverse_of: :account
+  has_many :mentions, inverse_of: :account
 
   # Follow relations
   has_many :active_relationships,  class_name: 'Follow', foreign_key: 'account_id',        dependent: :destroy
@@ -77,7 +78,7 @@ class Account < ActiveRecord::Base
 
   before_create do
     if local?
-      keypair = OpenSSL::PKey::RSA.new(Rails.env.test? ? 48 : 2048)
+      keypair = OpenSSL::PKey::RSA.new(Rails.env.test? ? 1024 : 2048)
       self.private_key = keypair.to_pem
       self.public_key  = keypair.public_key.to_pem
     end
diff --git a/app/models/mention.rb b/app/models/mention.rb
index 52f40e4b2..9fefa657a 100644
--- a/app/models/mention.rb
+++ b/app/models/mention.rb
@@ -1,6 +1,6 @@
 class Mention < ActiveRecord::Base
   belongs_to :account, inverse_of: :mentions
-  belongs_to :status, inverse_of: :mentions
+  belongs_to :status
 
   validates :account, :status, presence: true
   validates :account, uniqueness: { scope: :status }
diff --git a/app/services/process_feed_service.rb b/app/services/process_feed_service.rb
index 146869552..f6584bbda 100644
--- a/app/services/process_feed_service.rb
+++ b/app/services/process_feed_service.rb
@@ -5,10 +5,12 @@ class ProcessFeedService < BaseService
   def call(body, account)
     xml = Nokogiri::XML(body)
 
+    # If we got a full feed, make sure the account's profile is up to date
     unless xml.at_xpath('/xmlns:feed').nil?
       update_remote_profile_service.(xml.at_xpath('/xmlns:feed/xmlns:author'), account)
     end
 
+    # Process entries
     xml.xpath('//xmlns:entry').each do |entry|
       next unless [:note, :comment, :activity].include? object_type(entry)
 
@@ -16,7 +18,7 @@ class ProcessFeedService < BaseService
 
       next unless status.nil?
 
-      status = Status.new(uri: activity_id(entry), account: account, text: content(entry), created_at: published(entry), updated_at: updated(entry))
+      status = Status.new(uri: activity_id(entry), url: activity_link(entry), account: account, text: content(entry), created_at: published(entry), updated_at: updated(entry))
 
       if object_type(entry) == :comment
         add_reply!(entry, status)
@@ -26,7 +28,25 @@ class ProcessFeedService < BaseService
         add_post!(entry, status)
       end
 
-      process_mentions_service.(status) unless status.new_record?
+      # If we added a status, go through accounts it mentions and create respective relations
+      unless status.new_record?
+        entry.xpath('./xmlns:link[@rel="mentioned"]').each do |mention_link|
+          # Here we have to do a reverse lookup of local accounts by their URL!
+          # It's not pretty at all! I really wish all these protocols sticked to
+          # using acct:username@domain only! It would make things so much easier
+          # and tidier
+
+          href = Addressable::URI.parse(mention_link.attribute('href').value)
+
+          if href.host == LOCAL_DOMAIN
+            mentioned_account = Account.find_by(username: href.path.gsub('/users/', ''), domain: nil)
+
+            unless mentioned_account.nil?
+              mentioned_account.mentions.first_or_create(status: status)
+            end
+          end
+        end
+      end
     end
   end
 
@@ -103,12 +123,18 @@ class ProcessFeedService < BaseService
     xml.at_xpath('./xmlns:id').content
   end
 
+  def activity_link(xml)
+    xml.at_xpath('./xmlns:link[@rel="alternate"]').attribute('href').value
+  rescue
+    ''
+  end
+
   def target_content(xml)
     xml.at_xpath('.//activity:object/xmlns:content').content
   end
 
   def target_url(xml)
-    xml.at_xpath('.//activity:object/xmlns:link[@rel=alternate]').attribute('href').value
+    xml.at_xpath('.//activity:object/xmlns:link[@rel="alternate"]').attribute('href').value
   end
 
   def object_type(xml)
@@ -127,10 +153,6 @@ class ProcessFeedService < BaseService
     @follow_remote_account_service ||= FollowRemoteAccountService.new
   end
 
-  def process_mentions_service
-    @process_mentions_service ||= ProcessMentionsService.new
-  end
-
   def update_remote_profile_service
     @update_remote_profile_service ||= UpdateRemoteProfileService.new
   end
diff --git a/app/services/process_mentions_service.rb b/app/services/process_mentions_service.rb
index 93866666a..e1fc2f038 100644
--- a/app/services/process_mentions_service.rb
+++ b/app/services/process_mentions_service.rb
@@ -4,15 +4,17 @@ class ProcessMentionsService < BaseService
   # remote users
   # @param [Status] status
   def call(status)
+    return unless status.local?
+
     status.text.scan(Account::MENTION_RE).each do |match|
-      username, domain = match.first.split('@')
-      local_account = Account.find_by(username: username, domain: domain)
+      username, domain  = match.first.split('@')
+      mentioned_account = Account.find_by(username: username, domain: domain)
 
-      if local_account.nil?
-        local_account = follow_remote_account_service.("acct:#{match.first}")
+      if mentioned_account.nil?
+        mentioned_account = follow_remote_account_service.("acct:#{match.first}")
       end
 
-      local_account.mentions.first_or_create(status: status)
+      mentioned_account.mentions.first_or_create(status: status)
     end
 
     status.mentions.each do |mentioned_account|
diff --git a/app/views/profile/_status_footer.html.haml b/app/views/profile/_status_footer.html.haml
index 59197f26a..a2333df15 100644
--- a/app/views/profile/_status_footer.html.haml
+++ b/app/views/profile/_status_footer.html.haml
@@ -1,10 +1,2 @@
-.counter.counter-reblogs
-  %i.fa.fa-retweet
-  %span.num= status.reblogs.count
-
-.counter.counter-favourites
-  %i.fa.fa-star
-  %span.num= status.favourites.count
-
 - if status.reply?
   = link_to "In response to #{status.thread.account.acct}", status_url(status.thread), class: 'conversation-link'
diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb
index 0a04d560c..cb8088061 100644
--- a/spec/rails_helper.rb
+++ b/spec/rails_helper.rb
@@ -5,8 +5,10 @@ abort("The Rails environment is running in production mode!") if Rails.env.produ
 
 require 'spec_helper'
 require 'rspec/rails'
+require 'webmock/rspec'
 
 ActiveRecord::Migration.maintain_test_schema!
+WebMock.disable_net_connect!
 
 RSpec.configure do |config|
   config.fixture_path = "#{::Rails.root}/spec/fixtures"
diff --git a/spec/services/reblog_service_spec.rb b/spec/services/reblog_service_spec.rb
index 4e94d5a70..f12fdb837 100644
--- a/spec/services/reblog_service_spec.rb
+++ b/spec/services/reblog_service_spec.rb
@@ -1,5 +1,30 @@
 require 'rails_helper'
 
 RSpec.describe ReblogService do
-  pending
+  let(:alice)  { Fabricate(:account, username: 'alice') }
+  let(:bob)    { Fabricate(:account, username: 'bob', domain: 'example.com', salmon_url: 'http://salmon.example.com') }
+  let(:status) { Fabricate(:status, account: bob, uri: 'tag:example.com;something:something') }
+
+  subject { ReblogService.new }
+
+  before do
+    stub_const('HUB_URL', 'http://hub.example.com')
+
+    stub_request(:post, 'http://hub.example.com')
+    stub_request(:post, 'http://salmon.example.com')
+
+    subject.(alice, status)
+  end
+
+  it 'creates a reblog' do
+    expect(status.reblogs.count).to eq 1
+  end
+
+  it 'pings PubSubHubbub hubs' do
+    expect(a_request(:post, 'http://hub.example.com')).to have_been_made
+  end
+
+  it 'sends a Salmon slap for a remote reblog' do
+    expect(a_request(:post, 'http://salmon.example.com')).to have_been_made
+  end
 end