pyapns2 1.0.0
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.
- data/lib/pyapns2/version.rb +3 -0
- data/lib/pyapns2.rb +134 -0
- metadata +147 -0
data/lib/pyapns2.rb
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'xml/libxml/xmlrpc'
|
3
|
+
|
4
|
+
class Pyapns2
|
5
|
+
|
6
|
+
require 'pyapns2/version'
|
7
|
+
|
8
|
+
class Error < StandardError; end
|
9
|
+
|
10
|
+
attr_reader :host, :port
|
11
|
+
|
12
|
+
class ProvisionedClient
|
13
|
+
|
14
|
+
attr_reader :client, :app_id
|
15
|
+
|
16
|
+
def initialize(client, app_id)
|
17
|
+
@client = client
|
18
|
+
@app_id = app_id
|
19
|
+
end
|
20
|
+
|
21
|
+
# See Pyapns2::Client#notify, with the exception this version prefills in the app_id.
|
22
|
+
def notify(token, notification = nil)
|
23
|
+
client.notify app_id, token, notification
|
24
|
+
end
|
25
|
+
|
26
|
+
# See Pyapns2::Client#feedback, with the exception this version prefills in the app_id.
|
27
|
+
def feedback
|
28
|
+
client.feedback app_id
|
29
|
+
end
|
30
|
+
|
31
|
+
def inspect
|
32
|
+
"#<#{self.class.name} server=#{host}:#{port}, app_id=#{app_id}>"
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns a pre-provisioned client that also automatically prepends
|
38
|
+
# the app_id automatically to all api calls, making giving a simpler interface.
|
39
|
+
def self.provision(options = {})
|
40
|
+
host, port = options.delete(:host), options.delete(:port)
|
41
|
+
host ||= "localhost"
|
42
|
+
port ||= 7077
|
43
|
+
client = new(host, port)
|
44
|
+
client.provision(options)
|
45
|
+
ProvisionedClient.new client, options[:app_id]
|
46
|
+
end
|
47
|
+
|
48
|
+
def initialize(host = 'localhost', port = 7077)
|
49
|
+
raise ArgumentError, "host must be a string" unless host.is_a?(String)
|
50
|
+
raise ArgumentError, "port must be a number" unless port.is_a?(Numeric)
|
51
|
+
@host = host
|
52
|
+
@port = port
|
53
|
+
@http = Net::HTTP.new host, port
|
54
|
+
@xmlrpc = XML::XMLRPC::Client.new @http, "/"
|
55
|
+
end
|
56
|
+
|
57
|
+
def inspect
|
58
|
+
"#<#{self.class.name} server=#{host}:#{port}>"
|
59
|
+
end
|
60
|
+
|
61
|
+
# Given a hash of options, calls provision on the pyapns server. This
|
62
|
+
# expects the following options and will raise an ArgumentError if they're
|
63
|
+
# not given:
|
64
|
+
#
|
65
|
+
# :app_id - A String name for your application
|
66
|
+
# :timeout - A number (e.g. 15) for how long to time out after when connecting to the apn server
|
67
|
+
# :env / :environment - One of production or sandbox. The type of server to connect to.
|
68
|
+
# :cert - Either a path to the certificate file or the certificate contents as a string.
|
69
|
+
def provision(options)
|
70
|
+
options[:environment] = options.delete(:env) if options.has_key?(:env)
|
71
|
+
app_id = options[:app_id]
|
72
|
+
timeout = options[:timeout]
|
73
|
+
cert = options[:cert]
|
74
|
+
env = options[:environment]
|
75
|
+
raise ArgumentError, ":app_id must be a string" unless app_id.is_a?(String) && !app_id.strip.empty?
|
76
|
+
raise ArgumentError, ":cert must be a string" unless cert.is_a?(String) && !cert.strip.empty?
|
77
|
+
raise ArgumentError, ":environment (or :env) must be one of sandbox or production" unless %w(production sandbox).include?(env)
|
78
|
+
raise ArgumentError, ":timeout must be a valid integer" unless timeout.is_a?(Numeric) && timeout >= 0
|
79
|
+
@xmlrpc.call 'provision', app_id, cert, env, timeout
|
80
|
+
true
|
81
|
+
rescue LibXML::XML::XMLRPC::RemoteCallError => e
|
82
|
+
raise Error.new e.message
|
83
|
+
end
|
84
|
+
|
85
|
+
# The main notification endpoint. Takes the app_id as the first argument, and then one
|
86
|
+
# of three sets of notification data:
|
87
|
+
#
|
88
|
+
# 1. A single token (as a string) and notification (as a dictionary)
|
89
|
+
# 2. A hash of token to notifications.
|
90
|
+
# 3. An array of tokens mapping to an array of notifications.
|
91
|
+
#
|
92
|
+
# Under the hook, it will automatically convert it to the most appropriate form before continuing.
|
93
|
+
# Will raise ArgumentError if you attempt to pass in bad information.
|
94
|
+
def notify(app_id, token, notification = nil)
|
95
|
+
if token.is_a?(Hash)
|
96
|
+
token, notification = extra_notification_info_from_hash token
|
97
|
+
end
|
98
|
+
raise ArgumentError, "Please ensure you provide an app_id" unless app_id
|
99
|
+
raise ArgumentError, "Please ensure you provide a single notification or an array of notifications" unless typed_item_of(notification, Hash)
|
100
|
+
raise ArgumentError, "Please ensure you provide device tokens or a string of tokens" unless typed_item_of(token, String)
|
101
|
+
types = [notification.is_a?(Array), token.is_a?(Array)]
|
102
|
+
if types.any? && !types.all?
|
103
|
+
raise ArgumentError, "The notifications and the strings must both be arrays if one is."
|
104
|
+
end
|
105
|
+
@xmlrpc.call 'notify', app_id, token, notification
|
106
|
+
true
|
107
|
+
rescue LibXML::XML::XMLRPC::RemoteCallError => e
|
108
|
+
raise Error.new e.message
|
109
|
+
end
|
110
|
+
|
111
|
+
# Takes an app id and returns the list of feedback from pyapns.
|
112
|
+
def feedback(app_id)
|
113
|
+
raise ArgumentError, "app_id must be provided" unless app_id
|
114
|
+
@xmlrpc.call('feedback', app_id).params
|
115
|
+
rescue LibXML::XML::XMLRPC::RemoteCallError => e
|
116
|
+
raise Error.new e.message
|
117
|
+
end
|
118
|
+
|
119
|
+
private
|
120
|
+
|
121
|
+
def extra_notification_info_from_hash(hash)
|
122
|
+
tokens, notifications = [], []
|
123
|
+
hash.each_pair do |k,v|
|
124
|
+
tokens << k
|
125
|
+
notifications << v
|
126
|
+
end
|
127
|
+
return tokens, notifications
|
128
|
+
end
|
129
|
+
|
130
|
+
def typed_item_of(value, klass)
|
131
|
+
value.is_a?(klass) || (value.is_a?(Array) && value.all? { |v| v.is_a?(klass) })
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
metadata
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pyapns2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Darcy Laycock
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-06-17 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: libxml-xmlrpc
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '2.4'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.4'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rr
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '1.0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '1.0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: webmock
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: vcr
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
description: ! 'Pyapns2 provides an alterantive, simpler client for the pyapns push
|
111
|
+
notification server, using libxml-xmlrpc to handle all of the xmlrpc.
|
112
|
+
|
113
|
+
It also is tested against Ruby 1.9'
|
114
|
+
email:
|
115
|
+
- darcy@filtersquad.com
|
116
|
+
executables: []
|
117
|
+
extensions: []
|
118
|
+
extra_rdoc_files: []
|
119
|
+
files:
|
120
|
+
- lib/pyapns2/version.rb
|
121
|
+
- lib/pyapns2.rb
|
122
|
+
homepage: http://github.com/filtersquad
|
123
|
+
licenses: []
|
124
|
+
post_install_message:
|
125
|
+
rdoc_options: []
|
126
|
+
require_paths:
|
127
|
+
- lib
|
128
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
135
|
+
none: false
|
136
|
+
requirements:
|
137
|
+
- - ! '>='
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: 1.3.6
|
140
|
+
requirements: []
|
141
|
+
rubyforge_project:
|
142
|
+
rubygems_version: 1.8.24
|
143
|
+
signing_key:
|
144
|
+
specification_version: 3
|
145
|
+
summary: An alternative ruby client for the pyapns push notification server with an
|
146
|
+
emphasis on Ruby 1.9 support.
|
147
|
+
test_files: []
|