From ee73d35eea024894e851d807132c3f21a133152d Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 23 Feb 2016 22:17:07 +0100 Subject: [PATCH] Incoming Salmon requests can be turned into follows and unfollows --- README.md | 6 +++ app/services/process_interaction_service.rb | 49 ++++++++++++++++----- config/initializers/ostatus.rb | 7 +-- 3 files changed, 49 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index ce820af34..588c763f3 100644 --- a/README.md +++ b/README.md @@ -11,3 +11,9 @@ The core ideals of this project are: - Ease of deployment. The end-goal of this project is to be distributable as a Docker image. **Current status of the project is early development. Documentation, licensing information &co will be added later** + +## Configuration + +- `LOCAL_DOMAIN` should be the domain/hostname of your instance. This is **absolutely required** as it is used for generating unique IDs for everything federation-related +- `LOCAL_HTTPS` set it to `true` if HTTPS works on your website. This is used to generate canonical URLs, which is also important when generating and parsing federation-related IDs +- `HUB_URL` should be the URL of the PubsubHubbub service that your instance is going to use. By default it is the open service of Superfeedr diff --git a/app/services/process_interaction_service.rb b/app/services/process_interaction_service.rb index dd9e76956..b91cfcf66 100644 --- a/app/services/process_interaction_service.rb +++ b/app/services/process_interaction_service.rb @@ -1,35 +1,64 @@ class ProcessInteractionService + include ApplicationHelper + def call(envelope, target_account) body = salmon.unpack(envelope) xml = Nokogiri::XML(body) - return if !involves_target_account(xml, target_account) || xml.at_xpath('//xmlns:author/xmlns:name').nil? || xml.at_xpath('//xmlns:author/xmlns:uri').nil? + return unless involves_target_account?(xml, target_account) && contains_author?(xml) - username = xml.at_xpath('//xmlns:author/xmlns:name').content - url = xml.at_xpath('//xmlns:author/xmlns:uri').content + username = xml.at_xpath('/xmlns:entry/xmlns:author/xmlns:name').content + url = xml.at_xpath('/xmlns:entry/xmlns:author/xmlns:uri').content domain = Addressable::URI.parse(url).host account = Account.find_by(username: username, domain: domain) if account.nil? account = follow_remote_account_service.("acct:#{username}@#{domain}") + return if account.nil? end if salmon.verify(envelope, account.keypair) - verb = xml.at_path('//activity:verb').content - - case verb - when 'http://activitystrea.ms/schema/1.0/follow', 'follow' + case get_verb(xml) + when :follow account.follow!(target_account) - when 'http://activitystrea.ms/schema/1.0/unfollow', 'unfollow' + when :unfollow account.unfollow!(target_account) + when :favorite + # todo: a favourite + when :post + # todo: a reply + when :share + # todo: a reblog end end end private - def involves_target_account(target_account) - # todo + def contains_author?(xml) + !(xml.at_xpath('/xmlns:entry/xmlns:author/xmlns:name').nil? || xml.at_xpath('/xmlns:entry/xmlns:author/xmlns:uri').nil?) + end + + def involves_target_account?(xml, account) + targeted_at_account?(xml, account) || mentions_account?(xml, account) + end + + def targeted_at_account?(xml, account) + target_id = xml.at_xpath('/xmlns:entry/activity:object/xmlns:id') + !target_id.nil? && target_id.content == profile_url(name: account.username) + end + + def mentions_account?(xml, account) + xml.xpath('/xmlns:entry/xmlns:link[@rel="mentioned"]').each do |mention_link| + return true if mention_link.attribute('ref') == profile_url(name: account.username) + end + + false + end + + def get_verb(xml) + verb = xml.at_xpath('//activity:verb').content.gsub 'http://activitystrea.ms/schema/1.0/', '' + verb.to_sym end def salmon diff --git a/config/initializers/ostatus.rb b/config/initializers/ostatus.rb index 6f00ba7ed..624ea9ca0 100644 --- a/config/initializers/ostatus.rb +++ b/config/initializers/ostatus.rb @@ -1,6 +1,7 @@ -LOCAL_DOMAIN = ENV['LOCAL_DOMAIN'] || 'localhost' -HUB_URL = ENV['HUB_URL'] || 'https://pubsubhubbub.superfeedr.com' +LOCAL_DOMAIN = ENV['LOCAL_DOMAIN'] || 'localhost' +HUB_URL = ENV['HUB_URL'] || 'https://pubsubhubbub.superfeedr.com' +CANONICAL_PROTOCOL = ENV['LOCAL_HTTPS'] == 'true' ? 'https://' : 'http://' Rails.application.configure do - config.action_mailer.default_url_options = { host: LOCAL_DOMAIN } + config.action_mailer.default_url_options = { host: LOCAL_DOMAIN, protocol: CANONICAL_PROTOCOL } end