pixelletter 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2 @@
1
+ email: my@email.com
2
+ password: mypassword
@@ -0,0 +1,62 @@
1
+ Pixelletter
2
+ ===========
3
+
4
+ A simple gem to use the API @ pixelletter.de
5
+
6
+ This gem is not affiliated with http://www.pixelletter.de and not supported by them.
7
+
8
+ Pixelletter is a small SaaS from Germany. You can use it to send letters. Yay!
9
+ They currently only offer a curl and PHP example usage scenario. I hate PHP and I don't use curl from my Ruby code.
10
+ That's why I created this small gem.
11
+
12
+ It is a very rough draft. You cannot use the upload they offer.
13
+ That means you have to provide all content via an xml file which the gem creates for you. Just hand the
14
+ content as a hash.
15
+
16
+ Future versions might provide a more OO approach to creating orders.
17
+
18
+ # Install
19
+
20
+ ```
21
+ gem install pixelletter
22
+ ```
23
+
24
+ # Requirements
25
+
26
+ * You need an account at [pixelletter.de](http://www.pixelletter.de)
27
+ * Edit the file `CREDENTIALS.example` and enter your credentials.
28
+
29
+ # Usage
30
+
31
+ Initialize a Pixelletter::Request:
32
+ ```
33
+ my_request = Pixelletter::Request.new(email: ENV['EMAIL'], password: ENV['PASSWORD'], agb: true, widerrufsrecht: true))
34
+ ```
35
+ You can pass an optional attribute: `testmodus: true`. This makes sure no actual orders are created and you are not billed.
36
+
37
+
38
+ Create an order hash:
39
+ ```
40
+ order: { order:
41
+ {
42
+ options: {
43
+ type: 'text',
44
+ action: 1,
45
+ destination: 'DE'
46
+ },
47
+ text: {
48
+ address: "Erika Mustermann\nMusterstr. 2\nD-81237 Musterstadt",
49
+ subject: 'Das ist der Betreff',
50
+ message: 'Das ist die Nachricht.'
51
+ }
52
+ }
53
+ ```
54
+
55
+ Start a request with this order:
56
+ `my_request.request(order)`
57
+
58
+
59
+ # Meta
60
+ Created by Holger Frohloff
61
+ Released under the MIT License: [www.opensource.org/licenses/mit-license.php](www.opensource.org/licenses/mit-license.php)
62
+
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env rake
2
+ require 'bundler'
3
+ Bundler::GemHelper.install_tasks
4
+
5
+ require 'rspec/core/rake_task'
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task :test => :spec
9
+ task :default => :spec
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,23 @@
1
+ require 'active_support/core_ext'
2
+ require 'attr_required'
3
+ require 'attr_optional'
4
+ require 'restclient_with_cert'
5
+ require 'yaml'
6
+
7
+ module Pixelletter
8
+ if File.exists?(File.join(File.dirname('../'), "CREDENTIALS"))
9
+ f = File.join(File.dirname('../'), "CREDENTIALS")
10
+ yml = YAML.load(open(f))
11
+ ENV['EMAIL'] = yml['email']
12
+ ENV['PASSWORD'] = yml['password']
13
+ else
14
+ ENV['EMAIL'] = nil
15
+ ENV['PASSWORD'] = nil
16
+ end
17
+ end
18
+
19
+ require 'pixelletter/base'
20
+ require 'pixelletter/request/request'
21
+ require 'pixelletter/request/xml_builder'
22
+ # require 'pixelletter/order/order'
23
+ # require 'pixelletter/order/text_order'
@@ -0,0 +1,15 @@
1
+ module Pixelletter
2
+ class Base
3
+ include AttrRequired, AttrOptional
4
+
5
+ def initialize(attributes = {})
6
+ if attributes.is_a?(Hash)
7
+ (required_attributes + optional_attributes).each do |key|
8
+ value = attributes[key]
9
+ self.send "#{key}=", value
10
+ end
11
+ end
12
+ attr_missing!
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,57 @@
1
+ module Pixelletter
2
+ class Request < Base
3
+ attr_required :email, :password, :agb, :widerrufsverzicht, :testmodus
4
+
5
+ ENDPOINT = 'https://www.pixelletter.de/xml/index.php'
6
+
7
+ def initialize(attributes = {})
8
+ super
9
+ end
10
+
11
+ def request(order)
12
+ xml = build_xml(order)
13
+ xml_file = File.join(File.dirname('../'), "pixml.xml")
14
+ File.open(xml_file, 'w') { |file| file.write(xml) }
15
+ upload = File.new(File.join(File.dirname('../'), "pixml.xml"), 'rb')
16
+
17
+ response = handle_response do
18
+ RestClient.post('https://www.pixelletter.de/xml/index.php', xml: upload)
19
+ end
20
+
21
+ File.delete(File.join(File.dirname('../'), "pixml.xml"))
22
+ return response
23
+ end
24
+
25
+ private
26
+ def auth
27
+ {auth:
28
+ {
29
+ email: self.email,
30
+ password: self.password,
31
+ agb: self.agb,
32
+ widerrufsverzicht: self.widerrufsverzicht,
33
+ testmodus: self.testmodus
34
+ }
35
+ }
36
+ end
37
+
38
+ def build_xml(order)
39
+ b = XMLBuilder.new
40
+ return b.create_xml(auth, order)
41
+ end
42
+
43
+ def handle_response
44
+ response = yield
45
+ @doc = Nokogiri::XML(response)
46
+ value = @doc.xpath('//result').attr("code").value
47
+ msg = @doc.xpath('//msg').first.child.content if @doc.xpath('//msg').any?
48
+ id = @doc.xpath('//id').first.child.content if @doc.xpath('//id').any?
49
+ return {
50
+ value: value,
51
+ msg: msg,
52
+ id: id
53
+ }
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,62 @@
1
+ require 'builder'
2
+
3
+ module Pixelletter
4
+ class XMLBuilder < Base
5
+
6
+ def initialize
7
+ super
8
+ end
9
+
10
+
11
+ #
12
+ # args = [ {:auth => { email: 'email@email.de', password: 'password', ... }},
13
+ # {:options => { ... }}
14
+ # ]
15
+ #
16
+ #
17
+ def create_xml(*args)
18
+ xml = Builder::XmlMarkup.new( :indent => 2 ); false
19
+ xml.instruct! :xml, :encoding => "UTF-8"
20
+ xml.tag! "pixelletter", version: '1.0' do
21
+ args.flatten.each do |element|
22
+ xml = build_subparts(xml, element)
23
+ end
24
+ end
25
+ finalize_xml(xml)
26
+ end
27
+
28
+ private
29
+
30
+ def build_subparts(xml, element)
31
+ element.each do |key, value|
32
+ if value.class == Hash
33
+ xml.tag! key do
34
+ build_subparts(xml, value)
35
+ end
36
+ else
37
+ # Der Tag <testmodus> erwartet einen Boolean Wert, deshalb kein parsen.
38
+ if key.to_s == 'testmodus'
39
+ xml.tag! key, value
40
+ else
41
+ xml.tag! key, parse(value)
42
+ end
43
+ end
44
+ end
45
+ return xml
46
+ end
47
+
48
+ def parse(value)
49
+ if value == true
50
+ 'ja'
51
+ elsif value == false
52
+ 'nein'
53
+ else
54
+ "#{value}"
55
+ end
56
+ end
57
+
58
+ def finalize_xml(xml)
59
+ return xml.target!
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe Pixelletter do
4
+ context "with CREDENTIALS FILE" do
5
+ before do
6
+ if File.exists?(File.join(File.dirname('../'), "CREDENTIALS"))
7
+ system("mv #{File.join(File.dirname('../'), "CREDENTIALS")} #{File.join(File.dirname('../'), "CREDENTIALS.bak")}")
8
+ end
9
+ f = File.join(File.dirname('../'), "CREDENTIALS")
10
+ File.open(f, 'w') { |file| file.write("email: test@test.de\npassword: testpass") }
11
+ f = File.join(File.dirname('../'), "CREDENTIALS")
12
+ yml = YAML.load(open(f))
13
+ ENV['EMAIL'] = yml['email']
14
+ ENV['PASSWORD'] = yml['password']
15
+ end
16
+
17
+ it "should set the correct ENV variables" do
18
+ ENV['EMAIL'].should eq('test@test.de')
19
+ ENV['PASSWORD'].should eq('testpass')
20
+ end
21
+
22
+ after do
23
+ if File.exists?(File.join(File.dirname('../'), "CREDENTIALS.bak"))
24
+ system("mv #{File.join(File.dirname('../'), "CREDENTIALS.bak")} #{File.join(File.dirname('../'), "CREDENTIALS")}")
25
+ f = File.join(File.dirname('../'), "CREDENTIALS")
26
+ yml = YAML.load(open(f))
27
+ ENV['EMAIL'] = yml['email']
28
+ ENV['PASSWORD'] = yml['password']
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,99 @@
1
+ # Encoding: UTF-8
2
+ require 'spec_helper'
3
+
4
+ describe Pixelletter::Request do
5
+
6
+ let :attributes do
7
+ {
8
+ email: ENV['EMAIL'],
9
+ password: ENV['PASSWORD'],
10
+ agb: true,
11
+ widerrufsverzicht: true,
12
+ testmodus: true
13
+ }
14
+ end
15
+
16
+ describe '.new' do
17
+ context 'when any required parameters are missing' do
18
+ it 'should raise AttrRequired::AttrMissing' do
19
+ attributes.keys.each do |missing_key|
20
+ insufficient_attributes = attributes.reject do |key, value|
21
+ key == missing_key
22
+ end
23
+ expect do
24
+ Pixelletter::Request.new(insufficient_attributes)
25
+ end.to raise_error AttrRequired::AttrMissing
26
+ end
27
+ end
28
+ end
29
+
30
+ context 'when all required parameters are given' do
31
+ it 'should succeed' do
32
+ expect do
33
+ Pixelletter::Request.new(attributes)
34
+ end.not_to raise_error AttrRequired::AttrMissing
35
+ end
36
+ end
37
+ end
38
+
39
+ describe '#request' do
40
+ context 'with text' do
41
+ let :order do
42
+ { order:
43
+ {
44
+ options: {
45
+ type: 'text',
46
+ action: 1,
47
+ destination: 'DE'
48
+ },
49
+ text: {
50
+ address: "Erika Mustermann\nMusterstr. 2\nD-81237 Musterstadt",
51
+ subject: 'Das ist der Betreff',
52
+ message: 'Das ist die Nachricht.'
53
+ }
54
+ }
55
+ }
56
+ end
57
+
58
+ # <?xml version="1.0" encoding="UTF-8"?>
59
+ # <pixelletter version="1.1">
60
+ # <response>
61
+ # <result code="100">
62
+ # <msg>Auftrag erfolgreich übermittelt.</msg>
63
+ # <id>11954460</id>
64
+ # </result>
65
+ # </response>
66
+ # </pixelletter>
67
+
68
+ it "should send a successful request" do
69
+ # order = Pixelletter::TextOrder.new()
70
+ pr = mock(Pixelletter::Request.new(attributes))
71
+ pr.stub(:request).with(order).and_return({:value=>"100", :msg=>"Auftrag erfolgreich übermittelt.", :id=>"11954536"})
72
+ response = pr.request(order)
73
+ response[:value].should == '100'
74
+ end
75
+ end
76
+
77
+ context 'with upload' do
78
+ let :order do
79
+ { order:
80
+ {
81
+ options: {
82
+ type: 'upload',
83
+ action: 1,
84
+ destination: 'DE'
85
+ }
86
+ }
87
+ }
88
+ end
89
+
90
+ it "should send a successful request" do
91
+ pr = Pixelletter::Request.new(attributes)
92
+ # pr.stub(:request).with(order).and_return({:value=>"100", :msg=>"Auftrag erfolgreich übermittelt.", :id=>"11954536"})
93
+ response = pr.request(order)
94
+ puts response.inspect
95
+ # response[:value].should == '100'
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,76 @@
1
+ require 'spec_helper'
2
+
3
+ describe Pixelletter::XMLBuilder do
4
+ describe '#create_xml' do
5
+ let :auth do
6
+ { auth: { email: 'email@email.de', password: 'password', agb: true, widerrufsverzicht: true, testmodus: true } }
7
+ end
8
+
9
+ it 'should create a valid xml with an <auth> block' do
10
+ b = Pixelletter::XMLBuilder.new
11
+ xml = b.create_xml(auth)
12
+
13
+ xml.should equal_xml(<<-XML)
14
+ <?xml version="1.0" encoding="UTF-8"?>
15
+ <pixelletter version="1.0">
16
+ <auth>
17
+ <email>email@email.de</email>
18
+ <password>password</password>
19
+ <agb>ja</agb>
20
+ <widerrufsverzicht>ja</widerrufsverzicht>
21
+ <testmodus>true</testmodus>
22
+ </auth>
23
+ </pixelletter>
24
+ XML
25
+ end
26
+
27
+ let :order do
28
+ { order:
29
+ {
30
+ options: {
31
+ type: 'text',
32
+ action: 1,
33
+ destination: 'DE'
34
+ },
35
+ text: {
36
+ address: "Erika Mustermann\nMusterstr. 2\nD-81237 Musterstadt",
37
+ subject: 'Das ist der Betreff',
38
+ message: 'Das ist die Nachricht.'
39
+ }
40
+ }
41
+ }
42
+ end
43
+
44
+ it 'should create a valid xml with an <auth> and an <order> block' do
45
+ b = Pixelletter::XMLBuilder.new
46
+ xml = b.create_xml(auth, order)
47
+
48
+ xml.should equal_xml(<<-XML)
49
+ <?xml version="1.0" encoding="UTF-8"?>
50
+ <pixelletter version="1.0">
51
+ <auth>
52
+ <email>email@email.de</email>
53
+ <password>password</password>
54
+ <agb>ja</agb>
55
+ <widerrufsverzicht>ja</widerrufsverzicht>
56
+ <testmodus>true</testmodus>
57
+ </auth>
58
+ <order>
59
+ <options>
60
+ <type>text</type>
61
+ <action>1</action>
62
+ <destination>DE</destination>
63
+ </options>
64
+ <text>
65
+ <address>Erika Mustermann
66
+ Musterstr. 2
67
+ D-81237 Musterstadt</address>
68
+ <subject>Das ist der Betreff</subject>
69
+ <message>Das ist die Nachricht.</message>
70
+ </text>
71
+ </order>
72
+ </pixelletter>
73
+ XML
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,10 @@
1
+ require 'simplecov'
2
+ SimpleCov.start
3
+ require 'rspec'
4
+ require 'rspec/autorun'
5
+ require 'test_xml/spec'
6
+ require 'pixelletter'
7
+
8
+ RSpec.configure do |c|
9
+ c.mock_with :rspec
10
+ end
metadata ADDED
@@ -0,0 +1,249 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pixelletter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Holger Frohloff
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-06 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activesupport
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: attr_required
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
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: nokogiri
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: restclient_with_cert
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: builder
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: 3.1.4
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: 3.1.4
94
+ - !ruby/object:Gem::Dependency
95
+ name: rspec
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
+ - !ruby/object:Gem::Dependency
111
+ name: test_xml
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: rake
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ - !ruby/object:Gem::Dependency
143
+ name: simplecov
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ type: :development
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ - !ruby/object:Gem::Dependency
159
+ name: guard
160
+ requirement: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ - !ruby/object:Gem::Dependency
175
+ name: guard-rspec
176
+ requirement: !ruby/object:Gem::Requirement
177
+ none: false
178
+ requirements:
179
+ - - ! '>='
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ type: :development
183
+ prerelease: false
184
+ version_requirements: !ruby/object:Gem::Requirement
185
+ none: false
186
+ requirements:
187
+ - - ! '>='
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
190
+ - !ruby/object:Gem::Dependency
191
+ name: rb-fsevent
192
+ requirement: !ruby/object:Gem::Requirement
193
+ none: false
194
+ requirements:
195
+ - - ~>
196
+ - !ruby/object:Gem::Version
197
+ version: 0.9.1
198
+ type: :development
199
+ prerelease: false
200
+ version_requirements: !ruby/object:Gem::Requirement
201
+ none: false
202
+ requirements:
203
+ - - ~>
204
+ - !ruby/object:Gem::Version
205
+ version: 0.9.1
206
+ description: A simple gem to use the pixelletter.de API as there exists only an aweful
207
+ PHP class yet.
208
+ email: holger@5minutenpause.com
209
+ executables: []
210
+ extensions: []
211
+ extra_rdoc_files: []
212
+ files:
213
+ - CREDENTIALS.example
214
+ - Rakefile
215
+ - README.md
216
+ - VERSION
217
+ - lib/pixelletter.rb
218
+ - lib/pixelletter/base.rb
219
+ - lib/pixelletter/request/request.rb
220
+ - lib/pixelletter/request/xml_builder.rb
221
+ - spec/spec_helper.rb
222
+ - spec/pixelletter_spec.rb
223
+ - spec/request/request_spec.rb
224
+ - spec/request/xml_builder_spec.rb
225
+ homepage: http://rubygems.org/gems/pixelletter
226
+ licenses: []
227
+ post_install_message:
228
+ rdoc_options: []
229
+ require_paths:
230
+ - lib
231
+ required_ruby_version: !ruby/object:Gem::Requirement
232
+ none: false
233
+ requirements:
234
+ - - ! '>='
235
+ - !ruby/object:Gem::Version
236
+ version: '0'
237
+ required_rubygems_version: !ruby/object:Gem::Requirement
238
+ none: false
239
+ requirements:
240
+ - - ! '>='
241
+ - !ruby/object:Gem::Version
242
+ version: '0'
243
+ requirements: []
244
+ rubyforge_project:
245
+ rubygems_version: 1.8.24
246
+ signing_key:
247
+ specification_version: 3
248
+ summary: A gem to use the pixelletter.de API
249
+ test_files: []