pixelletter 0.0.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.
@@ -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: []