KayakoClient 0.0.1b
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/kayako_client.rb +36 -0
- data/lib/kayako_client/base.rb +98 -0
- data/lib/kayako_client/department.rb +31 -0
- data/lib/kayako_client/http/http.rb +217 -0
- data/lib/kayako_client/http/http_backend.rb +31 -0
- data/lib/kayako_client/http/http_client.rb +87 -0
- data/lib/kayako_client/http/http_response.rb +61 -0
- data/lib/kayako_client/http/net_http.rb +109 -0
- data/lib/kayako_client/mixins/api.rb +299 -0
- data/lib/kayako_client/mixins/attachment.rb +69 -0
- data/lib/kayako_client/mixins/authentication.rb +34 -0
- data/lib/kayako_client/mixins/client.rb +308 -0
- data/lib/kayako_client/mixins/logger.rb +29 -0
- data/lib/kayako_client/mixins/object.rb +456 -0
- data/lib/kayako_client/mixins/post_client.rb +42 -0
- data/lib/kayako_client/mixins/staff_visibility_api.rb +9 -0
- data/lib/kayako_client/mixins/ticket_api.rb +55 -0
- data/lib/kayako_client/mixins/ticket_client.rb +135 -0
- data/lib/kayako_client/mixins/user_visibility_api.rb +9 -0
- data/lib/kayako_client/staff.rb +25 -0
- data/lib/kayako_client/staff_group.rb +9 -0
- data/lib/kayako_client/ticket.rb +241 -0
- data/lib/kayako_client/ticket_attachment.rb +42 -0
- data/lib/kayako_client/ticket_count.rb +135 -0
- data/lib/kayako_client/ticket_custom_field.rb +110 -0
- data/lib/kayako_client/ticket_note.rb +105 -0
- data/lib/kayako_client/ticket_post.rb +61 -0
- data/lib/kayako_client/ticket_priority.rb +24 -0
- data/lib/kayako_client/ticket_status.rb +31 -0
- data/lib/kayako_client/ticket_time_track.rb +27 -0
- data/lib/kayako_client/ticket_type.rb +26 -0
- data/lib/kayako_client/user.rb +61 -0
- data/lib/kayako_client/user_group.rb +12 -0
- data/lib/kayako_client/user_organization.rb +23 -0
- data/lib/kayako_client/xml/lib_xml.rb +86 -0
- data/lib/kayako_client/xml/rexml_document.rb +77 -0
- data/lib/kayako_client/xml/xml.rb +63 -0
- data/lib/kayako_client/xml/xml_backend.rb +42 -0
- metadata +105 -0
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'kayako_client/mixins/user_visibility_api'
|
2
|
+
|
3
|
+
module KayakoClient
|
4
|
+
class TicketPriority < KayakoClient::Tickets
|
5
|
+
include KayakoClient::UserVisibilityAPI
|
6
|
+
|
7
|
+
supports :all, :get
|
8
|
+
|
9
|
+
PRIORITY_TYPES = [ :public, :private ].freeze
|
10
|
+
|
11
|
+
property :id, :integer
|
12
|
+
property :title, :string
|
13
|
+
property :display_order, :integer
|
14
|
+
property :fr_color_code, :string
|
15
|
+
property :bg_color_code, :string
|
16
|
+
property :display_icon, :string
|
17
|
+
property :type, :symbol, :in => PRIORITY_TYPES
|
18
|
+
property :user_visibility_custom, :boolean
|
19
|
+
property :user_group_ids, [ :integer ], :get => :usergroupid, :condition => { :user_visibility_custom => true }
|
20
|
+
|
21
|
+
associate :user_groups, :user_group_ids, UserGroup
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'kayako_client/department'
|
2
|
+
|
3
|
+
module KayakoClient
|
4
|
+
class TicketStatus < KayakoClient::Tickets
|
5
|
+
include KayakoClient::StaffVisibilityAPI
|
6
|
+
|
7
|
+
supports :all, :get
|
8
|
+
|
9
|
+
STATUS_TYPES = [ :public, :private ].freeze
|
10
|
+
|
11
|
+
property :id, :integer
|
12
|
+
property :title, :string
|
13
|
+
property :display_order, :integer
|
14
|
+
property :department_id, :integer
|
15
|
+
property :display_icon, :string
|
16
|
+
property :type, :symbol, :in => STATUS_TYPES
|
17
|
+
property :display_in_main_list, :boolean
|
18
|
+
property :mark_as_resolved, :boolean
|
19
|
+
property :display_count, :integer
|
20
|
+
property :status_color, :string
|
21
|
+
property :status_bg_color, :string
|
22
|
+
property :reset_due_time, :boolean
|
23
|
+
property :trigger_survey, :boolean
|
24
|
+
property :staff_visibility_custom, :boolean
|
25
|
+
property :staff_group_ids, [ :integer ], :get => :staffgroupid, :condition => { :staff_visibility_custom => true }
|
26
|
+
|
27
|
+
associate :department, :department_id, Department
|
28
|
+
associate :staff_groups, :staff_group_ids, StaffGroup
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'kayako_client/mixins/ticket_api'
|
2
|
+
|
3
|
+
module KayakoClient
|
4
|
+
class TicketTimeTrack < KayakoClient::Tickets
|
5
|
+
include KayakoClient::TicketAPI
|
6
|
+
|
7
|
+
supports :all, :get, :post, :delete
|
8
|
+
|
9
|
+
property :id, :integer, :readonly => true
|
10
|
+
property :ticket_id, :integer, :required => :post
|
11
|
+
property :time_worked, :integer, :required => :post, :set => :timespent
|
12
|
+
property :time_billable, :integer, :required => :post
|
13
|
+
property :bill_date, :date, :required => :post, :set => :billtimeline
|
14
|
+
property :work_date, :date, :required => :post, :set => :worktimeline
|
15
|
+
property :worker_staff_id, :integer
|
16
|
+
property :worker_staff_name, :string, :readonly => true
|
17
|
+
property :creator_staff_id, :integer, :required => :post, :set => :staffid
|
18
|
+
property :creator_staff_name, :string, :readonly => true
|
19
|
+
property :note_color, :integer, :range => 1..5
|
20
|
+
property :contents, :string, :required => :post
|
21
|
+
|
22
|
+
associate :ticket, :ticket_id, Ticket
|
23
|
+
associate :worker_staff, :worker_staff_id, Staff
|
24
|
+
associate :creator_staff, :creator_staff_id, Staff
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'kayako_client/mixins/user_visibility_api'
|
2
|
+
|
3
|
+
require 'kayako_client/department'
|
4
|
+
|
5
|
+
module KayakoClient
|
6
|
+
class TicketType < KayakoClient::Tickets
|
7
|
+
include KayakoClient::UserVisibilityAPI
|
8
|
+
|
9
|
+
supports :all, :get
|
10
|
+
|
11
|
+
TYPE_TYPES = [ :public, :private ].freeze
|
12
|
+
|
13
|
+
property :id, :integer
|
14
|
+
property :title, :string
|
15
|
+
property :display_order, :integer
|
16
|
+
property :department_id, :integer
|
17
|
+
property :display_icon, :string
|
18
|
+
property :type, :symbol, :in => TYPE_TYPES
|
19
|
+
property :user_visibility_custom, :boolean
|
20
|
+
property :user_group_ids, [ :integer ], :get => :usergroupid, :condition => { :user_visibility_custom => true }
|
21
|
+
|
22
|
+
associate :department, :department_id, Department
|
23
|
+
associate :user_groups, :user_group_ids, UserGroup
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'kayako_client/user_group'
|
2
|
+
require 'kayako_client/user_organization'
|
3
|
+
|
4
|
+
module KayakoClient
|
5
|
+
class User < KayakoClient::Base
|
6
|
+
|
7
|
+
USER_ROLES = [ :user, :manager ].freeze
|
8
|
+
USER_SALUTATIONS = [ 'Mr.', 'Ms.', 'Mrs.', 'Dr.' ].freeze
|
9
|
+
|
10
|
+
# NOTE: if :user_group_id is set the group should be of :registered type
|
11
|
+
|
12
|
+
property :id, :integer, :readonly => true
|
13
|
+
property :user_group_id, :integer, :required => :post
|
14
|
+
property :user_role, :symbol, :in => USER_ROLES
|
15
|
+
property :user_organization_id, :integer
|
16
|
+
property :salutation, :string, :in => USER_SALUTATIONS
|
17
|
+
property :user_expiry, :date
|
18
|
+
property :full_name, :string, :required => [ :put, :post ]
|
19
|
+
property :emails, [ :string ], :required => :post, :get => :email, :set => :email
|
20
|
+
property :designation, :string
|
21
|
+
property :phone, :string
|
22
|
+
property :date_line, :date, :readonly => true
|
23
|
+
property :last_visit, :date, :readonly => true
|
24
|
+
property :is_enabled, :boolean
|
25
|
+
property :time_zone, :string
|
26
|
+
property :enable_dst, :boolean
|
27
|
+
property :sla_plan_id, :integer
|
28
|
+
property :sla_plan_expiry, :date
|
29
|
+
property :password, :string, :new => true, :required => :post
|
30
|
+
property :send_welcome_email, :boolean, :new => true
|
31
|
+
|
32
|
+
associate :user_group, :user_group_id, UserGroup
|
33
|
+
associate :user_organization, :user_organization_id, UserOrganization
|
34
|
+
|
35
|
+
def self.all(marker = nil, limit = nil, options = {})
|
36
|
+
unless marker.nil?
|
37
|
+
unless marker.to_i > 0
|
38
|
+
logger.error "invalid :marker - #{marker}" if logger
|
39
|
+
raise ArgumentError, "invalid marker"
|
40
|
+
end
|
41
|
+
unless limit.nil? || limit.to_i > 0
|
42
|
+
logger.error "invalid :limit (:maxitems) - #{limit}" if logger
|
43
|
+
raise ArgumentError, "invalid limit"
|
44
|
+
end
|
45
|
+
else
|
46
|
+
if limit && limit.to_i > 0
|
47
|
+
logger.error "invalid :marker" if logger
|
48
|
+
raise ArgumentError, "missing marker"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
e = path + '/Filter'
|
53
|
+
if marker
|
54
|
+
e << "/#{marker.to_i}"
|
55
|
+
e << "/#{limit.to_i}" if limit
|
56
|
+
end
|
57
|
+
super(options.merge(:e => e))
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module KayakoClient
|
2
|
+
class UserGroup < KayakoClient::Base
|
3
|
+
|
4
|
+
USER_GROUP_TYPES = [ :guest, :registered ].freeze
|
5
|
+
|
6
|
+
property :id, :integer, :readonly => true
|
7
|
+
property :title, :string, :required => [ :put, :post ]
|
8
|
+
property :group_type, :symbol, :required => :post, :new => true
|
9
|
+
property :is_master, :boolean, :readonly => true
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module KayakoClient
|
2
|
+
class UserOrganization < KayakoClient::Base
|
3
|
+
|
4
|
+
USER_ORGANIZATION_TYPES = [ :restricted, :shared ].freeze
|
5
|
+
|
6
|
+
property :id, :integer, :readonly => true
|
7
|
+
property :name, :string, :required => [ :put, :post ]
|
8
|
+
property :organization_type, :symbol, :required => :post, :in => USER_ORGANIZATION_TYPES
|
9
|
+
property :address, :string
|
10
|
+
property :city, :string
|
11
|
+
property :state, :string
|
12
|
+
property :postal_code, :integer
|
13
|
+
property :country, :string
|
14
|
+
property :phone, :string
|
15
|
+
property :fax, :string
|
16
|
+
property :website, :string
|
17
|
+
property :date_line, :date, :readonly => true
|
18
|
+
property :last_update, :date, :readonly => true
|
19
|
+
property :sla_plan_id, :integer
|
20
|
+
property :sla_plan_expiry, :date
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'libxml'
|
2
|
+
|
3
|
+
module KayakoClient
|
4
|
+
|
5
|
+
class LibXML
|
6
|
+
include KayakoClient::Logger
|
7
|
+
include KayakoClient::XMLBackend
|
8
|
+
|
9
|
+
def initialize(document, options = {})
|
10
|
+
logger = options[:logger] if options[:logger]
|
11
|
+
if (document.start_with?('<?xml '))
|
12
|
+
@xml = ::LibXML::XML::Parser.string(document).parse
|
13
|
+
else
|
14
|
+
start = document.index('<?xml version="1.0" encoding="UTF-8"?>')
|
15
|
+
if start && start > 0
|
16
|
+
@notice = document.slice(0..start-1).gsub(%r{</?[A-Z0-9]+(?: +[A-Z]+="[^">]*")?>}i, '')
|
17
|
+
@xml = ::LibXML::XML::Parser.string(document.slice(start..document.size)).parse
|
18
|
+
else
|
19
|
+
@error = document.gsub(%r{</?[A-Z0-9]+(?: +[A-Z]+="[^">]*")?>}i, '')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
rescue ::LibXML::XML::Parser::ParseError => error
|
23
|
+
error.extend(::KayakoClient::XMLException)
|
24
|
+
raise
|
25
|
+
end
|
26
|
+
|
27
|
+
def count
|
28
|
+
if !error? && @xml.root
|
29
|
+
@xml.root.children.inject(0) do |count, node|
|
30
|
+
count += 1 if node.element?
|
31
|
+
count
|
32
|
+
end
|
33
|
+
else
|
34
|
+
0
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def each(&block)
|
39
|
+
@xml.root.each_element(&block) if !error? && @xml.root
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_hash(root = nil)
|
43
|
+
hash = {}
|
44
|
+
if !error? && @xml.root
|
45
|
+
root ||= @xml.root
|
46
|
+
root.each_attr do |attribute|
|
47
|
+
hash[attribute.name.to_sym] = attribute.value
|
48
|
+
end
|
49
|
+
root.each_element do |property|
|
50
|
+
name = property.name.to_sym
|
51
|
+
elements = property.children.inject(0) do |count, node|
|
52
|
+
count += 1 if node.element?
|
53
|
+
count
|
54
|
+
end
|
55
|
+
if elements > 0 || property.attributes?
|
56
|
+
value = to_hash(property)
|
57
|
+
if property.children.size == 1 && (property.first.text? || property.first.cdata?)
|
58
|
+
text = property.content.strip
|
59
|
+
unless text.empty?
|
60
|
+
value ||= {}
|
61
|
+
value[:contents] = text
|
62
|
+
end
|
63
|
+
end
|
64
|
+
elsif property.children.size == 1 && (property.first.text? || property.first.cdata?)
|
65
|
+
value = property.content.strip
|
66
|
+
end
|
67
|
+
unless value.nil? || value.empty?
|
68
|
+
if hash.include?(name)
|
69
|
+
hash[name] = [ hash[name] ] unless hash[name].is_a?(Array)
|
70
|
+
hash[name].push(value)
|
71
|
+
else
|
72
|
+
hash[name] = value
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
if root.children.size == 1 && (root.first.text? || root.first.cdata?)
|
77
|
+
text = root.content.strip
|
78
|
+
hash[:contents] = text unless text.empty?
|
79
|
+
end
|
80
|
+
end
|
81
|
+
hash.empty? ? nil : hash
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
|
3
|
+
module KayakoClient
|
4
|
+
class REXMLDocument
|
5
|
+
include KayakoClient::Logger
|
6
|
+
include KayakoClient::XMLBackend
|
7
|
+
|
8
|
+
def initialize(document, options = {})
|
9
|
+
logger = options[:logger] if options[:logger]
|
10
|
+
if (document.start_with?('<?xml '))
|
11
|
+
@xml = REXML::Document.new(document)
|
12
|
+
else
|
13
|
+
start = document.index('<?xml version="1.0" encoding="UTF-8"?>')
|
14
|
+
if start && start > 0
|
15
|
+
@notice = document.slice(0..start-1).gsub(%r{</?[A-Z0-9]+(?: +[A-Z]+="[^">]*")?>}i, '')
|
16
|
+
@xml = REXML::Document.new(document.slice(start..document.size))
|
17
|
+
else
|
18
|
+
@error = document.gsub(%r{</?[A-Z0-9]+(?: +[A-Z]+="[^">]*")?>}i, '')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
rescue REXML::ParseException => error
|
22
|
+
error.extend(::KayakoClient::XMLException)
|
23
|
+
raise
|
24
|
+
end
|
25
|
+
|
26
|
+
def count
|
27
|
+
if !error? && @xml.root
|
28
|
+
@xml.root.elements.count
|
29
|
+
else
|
30
|
+
0
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def each(&block)
|
35
|
+
@xml.root.elements.each(&block) if !error? && @xml.root
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_hash(root = nil)
|
39
|
+
hash = {}
|
40
|
+
if !error? && @xml.root
|
41
|
+
root ||= @xml.root
|
42
|
+
root.attributes.each do |attribute, value|
|
43
|
+
hash[attribute.to_sym] = value
|
44
|
+
end
|
45
|
+
root.elements.each do |property|
|
46
|
+
name = property.name.to_sym
|
47
|
+
if property.has_elements? || property.has_attributes?
|
48
|
+
value = to_hash(property)
|
49
|
+
if property.has_text?
|
50
|
+
text = property.text.strip
|
51
|
+
unless text.empty?
|
52
|
+
value ||= {}
|
53
|
+
value[:contents] = text
|
54
|
+
end
|
55
|
+
end
|
56
|
+
elsif property.has_text?
|
57
|
+
value = property.text.strip
|
58
|
+
end
|
59
|
+
unless value.nil? || value.empty?
|
60
|
+
if hash.include?(name)
|
61
|
+
hash[name] = [ hash[name] ] unless hash[name].is_a?(Array)
|
62
|
+
hash[name].push(value)
|
63
|
+
else
|
64
|
+
hash[name] = value
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
if root.has_text?
|
69
|
+
text = root.text.strip
|
70
|
+
hash[:contents] = text unless text.empty?
|
71
|
+
end
|
72
|
+
end
|
73
|
+
hash.empty? ? nil : hash
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module KayakoClient
|
2
|
+
module XML
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
def xml_backend=(backend)
|
9
|
+
if backend.is_a?(String)
|
10
|
+
raise ArgumentError, "invalid XML backend: #{backend}" unless backend =~ /^[A-Za-z_]+$/
|
11
|
+
file = backend.gsub(/([a-z])([A-Z])/, '\1_\2').gsub(/([A-Z])([A-Z][a-z])/, '\1_\2').downcase
|
12
|
+
require "kayako_client/xml/#{file}"
|
13
|
+
backend = KayakoClient.const_get(backend)
|
14
|
+
end
|
15
|
+
if backend.is_a?(Class)
|
16
|
+
if backend.included_modules.include?(KayakoClient::XMLBackend)
|
17
|
+
@xml_backend = backend
|
18
|
+
else
|
19
|
+
raise ArgumentError, "invalid XML backend: #{backend.name}"
|
20
|
+
end
|
21
|
+
else
|
22
|
+
raise ArgumentError, "unsupported XML backend"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def xml_backend
|
27
|
+
@xml_backend ||= self.class.xml_backend
|
28
|
+
end
|
29
|
+
|
30
|
+
module ClassMethods
|
31
|
+
|
32
|
+
def xml_backend=(backend)
|
33
|
+
if backend.is_a?(String)
|
34
|
+
raise ArgumentError, "invalid XML backend: #{backend}" unless backend =~ /^[A-Za-z_]+$/
|
35
|
+
file = backend.gsub(/([a-z])([A-Z])/, '\1_\2').gsub(/([A-Z])([A-Z][a-z])/, '\1_\2').downcase
|
36
|
+
require "kayako_client/xml/#{file}"
|
37
|
+
backend = KayakoClient.const_get(backend)
|
38
|
+
end
|
39
|
+
if backend.is_a?(Class)
|
40
|
+
if backend.included_modules.include?(KayakoClient::XMLBackend)
|
41
|
+
@@xml_backend = backend
|
42
|
+
else
|
43
|
+
raise ArgumentError, "invalid XML backend: #{backend.name}"
|
44
|
+
end
|
45
|
+
else
|
46
|
+
raise ArgumentError, "unsupported XML backend"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def xml_backend
|
51
|
+
begin
|
52
|
+
require 'kayako_client/xml/lib_xml'
|
53
|
+
@@xml_backend ||= KayakoClient::LibXML
|
54
|
+
rescue LoadError
|
55
|
+
require 'kayako_client/xml/rexml_document'
|
56
|
+
@@xml_backend ||= KayakoClient::REXMLDocument
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module KayakoClient
|
2
|
+
|
3
|
+
module XMLBackend
|
4
|
+
|
5
|
+
def initialize(document)
|
6
|
+
raise NotImplementedError, "not implemented"
|
7
|
+
end
|
8
|
+
|
9
|
+
def count
|
10
|
+
raise NotImplementedError, "not implemented"
|
11
|
+
end
|
12
|
+
|
13
|
+
def each(&block)
|
14
|
+
raise NotImplementedError, "not implemented"
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_hash(root = nil)
|
18
|
+
raise NotImplementedError, "not implemented"
|
19
|
+
end
|
20
|
+
|
21
|
+
def notice?
|
22
|
+
defined?(@notice)
|
23
|
+
end
|
24
|
+
|
25
|
+
def error?
|
26
|
+
defined?(@error)
|
27
|
+
end
|
28
|
+
|
29
|
+
def notice
|
30
|
+
@notice || nil
|
31
|
+
end
|
32
|
+
|
33
|
+
def error
|
34
|
+
@error || nil
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
module XMLException
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|