KayakoClient 0.0.1b

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/lib/kayako_client.rb +36 -0
  2. data/lib/kayako_client/base.rb +98 -0
  3. data/lib/kayako_client/department.rb +31 -0
  4. data/lib/kayako_client/http/http.rb +217 -0
  5. data/lib/kayako_client/http/http_backend.rb +31 -0
  6. data/lib/kayako_client/http/http_client.rb +87 -0
  7. data/lib/kayako_client/http/http_response.rb +61 -0
  8. data/lib/kayako_client/http/net_http.rb +109 -0
  9. data/lib/kayako_client/mixins/api.rb +299 -0
  10. data/lib/kayako_client/mixins/attachment.rb +69 -0
  11. data/lib/kayako_client/mixins/authentication.rb +34 -0
  12. data/lib/kayako_client/mixins/client.rb +308 -0
  13. data/lib/kayako_client/mixins/logger.rb +29 -0
  14. data/lib/kayako_client/mixins/object.rb +456 -0
  15. data/lib/kayako_client/mixins/post_client.rb +42 -0
  16. data/lib/kayako_client/mixins/staff_visibility_api.rb +9 -0
  17. data/lib/kayako_client/mixins/ticket_api.rb +55 -0
  18. data/lib/kayako_client/mixins/ticket_client.rb +135 -0
  19. data/lib/kayako_client/mixins/user_visibility_api.rb +9 -0
  20. data/lib/kayako_client/staff.rb +25 -0
  21. data/lib/kayako_client/staff_group.rb +9 -0
  22. data/lib/kayako_client/ticket.rb +241 -0
  23. data/lib/kayako_client/ticket_attachment.rb +42 -0
  24. data/lib/kayako_client/ticket_count.rb +135 -0
  25. data/lib/kayako_client/ticket_custom_field.rb +110 -0
  26. data/lib/kayako_client/ticket_note.rb +105 -0
  27. data/lib/kayako_client/ticket_post.rb +61 -0
  28. data/lib/kayako_client/ticket_priority.rb +24 -0
  29. data/lib/kayako_client/ticket_status.rb +31 -0
  30. data/lib/kayako_client/ticket_time_track.rb +27 -0
  31. data/lib/kayako_client/ticket_type.rb +26 -0
  32. data/lib/kayako_client/user.rb +61 -0
  33. data/lib/kayako_client/user_group.rb +12 -0
  34. data/lib/kayako_client/user_organization.rb +23 -0
  35. data/lib/kayako_client/xml/lib_xml.rb +86 -0
  36. data/lib/kayako_client/xml/rexml_document.rb +77 -0
  37. data/lib/kayako_client/xml/xml.rb +63 -0
  38. data/lib/kayako_client/xml/xml_backend.rb +42 -0
  39. metadata +105 -0
@@ -0,0 +1,36 @@
1
+ require 'kayako_client/http/http_response'
2
+ require 'kayako_client/http/http_backend'
3
+ require 'kayako_client/http/http'
4
+
5
+ require 'kayako_client/xml/xml_backend'
6
+ require 'kayako_client/xml/xml'
7
+
8
+ require 'kayako_client/mixins/api'
9
+ require 'kayako_client/mixins/object'
10
+ require 'kayako_client/mixins/client'
11
+ require 'kayako_client/mixins/ticket_client'
12
+ require 'kayako_client/mixins/post_client'
13
+ require 'kayako_client/mixins/logger'
14
+ require 'kayako_client/mixins/authentication'
15
+ require 'kayako_client/mixins/attachment'
16
+ require 'kayako_client/mixins/ticket_api'
17
+ require 'kayako_client/mixins/user_visibility_api'
18
+ require 'kayako_client/mixins/staff_visibility_api'
19
+
20
+ require 'kayako_client/base'
21
+ require 'kayako_client/department'
22
+ require 'kayako_client/staff'
23
+ require 'kayako_client/staff_group'
24
+ require 'kayako_client/ticket'
25
+ require 'kayako_client/ticket_attachment'
26
+ require 'kayako_client/ticket_custom_field'
27
+ require 'kayako_client/ticket_note'
28
+ require 'kayako_client/ticket_post'
29
+ require 'kayako_client/ticket_priority'
30
+ require 'kayako_client/ticket_status'
31
+ require 'kayako_client/ticket_time_track'
32
+ require 'kayako_client/ticket_type'
33
+ require 'kayako_client/ticket_count'
34
+ require 'kayako_client/user'
35
+ require 'kayako_client/user_group'
36
+ require 'kayako_client/user_organization'
@@ -0,0 +1,98 @@
1
+ module KayakoClient
2
+
3
+ class Base
4
+ include KayakoClient::API
5
+ include KayakoClient::Logger
6
+ include KayakoClient::Object
7
+ include KayakoClient::Authentication
8
+ include KayakoClient::HTTP
9
+ include KayakoClient::XML
10
+
11
+ def initialize(*args)
12
+ options = args.last.is_a?(Hash) ? args.pop : {}
13
+
14
+ if args[0]
15
+ @api_url = args[0]
16
+ elsif options.has_key?(:api_url)
17
+ @api_url = options.delete(:api_url)
18
+ else
19
+ @api_url = Base.api_url
20
+ end
21
+
22
+ if args[1]
23
+ @api_key = args[1]
24
+ elsif options.has_key?(:api_key)
25
+ @api_key = options.delete(:api_key)
26
+ else
27
+ @api_key = Base.api_key
28
+ end
29
+
30
+ if args[2]
31
+ @secret_key = args[2]
32
+ elsif options.has_key?(:secret_key)
33
+ @secret_key = options.delete(:secret_key)
34
+ else
35
+ @secret_key = Base.secret_key
36
+ end
37
+
38
+ if options.has_key?(:client)
39
+ http = options.delete(:client)
40
+ if http
41
+ if http.class.included_modules.include?(KayakoClient::HTTPBackend)
42
+ @http_backend = http.class
43
+ @client = http
44
+ else
45
+ raise ArgumentError, "invalid HTTP client: #{http.class.name}"
46
+ end
47
+ end
48
+ end
49
+
50
+ if options.has_key?(:logger)
51
+ @logger = options.delete(:logger)
52
+ end
53
+
54
+ if self.instance_of?(KayakoClient::Base)
55
+ unless defined?(@client) && @client
56
+ @client = http_backend.new(proxy.merge(:logger => logger))
57
+ end
58
+ self.extend(KayakoClient::Client)
59
+ end
60
+
61
+ @associated = {}
62
+ import(options)
63
+ end
64
+
65
+ def inherited_options
66
+ inherited = {}
67
+ inherited[:api_url] = @api_url if defined?(@api_url)
68
+ inherited[:api_key] = @api_key if defined?(@api_key)
69
+ inherited[:secret_key] = @secret_key if defined?(@secret_key)
70
+ inherited[:client] = @client if defined?(@client)
71
+ inherited[:logger] = @logger if defined?(@logger)
72
+ inherited
73
+ end
74
+
75
+ class << self
76
+
77
+ def configure(&block)
78
+ instance_eval(&block)
79
+ end
80
+
81
+ def inherited_options(options)
82
+ inherited = {}
83
+ inherited[:api_url] = options[:api_url] if options.has_key?(:api_url)
84
+ inherited[:api_key] = options[:api_key] if options.has_key?(:api_key)
85
+ inherited[:secret_key] = options[:secret_key] if options.has_key?(:secret_key)
86
+ inherited[:client] = options[:client] if options.has_key?(:client)
87
+ inherited[:logger] = options[:logger] if options.has_key?(:logger)
88
+ inherited
89
+ end
90
+
91
+ end
92
+
93
+ end
94
+
95
+ class Tickets < Base
96
+ end
97
+
98
+ end
@@ -0,0 +1,31 @@
1
+ require 'kayako_client/mixins/user_visibility_api'
2
+
3
+ require 'kayako_client/user_group'
4
+
5
+ module KayakoClient
6
+ class Department < KayakoClient::Base
7
+ include KayakoClient::UserVisibilityAPI
8
+
9
+ DEPARTMENT_TYPES = [ :public, :private ].freeze
10
+ DEPARTMENT_MODULES = [ :tickets, :livechat ].freeze
11
+
12
+ # NOTE: if :parent_department_id is set :module should have the same value
13
+
14
+ property :id, :integer, :readonly => true
15
+ property :title, :string, :required => [ :put, :post ]
16
+ property :type, :symbol, :in => DEPARTMENT_TYPES, :required => :post
17
+ property :module, :symbol, :in => DEPARTMENT_MODULES, :required => :post, :new => true
18
+ property :display_order, :integer
19
+ property :parent_department_id, :integer
20
+ property :user_visibility_custom, :boolean
21
+ property :user_group_ids, [ :integer ], :get => :usergroups, :set => :usergroupid, :condition => { :user_visibility_custom => true }
22
+
23
+ associate :parent_department, :parent_department_id, Department
24
+ associate :user_groups, :user_group_ids, UserGroup
25
+
26
+ def has_parent_department?
27
+ !parent_department_id.nil? && parent_department_id > 0
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,217 @@
1
+ module KayakoClient
2
+ module HTTP
3
+
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ def proxy=(options = {})
9
+ @proxy = {}
10
+ options.each do |key, value|
11
+ if [ :host, :port, :user, :pass ].include?(key)
12
+ @proxy[key] = value
13
+ else
14
+ raise ArgumentError, "unsupported option: #{key}"
15
+ end
16
+ end
17
+ end
18
+
19
+ def proxy
20
+ @proxy ||= self.class.proxy
21
+ end
22
+
23
+ def http_backend=(backend)
24
+ if backend.is_a?(String)
25
+ raise ArgumentError, "invalid HTTP backend: #{backend}" unless backend =~ /^[A-Za-z_]+$/
26
+ file = backend.gsub(/([a-z])([A-Z])/, '\1_\2').gsub(/([A-Z])([A-Z][a-z])/, '\1_\2').downcase
27
+ require "kayako_client/http/#{file}"
28
+ backend = KayakoClient.const_get(backend)
29
+ end
30
+ if backend.is_a?(Class)
31
+ if backend.included_modules.include?(KayakoClient::HTTPBackend)
32
+ @http_backend = backend
33
+ @client = nil
34
+ else
35
+ raise ArgumentError, "invalid HTTP backend: #{backend.name}"
36
+ end
37
+ else
38
+ if backend.class.included_modules.include?(KayakoClient::HTTPBackend)
39
+ @http_backend = backend.class
40
+ @client = backend
41
+ else
42
+ raise ArgumentError, "invalid HTTP backend: #{backend.class.name}"
43
+ end
44
+ end
45
+ end
46
+
47
+ def http_backend
48
+ @http_backend ||= self.class.http_backend
49
+ end
50
+
51
+ def client
52
+ @client ||= nil
53
+ unless @client
54
+ if !instance_of?(KayakoClient::Base) && http_backend == self.class.http_backend && self.class.client
55
+ @client = self.class.client
56
+ else
57
+ @client = http_backend.new(proxy.merge(:logger => logger))
58
+ end
59
+ end
60
+ @client
61
+ end
62
+
63
+ def put_request(params = {})
64
+ @errors ||= {}
65
+ raise RuntimeError, "undefined ID" unless id
66
+ random = self.class.salt
67
+ e = params.delete(:e) || "#{self.class.path}/#{id}"
68
+ data = self.class.validate(params.merge(:errors => @errors))
69
+ if @errors.empty?
70
+ client.put(api_url, data.merge(:e => e,
71
+ :apikey => api_key,
72
+ :salt => random,
73
+ :signature => self.class.signature(random, secret_key)))
74
+ else
75
+ @errors
76
+ end
77
+ end
78
+
79
+ def post_request(params = {})
80
+ @errors ||= {}
81
+ random = self.class.salt
82
+ e = params.delete(:e) || self.class.path
83
+ data = self.class.validate(params.merge(:errors => @errors))
84
+ if @errors.empty?
85
+ client.post(api_url, data.merge(:e => e,
86
+ :apikey => api_key,
87
+ :salt => random,
88
+ :signature => self.class.signature(random, secret_key)))
89
+ else
90
+ @errors
91
+ end
92
+ end
93
+
94
+ def delete_request(params = {})
95
+ raise RuntimeError, "undefined ID" unless id
96
+ random = self.class.salt
97
+ e = params.delete(:e) || "#{self.class.path}/#{id}"
98
+ client.delete(api_url, :e => e,
99
+ :apikey => api_key,
100
+ :salt => random,
101
+ :signature => self.class.signature(random, secret_key))
102
+ end
103
+
104
+ module ClassMethods
105
+
106
+ def proxy=(options = {})
107
+ @@proxy = {}
108
+ options.each do |key, value|
109
+ if [ :host, :port, :user, :pass ].include?(key)
110
+ @@proxy[key] = value
111
+ else
112
+ raise ArgumentError, "unsupported option: #{key}"
113
+ end
114
+ end
115
+ end
116
+
117
+ def proxy
118
+ @@proxy ||= {}
119
+ end
120
+
121
+ def http_backend=(backend)
122
+ if backend.is_a?(String)
123
+ raise ArgumentError, "invalid HTTP backend: #{backend}" unless backend =~ /^[A-Za-z_]+$/
124
+ file = backend.gsub(/([a-z])([A-Z])/, '\1_\2').gsub(/([A-Z])([A-Z][a-z])/, '\1_\2').downcase
125
+ require "kayako_client/http/#{file}"
126
+ backend = KayakoClient.const_get(backend)
127
+ end
128
+ if backend.is_a?(Class)
129
+ if backend.included_modules.include?(KayakoClient::HTTPBackend)
130
+ @@http_backend = backend
131
+ @@client = nil
132
+ else
133
+ raise ArgumentError, "invalid HTTP backend: #{backend.name}"
134
+ end
135
+ else
136
+ if backend.class.included_modules.include?(KayakoClient::HTTPBackend)
137
+ @@http_backend = backend.class
138
+ @@client = backend
139
+ else
140
+ raise ArgumentError, "invalid HTTP backend: #{backend.class.name}"
141
+ end
142
+ end
143
+ end
144
+
145
+ def http_backend
146
+ begin
147
+ require 'kayako_client/http/http_client'
148
+ @@http_backend ||= KayakoClient::HTTPClient
149
+ rescue LoadError
150
+ require 'kayako_client/http/net_http'
151
+ @@http_backend ||= KayakoClient::NetHTTP
152
+ end
153
+ end
154
+
155
+ def client
156
+ @@client ||= nil
157
+ unless @@client
158
+ @@client = http_backend.new(proxy.merge(:logger => logger))
159
+ end
160
+ @@client
161
+ end
162
+
163
+ def get_request(options = {})
164
+ random = salt
165
+ params = options.dup
166
+
167
+ id = params.delete(:id)
168
+ e = params.delete(:e) || (id.nil? ? path : "#{path}/#{id}")
169
+ http = params.delete(:client) || client
170
+ url = params.delete(:api_url) || api_url
171
+ key = params.delete(:api_key) || api_key
172
+ secret = params.delete(:secret_key) || secret_key
173
+
174
+ http.get(url, params.merge(:e => e,
175
+ :apikey => key,
176
+ :salt => random,
177
+ :signature => signature(random, secret)))
178
+ end
179
+
180
+ def post_request(options = {})
181
+ random = salt
182
+ params = options.dup
183
+
184
+ e = params.delete(:e) || path
185
+ http = params.delete(:client) || client
186
+ url = params.delete(:api_url) || api_url
187
+ key = params.delete(:api_key) || api_key
188
+ secret = params.delete(:secret_key) || secret_key
189
+
190
+ http.post(url, params.merge(:e => e,
191
+ :apikey => key,
192
+ :salt => random,
193
+ :signature => signature(random, secret)))
194
+ end
195
+
196
+ def delete_request(options = {})
197
+ random = salt
198
+ params = options.dup
199
+
200
+ id = params.delete(:id)
201
+ e = params.delete(:e) || "#{path}/#{id}"
202
+ http = params.delete(:client) || client
203
+ url = params.delete(:api_url) || api_url
204
+ key = params.delete(:api_key) || api_key
205
+ secret = params.delete(:secret_key) || secret_key
206
+
207
+ raise ArgumentError, "missing ID" unless id
208
+ http.delete(url, :e => e,
209
+ :apikey => key,
210
+ :salt => random,
211
+ :signature => signature(random, secret))
212
+ end
213
+
214
+ end
215
+
216
+ end
217
+ end
@@ -0,0 +1,31 @@
1
+ require 'uri'
2
+
3
+ module KayakoClient
4
+ module HTTPBackend
5
+
6
+ def initialize(options = {})
7
+ raise NotImplementedError, "not implemented"
8
+ end
9
+
10
+ def get(base, params = {})
11
+ raise NotImplementedError, "not implemented"
12
+ end
13
+
14
+ def put(base, params = {})
15
+ raise NotImplementedError, "not implemented"
16
+ end
17
+
18
+ def post(base, params = {})
19
+ raise NotImplementedError, "not implemented"
20
+ end
21
+
22
+ def delete(base, params = {})
23
+ raise NotImplementedError, "not implemented"
24
+ end
25
+
26
+ def response(resp)
27
+ raise NotImplementedError, "not implemented"
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,87 @@
1
+ require 'httpclient'
2
+
3
+ module KayakoClient
4
+ class HTTPClient
5
+ include KayakoClient::Logger
6
+ include KayakoClient::HTTPBackend
7
+
8
+ def initialize(options = {})
9
+ @client = ::HTTPClient.new
10
+ if options[:host]
11
+ @client.proxy = "http://#{options[:host]}:#{options[:port] || 80}"
12
+ @client.set_proxy_auth(options[:user], options[:pass])
13
+ end
14
+ @logger = options[:logger] if options[:logger]
15
+ end
16
+
17
+ def get(base, params = {})
18
+ log = params.delete(:logger) || logger
19
+ log.debug ":get => #{base} + #{params.inspect}" if log
20
+ resp = @client.request(:get, base, params)
21
+ response(resp)
22
+ end
23
+
24
+ def put(base, params = {})
25
+ query = { :e => params.delete(:e) }
26
+ data = form_data(params)
27
+ log = params.delete(:logger) || logger
28
+ if log
29
+ log.debug ":put => #{base} + #{query.inspect}"
30
+ log.debug "PUT Data: #{data.inspect}"
31
+ end
32
+ resp = @client.request(:put, base, query, data, { 'Content-Type' => 'application/x-www-form-urlencoded' })
33
+ response(resp)
34
+ end
35
+
36
+ def post(base, params = {})
37
+ query = { :e => params.delete(:e) }
38
+ data = form_data(params)
39
+ log = params.delete(:logger) || logger
40
+ if log
41
+ log.debug ":post => #{base} + #{query.inspect}"
42
+ log.debug "POST Data: #{data.inspect}"
43
+ end
44
+ resp = @client.request(:post, base, query, data, { 'Content-Type' => 'application/x-www-form-urlencoded' })
45
+ response(resp)
46
+ end
47
+
48
+ def delete(base, params = {})
49
+ log = params.delete(:logger) || logger
50
+ log.debug ":delete => #{base} + #{params.inspect}" if log
51
+ resp = @client.request(:delete, base, params)
52
+ response(resp)
53
+ end
54
+
55
+ def response(resp)
56
+ case resp.status
57
+ when 200
58
+ KayakoClient::HTTPOK.new(resp.content)
59
+ when 400
60
+ KayakoClient::HTTPBadRequest.new(resp.content)
61
+ when 401
62
+ KayakoClient::HTTPUnauthorized.new(resp.content)
63
+ when 403
64
+ KayakoClient::HTTPForbidden.new(resp.content)
65
+ when 404
66
+ KayakoClient::HTTPNotFound.new(resp.content)
67
+ when 405
68
+ KayakoClient::HTTPNotAllowed.new(resp.content)
69
+ else
70
+ KayakoClient::HTTPResponse.new(resp.status, resp.content)
71
+ end
72
+ end
73
+
74
+ private
75
+
76
+ def form_data(params = {})
77
+ params.inject([]) do |array, (name, value)|
78
+ if value.is_a?(Array)
79
+ array.concat(value.collect { |item| [ name.to_s + '[]', item.to_s ] })
80
+ else
81
+ array.push([ name.to_s, value.to_s ])
82
+ end
83
+ end
84
+ end
85
+
86
+ end
87
+ end