pubnub 3.6.10 → 3.7.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of pubnub might be problematic. Click here for more details.

Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.txt +3 -0
  3. data/Gemfile.lock +1 -1
  4. data/README.md +144 -10
  5. data/examples/demo_console.rb +61 -23
  6. data/fixtures/vcr_cassettes/cg/add-c-as-array.yml +51 -0
  7. data/fixtures/vcr_cassettes/cg/add-c-as-csv.yml +51 -0
  8. data/fixtures/vcr_cassettes/cg/add-c-as-string.yml +51 -0
  9. data/fixtures/vcr_cassettes/cg/add-c-as-symbol.yml +51 -0
  10. data/fixtures/vcr_cassettes/cg/audit-cg.yml +44 -0
  11. data/fixtures/vcr_cassettes/cg/audit-ns.yml +44 -0
  12. data/fixtures/vcr_cassettes/cg/grant-cg.yml +44 -0
  13. data/fixtures/vcr_cassettes/cg/grant-ns.yml +44 -0
  14. data/fixtures/vcr_cassettes/cg/here_now-cg.yml +51 -0
  15. data/fixtures/vcr_cassettes/cg/leave-cg-c.yml +132 -0
  16. data/fixtures/vcr_cassettes/cg/leave-cg.yml +133 -0
  17. data/fixtures/vcr_cassettes/cg/list-all-c-in-in-ns-cg.yml +50 -0
  18. data/fixtures/vcr_cassettes/cg/list-all-c-in-non-ns-cg.yml +51 -0
  19. data/fixtures/vcr_cassettes/cg/list-all-cg-in-ns.yml +51 -0
  20. data/fixtures/vcr_cassettes/cg/list-all-namespaces.yml +50 -0
  21. data/fixtures/vcr_cassettes/cg/list-all-non-namespaced-cg.yml +49 -0
  22. data/fixtures/vcr_cassettes/cg/remove-c-as-array.yml +51 -0
  23. data/fixtures/vcr_cassettes/cg/remove-c-as-csv.yml +51 -0
  24. data/fixtures/vcr_cassettes/cg/remove-c-as-string.yml +51 -0
  25. data/fixtures/vcr_cassettes/cg/remove-c-as-symbol.yml +51 -0
  26. data/fixtures/vcr_cassettes/cg/remove-cg-from-ns-csv.yml +51 -0
  27. data/fixtures/vcr_cassettes/cg/remove-ns-csv.yml +51 -0
  28. data/fixtures/vcr_cassettes/cg/subscribe-cg-and-channel.yml +85 -0
  29. data/fixtures/vcr_cassettes/cg/subscribe-cg-only.yml +85 -0
  30. data/lib/pubnub/client.rb +6 -2
  31. data/lib/pubnub/envelope.rb +1 -0
  32. data/lib/pubnub/event.rb +105 -20
  33. data/lib/pubnub/events/audit.rb +13 -0
  34. data/lib/pubnub/events/channel_registration.rb +132 -0
  35. data/lib/pubnub/events/grant.rb +17 -7
  36. data/lib/pubnub/events/heartbeat.rb +29 -3
  37. data/lib/pubnub/events/here_now.rb +21 -7
  38. data/lib/pubnub/events/leave.rb +27 -3
  39. data/lib/pubnub/events/presence.rb +4 -3
  40. data/lib/pubnub/events/set_state.rb +16 -3
  41. data/lib/pubnub/events/state.rb +15 -9
  42. data/lib/pubnub/events/subscribe.rb +17 -3
  43. data/lib/pubnub/formatter.rb +31 -7
  44. data/lib/pubnub/pam.rb +4 -3
  45. data/lib/pubnub/version.rb +1 -1
  46. data/spec/lib/integration/channel_groups_spec.rb +120 -0
  47. data/spec/lib/integration/channel_registration_spec.rb +317 -0
  48. data/spec/spec_helper.rb +0 -1
  49. metadata +31 -2
@@ -17,6 +17,19 @@ module Pubnub
17
17
  raise ArgumentError.new(:object => self, :message => 'publish_key is required by Audit') unless @publish_key
18
18
  raise ArgumentError.new(:object => self, :message => 'Parameter secret_key is required by Audit') if !@secret_key || @secret_key == 0
19
19
 
20
+ # check channel/channels
21
+ raise ArgumentError.new(:object => self, :message => 'SetState requires :channel, :channels or :group argument') if @channel.blank? && @channel_group.blank?
22
+ unless @channel.blank?
23
+ raise ArgumentError.new(:object => self, :message => 'Invalid channel(s) format! Should be type of: String, Symbol, or Array of both') unless valid_channel?
24
+ end
25
+
26
+ unless @channel_group.blank?
27
+ # check channel_group
28
+ raise ArgumentError.new(:object => self, :message => 'Invalid channel group format! Should be type of: String, Symbol') unless [String, Symbol, NilClass].include?(@channel_group.class)
29
+
30
+ # check channel_group
31
+ # raise ArgumentError.new(:object => self, :message => ':group argument has to be in format "ns:cg", "ns:" or ":cg"') if @channel_group.count(':') != 1
32
+ end
20
33
  end
21
34
 
22
35
  private
@@ -0,0 +1,132 @@
1
+ module Pubnub
2
+ class ChannelRegistration
3
+ include Pubnub::Event
4
+ include Pubnub::SingleEvent
5
+ include Pubnub::Formatter
6
+ include Pubnub::Validator
7
+
8
+ def initialize(options, app)
9
+ @group = options[:group]
10
+ @action = options[:action]
11
+ @cloak = options[:cloak]
12
+ super
13
+
14
+ @channel = nil if @channel.size == 1 && @channel.first.empty?
15
+ format_group if @group
16
+
17
+ @event = 'channel_registration'
18
+ end
19
+
20
+ private
21
+
22
+ def validate!
23
+ # Callback
24
+ raise ArgumentError.new(:object => self, :message => 'Callback parameter is required while using async channel_registration') if !@http_sync && @callback.blank?
25
+
26
+ # Channel group
27
+ if @channel_group.class == Array
28
+ @channel_group.each do |cg|
29
+ # raise ArgumentError.new(:object => self, :message => ':group argument has to be in format "ns:cg", "ns:" or ":cg"') if cg.count(':') != 1
30
+ end
31
+ elsif !@channel_group.blank?
32
+ number_of_groups = @channel_group.to_s.split(',').size # In case it will be given as csv
33
+ # raise ArgumentError.new(:object => self, :message => ':group argument has to be in format "ns:cg", "ns:" or ":cg"') if @channel_group.to_s.count(':') != number_of_groups
34
+ end
35
+ end
36
+
37
+ def format_group
38
+ if @group.to_s.count(':') > 0
39
+ @namespace_id, @group_id = @group.to_s.split(':')
40
+ else
41
+ @namespace_id = nil
42
+ @group_id = @group.to_s
43
+ end
44
+ end
45
+
46
+ def parameters(app)
47
+ parameters = super(app)
48
+ parameters.merge!({cloak: @cloak}) if @cloak
49
+ parameters.merge!({add: @channel.join(',')}) if @action == :add && !@channel.blank?
50
+ parameters.merge!({remove: @channel.join(',')}) if @action == :remove && !@channel.blank?
51
+ parameters
52
+ end
53
+
54
+ def path(app)
55
+ head = "/v1/channel-registration/sub-key/#{@subscribe_key}/"
56
+ body = ''
57
+ case @action
58
+ when :list_groups
59
+ body << [
60
+ 'channel-group'
61
+ ].join('/')
62
+ when :list_namespaces
63
+ body << [
64
+ 'namespace'
65
+ ].join('/')
66
+
67
+ when :get
68
+ body << [
69
+ ('namespace' unless @namespace_id.blank?),
70
+ @namespace_id,
71
+ 'channel-group',
72
+ @group_id
73
+ ].delete_if { |e| e.blank? }.join('/')
74
+
75
+ when :add
76
+ body << [
77
+ ('namespace' unless @namespace_id.blank?),
78
+ @namespace_id,
79
+ 'channel-group',
80
+ @group_id
81
+ ].delete_if { |e| e.blank? }.join('/')
82
+
83
+ when :remove
84
+ body << [
85
+ ('namespace' unless @namespace_id.blank?),
86
+ @namespace_id,
87
+ ('channel-group' unless @group_id.blank?),
88
+ @group_id,
89
+ ('remove' if @channel.blank?)
90
+ ].delete_if { |e| e.blank? }.join('/')
91
+
92
+ when :set_cloak
93
+ body << [
94
+ ('namespace' unless @namespace_id.blank?),
95
+ @namespace_id,
96
+ 'channel-group',
97
+ @group_id
98
+ ].delete_if { |e| e.blank? }.join('/')
99
+
100
+ else
101
+ fail ArgumentError.new(:object => self, :message => 'ChannelRegistration requires proper :action key'), 'ChannelRegistration requires proper :action key'
102
+ end
103
+
104
+ head + body
105
+ end
106
+
107
+
108
+ def format_envelopes(response, app, error)
109
+
110
+ parsed_response = Parser.parse_json(response.body) if Parser.valid_json?(response.body)
111
+
112
+ envelopes = Array.new
113
+ envelopes << Envelope.new({
114
+ :parsed_response => parsed_response,
115
+ :payload => (parsed_response['payload'] if parsed_response),
116
+ :service => (parsed_response['service'] if parsed_response),
117
+ :message => (parsed_response['message'] if parsed_response),
118
+ :status => (parsed_response['status'] if parsed_response),
119
+ :error => (parsed_response['error'] if parsed_response)
120
+ }, app)
121
+
122
+ envelopes = add_common_data_to_envelopes(envelopes, response, app, error)
123
+
124
+ envelopes
125
+
126
+ end
127
+
128
+ def encode_state(state)
129
+ URI.encode_www_form_component(state.to_json).gsub('+', '%20')
130
+ end
131
+ end
132
+ end
@@ -12,9 +12,7 @@ module Pubnub
12
12
  @allow_multiple_channels = true
13
13
  @timestamp = current_time
14
14
 
15
- @write = options[:write]
16
- @read = options[:read]
17
- @ttl = options[:ttl] || Pubnub::Configuration::DEFAULT_TTL
15
+ @ttl = options[:ttl] || Pubnub::Configuration::DEFAULT_TTL
18
16
  end
19
17
 
20
18
  def validate!
@@ -25,24 +23,37 @@ module Pubnub
25
23
 
26
24
  raise ArgumentError.new(:object => self, :message => 'write parameter accept only one of: 1, "1", 0, "0", true, false values') unless [nil, 1, '1', 0, '0', true, false].include?(@write)
27
25
  raise ArgumentError.new(:object => self, :message => 'read parameter accept only: 1, "1", 0, "0", true, false values') unless [nil, 1, '1', 0, '0', true, false].include?(@read)
26
+ raise ArgumentError.new(:object => self, :message => 'manage parameter accept only: 1, "1", 0, "0", true, false values') unless [nil, 1, '1', 0, '0', true, false].include?(@manage)
28
27
 
29
28
  raise ArgumentError.new(:object => self, :message => 'ttl parameter is too big, max value is: 525600') unless @ttl.to_i <= 525600 || @ttl.nil?
30
29
  raise ArgumentError.new(:object => self, :message => 'ttl parameter can\'t be negative') unless @ttl.to_i >= 0 || @ttl.nil?
31
30
 
31
+ # Channel group
32
+ if @channel_group.class == Array
33
+ @channel_group.each do |cg|
34
+ # raise ArgumentError.new(:object => self, :message => ':group argument has to be in format "ns:cg", "ns:" or ":cg"') if cg.count(':') != 1
35
+ end
36
+ elsif !@channel_group.blank?
37
+ number_of_groups = @channel_group.to_s.split(',').size # In case it will be given as csv
38
+ # raise ArgumentError.new(:object => self, :message => ':group argument has to be in format "ns:cg", "ns:" or ":cg"') if @channel_group.to_s.count(':') != number_of_groups
39
+ end
40
+
32
41
  end
33
42
 
34
43
  private
35
44
 
36
45
  def parameters(app, signature = false)
37
- write = [0, '0', false].include?(@write) ? 0 : 1
38
- read = [0, '0', false].include?(@read) ? 0 : 1
46
+ write = [0, '0', false].include?(@write) ? 0 : 1
47
+ read = [0, '0', false].include?(@read) ? 0 : 1
48
+ manage = [0, '0', false].include?(@manage) ? 0 : 1 unless @channel_group.blank?
39
49
 
40
50
  {
41
51
  :timestamp => @timestamp,
42
52
  :w => write,
43
53
  :r => read,
54
+ :m => manage,
44
55
  :ttl => @ttl
45
- }.merge(super(app, signature))
56
+ }.delete_if {|k, v| v.nil? }.merge(super(app, signature))
46
57
  end
47
58
 
48
59
  def path(app)
@@ -54,6 +65,5 @@ module Pubnub
54
65
  @subscribe_key
55
66
  ].join('/')
56
67
  end
57
-
58
68
  end
59
69
  end
@@ -18,22 +18,48 @@ module Pubnub
18
18
 
19
19
  private
20
20
 
21
+ def validate!
22
+ super
23
+ # Check channels
24
+ raise ArgumentError.new(:object => self, :message => 'Heartbeat requires :channel, :channels or :group argument') if @channel.blank? && @channel_group.blank?
25
+
26
+ # Check callback
27
+ raise ArgumentError.new(:object => self, :message => 'Callback parameter is required while using async heartbeat') if !@http_sync && @callback.blank?
28
+
29
+ # Channel group
30
+ # if @channel_group.class == Array
31
+ # @channel_group.each do |cg|
32
+ # raise ArgumentError.new(:object => self, :message => ':group argument has to be in format "ns:cg", "ns:" or ":cg"') if cg.count(':') != 1
33
+ # end
34
+ # elsif !@channel_group.blank?
35
+ # number_of_groups = @channel_group.to_s.split(',').size # In case it will be given as csv
36
+ # raise ArgumentError.new(:object => self, :message => ':group argument has to be in format "ns:cg", "ns:" or ":cg"') if @channel_group.to_s.count(':') != number_of_groups
37
+ # end
38
+ end
39
+
21
40
  def path(app)
41
+ if @channel == [''] || @channel.blank?
42
+ channel = [',']
43
+ else
44
+ channel = @channel
45
+ end
46
+
22
47
  '/' + [
23
48
  'v2',
24
49
  'presence',
25
50
  'sub-key',
26
51
  @subscribe_key,
27
52
  'channel',
28
- @channel.join(','),
53
+ channel.join(','),
29
54
  'heartbeat'
30
55
  ].join('/')
31
56
  end
32
57
 
33
58
  def parameters(app)
34
59
  parameters = super(app)
35
- parameters.merge!({:state => encode_state(app.env[:state][@origin])}) if app.env[:state] && app.env[:state][@origin]
36
- parameters.merge!({:heartbeat => app.env[:heartbeat]}) if app.env[:heartbeat]
60
+ parameters.merge!({:state => encode_state(app.env[:state][@origin])}) if app.env[:state] && app.env[:state][@origin]
61
+ parameters.merge!({:heartbeat => app.env[:heartbeat]}) if app.env[:heartbeat]
62
+ parameters.merge!({'channel-group' => format_channel_group(@channel_group, true).join(',')}) unless @channel_group.blank?
37
63
  parameters
38
64
  end
39
65
 
@@ -16,8 +16,15 @@ module Pubnub
16
16
  super
17
17
 
18
18
  # check channel
19
- raise ArgumentError.new(:object => self, :message => 'Invalid channel format! Should be type of: String, Symbol') unless [String, Symbol, NilClass].include?(@channel.class)
19
+ raise ArgumentError.new(:object => self, :message => 'Invalid channel format! Should be type of: String, Symbol') unless [String, Symbol, NilClass].include?(@channel.class)
20
20
 
21
+ unless @channel_group.blank?
22
+ # check channel_group
23
+ raise ArgumentError.new(:object => self, :message => 'Invalid channel group format! Should be type of: String, Symbol') unless [String, Symbol, NilClass].include?(@channel_group.class)
24
+
25
+ # check channel_group
26
+ # raise ArgumentError.new(:object => self, :message => ':group argument has to be in format "ns:cg", "ns:" or ":cg"') if @channel_group.count(':') != 1
27
+ end
21
28
  end
22
29
 
23
30
  private
@@ -38,11 +45,19 @@ module Pubnub
38
45
  'v2',
39
46
  'presence',
40
47
  'sub-key',
41
- @subscribe_key
48
+ @subscribe_key,
49
+ ('channel' if @channel_group),
50
+ (',' if @channel_group)
42
51
  ].join('/')
43
52
  end
44
53
  end
45
54
 
55
+ def parameters(app)
56
+ parameters = super(app)
57
+ parameters.merge!({'channel-group' => format_channel_group(@channel_group, false).join(',')}) unless @channel_group.blank?
58
+ parameters
59
+ end
60
+
46
61
  def format_envelopes(response, app, error)
47
62
  parsed_response = Parser.parse_json(response.body) if Parser.valid_json?(response.body)
48
63
 
@@ -50,11 +65,10 @@ module Pubnub
50
65
  envelopes << Envelope.new(
51
66
  {
52
67
  :parsed_response => parsed_response,
53
- :occupancy => (parsed_response['occupancy'] if parsed_response),
54
- :service => (parsed_response['service'] if parsed_response),
55
- :message => (parsed_response['message'] if parsed_response),
56
- :uuid => (parsed_response['uuids'] if parsed_response),
57
- :status => (parsed_response['status'] if parsed_response)
68
+ :payload => (parsed_response['payload'] if parsed_response),
69
+ :service => (parsed_response['service'] if parsed_response),
70
+ :message => (parsed_response['message'] if parsed_response),
71
+ :status => (parsed_response['status'] if parsed_response)
58
72
  },
59
73
  app
60
74
  )
@@ -19,8 +19,8 @@ module Pubnub
19
19
  super
20
20
 
21
21
  # check channel
22
- raise ArgumentError.new(:object => self, :message => 'Leave requires :channel argument') unless @channel
23
- raise ArgumentError.new(:object => self, :message => 'Invalid channel format! Should be type of: String, Symbol, or Array of both') unless valid_channel?
22
+ # raise ArgumentError.new(:object => self, :message => 'Leave requires :channel argument') unless @channel
23
+ # raise ArgumentError.new(:object => self, :message => 'Invalid channel format! Should be type of: String, Symbol, or Array of both') unless valid_channel?
24
24
  end
25
25
 
26
26
  def fire(app)
@@ -35,12 +35,24 @@ module Pubnub
35
35
  $logger.debug('Pubnub'){"#{app.env[:subscriptions][@origin].get_channels.to_s}.include? #{channel}"}
36
36
  raise ArgumentError.new(:object => self, :message => 'You cannot leave channel that is not subscribed') unless app.env[:subscriptions][@origin].get_channels.include?(channel)
37
37
  end
38
+
39
+ @channel_group.each do |channel_group|
40
+ $logger.debug('Pubnub'){"#{app.env[:subscriptions][@origin].get_channel_groups.to_s}.include? #{channel_group}"}
41
+ raise ArgumentError.new(:object => self, :message => 'You cannot leave channel group that is not subscribed') unless app.env[:subscriptions][@origin].get_channel_groups.include?(channel_group)
42
+ end
38
43
  end unless @force
44
+
39
45
  @channel.each do |channel|
40
46
  app.env[:subscriptions][@origin].remove_channel(channel, app) if app.env[:subscriptions][@origin]
41
47
  @left = true
42
48
  end unless @skip_remove
49
+
50
+ @channel_group.each do |channel_group|
51
+ app.env[:subscriptions][@origin].remove_channel_group(channel_group, app) if app.env[:subscriptions][@origin]
52
+ @left = true
53
+ end unless @skip_remove
43
54
  end
55
+
44
56
  envelopes = super
45
57
  app.start_subscribe
46
58
  envelopes
@@ -48,14 +60,26 @@ module Pubnub
48
60
 
49
61
  private
50
62
 
63
+ def parameters(app)
64
+ params = super(app)
65
+ params.merge!({ 'channel-group' => @channel_group.join(',') }) unless @channel_group.blank?
66
+ params
67
+ end
68
+
51
69
  def path(app)
70
+ if @channel == [''] || @channel.blank?
71
+ channel = [',']
72
+ else
73
+ channel = @channel
74
+ end
75
+
52
76
  '/' + [
53
77
  'v2',
54
78
  'presence',
55
79
  'sub-key',
56
80
  @subscribe_key,
57
81
  'channel',
58
- @channel.join(','),
82
+ channel.join(','),
59
83
  'leave'
60
84
  ].join('/')
61
85
  end
@@ -8,7 +8,8 @@ module Pubnub
8
8
 
9
9
  def initialize(options, app)
10
10
  super
11
- @channel = @channel.map {|c| c + '-pnpres'}
11
+ @channel = @channel.map {|c| c + '-pnpres'}
12
+ @channel_group = @channel_group.map {|c| c + '-pnpres'}
12
13
  @event = 'presence'
13
14
  @allow_multiple_channels = true
14
15
 
@@ -23,8 +24,8 @@ module Pubnub
23
24
  super
24
25
 
25
26
  # Check channels
26
- raise ArgumentError.new(:object => self, :message => 'Presence requires :channel or :channels argument') unless @channel
27
- raise ArgumentError.new(:object => self, :message => 'Invalid channel(s) format! Should be type of: String, Symbol, or Array of both') unless valid_channel?
27
+ # raise ArgumentError.new(:object => self, :message => 'Presence requires :channel, :channels or :channel_group argument') unless @channel || @channel_group
28
+ # raise ArgumentError.new(:object => self, :message => 'Invalid channel(s) format! Should be type of: String, Symbol, or Array of both') unless valid_channel?
28
29
 
29
30
  end
30
31
 
@@ -15,6 +15,10 @@ module Pubnub
15
15
  app.env[:state][@origin][channel.to_s] = @state
16
16
  end
17
17
 
18
+ @channel_group.each do |channel|
19
+ app.env[:state][@origin][channel.to_s] = @state
20
+ end
21
+
18
22
  @allow_multiple_channels = true
19
23
  @event = 'set_state'
20
24
  end
@@ -25,15 +29,24 @@ module Pubnub
25
29
  raise 'You can set state only as hash' unless (@state.is_a?(Hash) || @state.is_a?(NilClass))
26
30
 
27
31
  # check channel/channels
28
- raise ArgumentError.new(:object => self, :message => 'SetState requires :channel or :channels argument') unless @channel
32
+ raise ArgumentError.new(:object => self, :message => 'SetState requires :channel, :channels or :group argument') if @channel.blank? && @channel_group.blank?
29
33
  raise ArgumentError.new(:object => self, :message => 'Invalid channel(s) format! Should be type of: String, Symbol, or Array of both') unless valid_channel?
34
+
35
+ unless @channel_group.blank?
36
+ # check channel_group
37
+ raise ArgumentError.new(:object => self, :message => 'Invalid channel group format! Should be type of: String, Symbol') unless [String, Symbol, NilClass].include?(@channel_group.class)
38
+
39
+ # check channel_group
40
+ # raise ArgumentError.new(:object => self, :message => ':group argument has to be in format "ns:cg", "ns:" or ":cg"') if @channel_group.count(':') != 1
41
+ end
30
42
  end
31
43
 
32
44
  private
33
45
 
34
46
  def parameters(app)
35
47
  parameters = super(app)
36
- parameters.merge!({:state => encode_state(@state)})
48
+ parameters.merge!({ :state => encode_state(@state)})
49
+ parameters.merge!({ 'channel-group' => format_channel_group(@channel_group).join(',') }) unless @channel_group.blank?
37
50
  parameters
38
51
  end
39
52
 
@@ -44,7 +57,7 @@ module Pubnub
44
57
  'sub-key',
45
58
  @subscribe_key,
46
59
  'channel',
47
- @channel,
60
+ channels_for_url(@channel),
48
61
  'uuid',
49
62
  app.env[:uuid],
50
63
  'data'