ostatus2 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/README.md +1 -3
 - data/lib/ostatus2/publication.rb +23 -0
 - data/lib/ostatus2/salmon.rb +85 -0
 - data/lib/ostatus2/subscription.rb +62 -0
 - data/lib/ostatus2/version.rb +3 -0
 - data/lib/ostatus2.rb +18 -0
 - metadata +11 -6
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 53864441f9a3c0a536a52f316390630d8982ccbf
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: c8699fed6438b98e12c82075c3aecdd3ca98bf6c
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 0f5b426461d8508c31d82fc40253eddaaf06d45ed848324edfdc96186d28b71b2dd1bb6a62973659bbfbd5fa613698fce6a04f9336159d4733f74037e3ecfca1
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 488bd014fe2b8d546e28e191eb48a07a3b9805e1e81020f958bfbebef21eded45fb654d3d205d941b38f93cde60155ff73051f8a0288d0b97ba85037a728cdee
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -1,5 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            OStatus2
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
      
 2 
     | 
    
         
            +
            ==========
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            [][gem]
         
     | 
| 
       5 
5 
     | 
    
         
             
            [][travis]
         
     | 
| 
         @@ -14,8 +14,6 @@ A Ruby toolset for interacting with the OStatus suite of protocols: 
     | 
|
| 
       14 
14 
     | 
    
         
             
            * Subscribing to and publishing feeds via PubSubHubbub
         
     | 
| 
       15 
15 
     | 
    
         
             
            * Interacting with feeds via Salmon
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
       17 
     | 
    
         
            -
            The 2 in the name is not a reference to any protocol version. There used to be a different Ruby gem called "ostatus" which this one seeks to replace.
         
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
17 
     | 
    
         
             
            ## Installation
         
     | 
| 
       20 
18 
     | 
    
         | 
| 
       21 
19 
     | 
    
         
             
                gem install ostatus2
         
     | 
| 
         @@ -0,0 +1,23 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module OStatus2
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Publication
         
     | 
| 
      
 3 
     | 
    
         
            +
                # @param [String] url Topic URL
         
     | 
| 
      
 4 
     | 
    
         
            +
                # @param [Array] hubs URLs of the hubs which should be notified about the update
         
     | 
| 
      
 5 
     | 
    
         
            +
                def initialize(url, hubs = [])
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @url  = url
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @hubs = hubs.map { |hub_url| Addressable::URI.parse(hub_url) }
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                # Notifies hubs about the update to the topic URL
         
     | 
| 
      
 11 
     | 
    
         
            +
                # @raise [HTTP::Error] Error raised upon delivery failure
         
     | 
| 
      
 12 
     | 
    
         
            +
                # @raise [OpenSSL::SSL::SSLError] Error raised upon SSL-related failure during delivery
         
     | 
| 
      
 13 
     | 
    
         
            +
                def publish
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @hubs.each { |hub| http_client.post(hub, form: { 'hub.mode' => 'publish', 'hub.url' => @url }) }
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                private
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                def http_client
         
     | 
| 
      
 20 
     | 
    
         
            +
                  HTTP
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,85 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module OStatus2
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Salmon
         
     | 
| 
      
 3 
     | 
    
         
            +
                XMLNS = 'http://salmon-protocol.org/ns/magic-env'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                # Create a magical envelope XML document around the original body
         
     | 
| 
      
 6 
     | 
    
         
            +
                # and sign it with a private key
         
     | 
| 
      
 7 
     | 
    
         
            +
                # @param [String] body
         
     | 
| 
      
 8 
     | 
    
         
            +
                # @param [OpenSSL::PKey::RSA] key The private part of the key will be used
         
     | 
| 
      
 9 
     | 
    
         
            +
                # @return [String] Magical envelope XML
         
     | 
| 
      
 10 
     | 
    
         
            +
                def pack(body, key)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  signed    = plaintext_signature(body, 'application/atom+xml', 'base64url', 'RSA-SHA256')
         
     | 
| 
      
 12 
     | 
    
         
            +
                  signature = Base64.urlsafe_encode64(key.sign(digest, signed))
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  Nokogiri::XML::Builder.new do |xml|
         
     | 
| 
      
 15 
     | 
    
         
            +
                    xml['me'].env({ 'xmlns:me' => XMLNS }) do
         
     | 
| 
      
 16 
     | 
    
         
            +
                      xml['me'].data({ type: 'application/atom+xml' }, Base64.urlsafe_encode64(body))
         
     | 
| 
      
 17 
     | 
    
         
            +
                      xml['me'].encoding('base64url')
         
     | 
| 
      
 18 
     | 
    
         
            +
                      xml['me'].alg('RSA-SHA256')
         
     | 
| 
      
 19 
     | 
    
         
            +
                      xml['me'].sig({ key_id: Base64.urlsafe_encode64(key.public_key.to_s) }, signature)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    end
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end.to_xml
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                # Deliver the magical envelope to a Salmon endpoint
         
     | 
| 
      
 25 
     | 
    
         
            +
                # @param [String] salmon_url Salmon endpoint URL
         
     | 
| 
      
 26 
     | 
    
         
            +
                # @param [String] envelope Magical envelope
         
     | 
| 
      
 27 
     | 
    
         
            +
                # @raise [HTTP::Error] Error raised upon delivery failure
         
     | 
| 
      
 28 
     | 
    
         
            +
                # @raise [OpenSSL::SSL::SSLError] Error raised upon SSL-related failure during delivery
         
     | 
| 
      
 29 
     | 
    
         
            +
                # @return [HTTP::Response]
         
     | 
| 
      
 30 
     | 
    
         
            +
                def post(salmon_url, envelope)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  http_client.headers(HTTP::Headers::CONTENT_TYPE => 'application/magic-envelope+xml').post(Addressable::URI.parse(salmon_url), body: envelope)
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                # Unpack a magical envelope to get the content inside
         
     | 
| 
      
 35 
     | 
    
         
            +
                # @param [String] raw_body Magical envelope
         
     | 
| 
      
 36 
     | 
    
         
            +
                # @raise [OStatus2::BadSalmonError] Error raised if the envelope is malformed
         
     | 
| 
      
 37 
     | 
    
         
            +
                # @return [String] Content inside the envelope
         
     | 
| 
      
 38 
     | 
    
         
            +
                def unpack(raw_body)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  body, _, _ = parse(raw_body)
         
     | 
| 
      
 40 
     | 
    
         
            +
                  body
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                # Verify the magical envelope's integrity
         
     | 
| 
      
 44 
     | 
    
         
            +
                # @param [String] raw_body Magical envelope
         
     | 
| 
      
 45 
     | 
    
         
            +
                # @param [OpenSSL::PKey::RSA] key The public part of the key will be used
         
     | 
| 
      
 46 
     | 
    
         
            +
                # @return [Boolean]
         
     | 
| 
      
 47 
     | 
    
         
            +
                def verify(raw_body, key)
         
     | 
| 
      
 48 
     | 
    
         
            +
                  _, plaintext, signature = parse(raw_body)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  key.public_key.verify(digest, signature, plaintext)
         
     | 
| 
      
 50 
     | 
    
         
            +
                rescue OStatus2::BadSalmonError
         
     | 
| 
      
 51 
     | 
    
         
            +
                  false
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                private
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                def http_client
         
     | 
| 
      
 57 
     | 
    
         
            +
                  HTTP
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                def digest
         
     | 
| 
      
 61 
     | 
    
         
            +
                  OpenSSL::Digest::SHA256.new
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                def parse(raw_body)
         
     | 
| 
      
 65 
     | 
    
         
            +
                  xml = Nokogiri::XML(raw_body)
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                  raise OStatus2::BadSalmonError if xml.at_xpath('//me:data').nil? || xml.at_xpath('//me:data').attribute('type').nil? || xml.at_xpath('//me:sig').nil? || xml.at_xpath('//me:encoding').nil? || xml.at_xpath('//me:alg').nil?
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                  data      = xml.at_xpath('//me:data')
         
     | 
| 
      
 70 
     | 
    
         
            +
                  type      = data.attribute('type').value
         
     | 
| 
      
 71 
     | 
    
         
            +
                  body      = Base64::urlsafe_decode64(data.content)
         
     | 
| 
      
 72 
     | 
    
         
            +
                  sig       = xml.at_xpath('//me:sig')
         
     | 
| 
      
 73 
     | 
    
         
            +
                  signature = Base64::urlsafe_decode64(sig.content)
         
     | 
| 
      
 74 
     | 
    
         
            +
                  encoding  = xml.at_xpath('//me:encoding').content
         
     | 
| 
      
 75 
     | 
    
         
            +
                  alg       = xml.at_xpath('//me:alg').content
         
     | 
| 
      
 76 
     | 
    
         
            +
                  plaintext = plaintext_signature(body, type, encoding, alg)
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                  [body, plaintext, signature]
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                def plaintext_signature(data, type, encoding, alg)
         
     | 
| 
      
 82 
     | 
    
         
            +
                  [data, type, encoding, alg].map { |i| Base64.urlsafe_encode64(i) }.join('.')
         
     | 
| 
      
 83 
     | 
    
         
            +
                end
         
     | 
| 
      
 84 
     | 
    
         
            +
              end
         
     | 
| 
      
 85 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,62 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module OStatus2
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Subscription
         
     | 
| 
      
 3 
     | 
    
         
            +
                # @param [String] topic_url The URL of the topic of the subscription
         
     | 
| 
      
 4 
     | 
    
         
            +
                # @param [Hash] options
         
     | 
| 
      
 5 
     | 
    
         
            +
                # @option options [String] :webhook Webhook URL
         
     | 
| 
      
 6 
     | 
    
         
            +
                # @option options [String] :hub Hub URL to work with
         
     | 
| 
      
 7 
     | 
    
         
            +
                # @option options [String] :secret Secret key of the subscription
         
     | 
| 
      
 8 
     | 
    
         
            +
                # @option options [String] :token Verification token of the subscription
         
     | 
| 
      
 9 
     | 
    
         
            +
                def initialize(topic_url, options = {})
         
     | 
| 
      
 10 
     | 
    
         
            +
                  @topic_url   = topic_url
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @webhook_url = options[:webhook] || ''
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @secret      = options[:secret]  || ''
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @token       = options[:token]   || ''
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @hub         = options[:hub]     || ''
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                # Subscribe to the topic via a specified hub
         
     | 
| 
      
 18 
     | 
    
         
            +
                # @raise [HTTP::Error] Error raised upon delivery failure
         
     | 
| 
      
 19 
     | 
    
         
            +
                # @raise [OpenSSL::SSL::SSLError] Error raised upon SSL-related failure during delivery
         
     | 
| 
      
 20 
     | 
    
         
            +
                # @return [Boolean]
         
     | 
| 
      
 21 
     | 
    
         
            +
                def subscribe
         
     | 
| 
      
 22 
     | 
    
         
            +
                  update_subscription(:subscribe)
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                # Unsubscribe from the topic via a specified hub
         
     | 
| 
      
 26 
     | 
    
         
            +
                # @raise [HTTP::Error] Error raised upon delivery failure
         
     | 
| 
      
 27 
     | 
    
         
            +
                # @raise [OpenSSL::SSL::SSLError] Error raised upon SSL-related failure during delivery
         
     | 
| 
      
 28 
     | 
    
         
            +
                # @return [Boolean]
         
     | 
| 
      
 29 
     | 
    
         
            +
                def unsubscribe
         
     | 
| 
      
 30 
     | 
    
         
            +
                  update_subscription(:unsubscribe)
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                # Check if the hub is responding to the right subscription request
         
     | 
| 
      
 34 
     | 
    
         
            +
                # @param [String] topic_url A hub.topic from the hub
         
     | 
| 
      
 35 
     | 
    
         
            +
                # @param [String] token A hub.verify_token from the hub
         
     | 
| 
      
 36 
     | 
    
         
            +
                # @return [Boolean]
         
     | 
| 
      
 37 
     | 
    
         
            +
                def valid?(topic_url, token)
         
     | 
| 
      
 38 
     | 
    
         
            +
                  @topic_url == topic_url && @token == token
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                # Verify that the feed contents were meant for this subscription
         
     | 
| 
      
 42 
     | 
    
         
            +
                # @param [String] content
         
     | 
| 
      
 43 
     | 
    
         
            +
                # @param [String] signature
         
     | 
| 
      
 44 
     | 
    
         
            +
                # @return [Boolean]
         
     | 
| 
      
 45 
     | 
    
         
            +
                def verify(content, signature)
         
     | 
| 
      
 46 
     | 
    
         
            +
                  hmac = OpenSSL::HMAC.hexdigest('sha1', @secret, content)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  signature == "sha1=#{hmac}"
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                private
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                def update_subscription(mode)
         
     | 
| 
      
 53 
     | 
    
         
            +
                  hub_url  = Addressable::URI.parse(@hub)
         
     | 
| 
      
 54 
     | 
    
         
            +
                  response = http_client.post(hub_url, form: { 'hub.mode' => mode.to_s, 'hub.callback' => @webhook_url, 'hub.verify' => 'async', 'hub.verify_token' => @token, 'hub.lease_seconds' => '', 'hub.secret' => @secret, 'hub.topic' => @topic_url })
         
     | 
| 
      
 55 
     | 
    
         
            +
                  response.code == 200
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                def http_client
         
     | 
| 
      
 59 
     | 
    
         
            +
                  HTTP
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
              end
         
     | 
| 
      
 62 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/ostatus2.rb
    ADDED
    
    | 
         @@ -0,0 +1,18 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'base64'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'openssl'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'http'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'addressable'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'nokogiri'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            require 'ostatus2/version'
         
     | 
| 
      
 8 
     | 
    
         
            +
            require 'ostatus2/publication'
         
     | 
| 
      
 9 
     | 
    
         
            +
            require 'ostatus2/subscription'
         
     | 
| 
      
 10 
     | 
    
         
            +
            require 'ostatus2/salmon'
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            module OStatus2
         
     | 
| 
      
 13 
     | 
    
         
            +
              class Error < StandardError
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              class BadSalmonError < Error
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: ostatus2
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0.1. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.1.1
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Eugen Rochko
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2016-02- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2016-02-20 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: http
         
     | 
| 
         @@ -58,15 +58,15 @@ dependencies: 
     | 
|
| 
       58 
58 
     | 
    
         
             
                requirements:
         
     | 
| 
       59 
59 
     | 
    
         
             
                - - "~>"
         
     | 
| 
       60 
60 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       61 
     | 
    
         
            -
                    version: '1. 
     | 
| 
      
 61 
     | 
    
         
            +
                    version: '1.3'
         
     | 
| 
       62 
62 
     | 
    
         
             
              type: :development
         
     | 
| 
       63 
63 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       64 
64 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       65 
65 
     | 
    
         
             
                requirements:
         
     | 
| 
       66 
66 
     | 
    
         
             
                - - "~>"
         
     | 
| 
       67 
67 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       68 
     | 
    
         
            -
                    version: '1. 
     | 
| 
       69 
     | 
    
         
            -
            description: Toolset for interacting with the  
     | 
| 
      
 68 
     | 
    
         
            +
                    version: '1.3'
         
     | 
| 
      
 69 
     | 
    
         
            +
            description: Toolset for interacting with the OStatus2 suite of protocols
         
     | 
| 
       70 
70 
     | 
    
         
             
            email:
         
     | 
| 
       71 
71 
     | 
    
         
             
            - eugen@zeonfederated.com
         
     | 
| 
       72 
72 
     | 
    
         
             
            executables: []
         
     | 
| 
         @@ -74,6 +74,11 @@ extensions: [] 
     | 
|
| 
       74 
74 
     | 
    
         
             
            extra_rdoc_files: []
         
     | 
| 
       75 
75 
     | 
    
         
             
            files:
         
     | 
| 
       76 
76 
     | 
    
         
             
            - README.md
         
     | 
| 
      
 77 
     | 
    
         
            +
            - lib/ostatus2.rb
         
     | 
| 
      
 78 
     | 
    
         
            +
            - lib/ostatus2/publication.rb
         
     | 
| 
      
 79 
     | 
    
         
            +
            - lib/ostatus2/salmon.rb
         
     | 
| 
      
 80 
     | 
    
         
            +
            - lib/ostatus2/subscription.rb
         
     | 
| 
      
 81 
     | 
    
         
            +
            - lib/ostatus2/version.rb
         
     | 
| 
       77 
82 
     | 
    
         
             
            homepage: https://github.com/Gargron/ostatus2
         
     | 
| 
       78 
83 
     | 
    
         
             
            licenses:
         
     | 
| 
       79 
84 
     | 
    
         
             
            - MIT
         
     | 
| 
         @@ -97,6 +102,6 @@ rubyforge_project: 
     | 
|
| 
       97 
102 
     | 
    
         
             
            rubygems_version: 2.4.6
         
     | 
| 
       98 
103 
     | 
    
         
             
            signing_key: 
         
     | 
| 
       99 
104 
     | 
    
         
             
            specification_version: 4
         
     | 
| 
       100 
     | 
    
         
            -
            summary: Toolset for interacting with the  
     | 
| 
      
 105 
     | 
    
         
            +
            summary: Toolset for interacting with the OStatus2 suite of protocols
         
     | 
| 
       101 
106 
     | 
    
         
             
            test_files: []
         
     | 
| 
       102 
107 
     | 
    
         
             
            has_rdoc: 
         
     |