KayakoClient 1.0.2 → 1.1.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.
Files changed (84) hide show
  1. data/lib/kayako_client.rb +31 -0
  2. data/lib/kayako_client/base.rb +23 -0
  3. data/lib/kayako_client/custom_field.rb +14 -0
  4. data/lib/kayako_client/department.rb +18 -3
  5. data/lib/kayako_client/http/http.rb +14 -0
  6. data/lib/kayako_client/http/http_backend.rb +14 -0
  7. data/lib/kayako_client/http/http_client.rb +14 -0
  8. data/lib/kayako_client/http/http_response.rb +14 -0
  9. data/lib/kayako_client/http/net_http.rb +14 -0
  10. data/lib/kayako_client/knowledgebase_article.rb +131 -0
  11. data/lib/kayako_client/knowledgebase_attachment.rb +59 -0
  12. data/lib/kayako_client/knowledgebase_category.rb +71 -0
  13. data/lib/kayako_client/knowledgebase_comment.rb +32 -0
  14. data/lib/kayako_client/mixins/api.rb +14 -0
  15. data/lib/kayako_client/mixins/article_client.rb +76 -0
  16. data/lib/kayako_client/mixins/attachment.rb +16 -1
  17. data/lib/kayako_client/mixins/authentication.rb +14 -0
  18. data/lib/kayako_client/mixins/client.rb +300 -0
  19. data/lib/kayako_client/mixins/comment_object.rb +102 -0
  20. data/lib/kayako_client/mixins/convert_api.rb +39 -0
  21. data/lib/kayako_client/mixins/creator_api.rb +44 -0
  22. data/lib/kayako_client/mixins/knowledgebase_article_api.rb +69 -0
  23. data/lib/kayako_client/mixins/knowledgebase_category_client.rb +51 -0
  24. data/lib/kayako_client/mixins/logger.rb +14 -0
  25. data/lib/kayako_client/mixins/news_category_client.rb +51 -0
  26. data/lib/kayako_client/mixins/news_client.rb +51 -0
  27. data/lib/kayako_client/mixins/object.rb +24 -7
  28. data/lib/kayako_client/mixins/post_client.rb +14 -0
  29. data/lib/kayako_client/mixins/staff_visibility_api.rb +14 -0
  30. data/lib/kayako_client/mixins/ticket_api.rb +14 -0
  31. data/lib/kayako_client/mixins/ticket_client.rb +14 -0
  32. data/lib/kayako_client/mixins/troubleshooter_step_api.rb +69 -0
  33. data/lib/kayako_client/mixins/troubleshooter_step_client.rb +76 -0
  34. data/lib/kayako_client/mixins/user_visibility_api.rb +14 -0
  35. data/lib/kayako_client/news_category.rb +29 -0
  36. data/lib/kayako_client/news_comment.rb +32 -0
  37. data/lib/kayako_client/news_item.rb +81 -0
  38. data/lib/kayako_client/news_subscriber.rb +33 -0
  39. data/lib/kayako_client/staff.rb +14 -0
  40. data/lib/kayako_client/staff_group.rb +14 -0
  41. data/lib/kayako_client/ticket.rb +24 -1
  42. data/lib/kayako_client/ticket_attachment.rb +18 -0
  43. data/lib/kayako_client/ticket_count.rb +14 -0
  44. data/lib/kayako_client/ticket_custom_field.rb +14 -0
  45. data/lib/kayako_client/ticket_note.rb +14 -1
  46. data/lib/kayako_client/ticket_post.rb +15 -0
  47. data/lib/kayako_client/ticket_priority.rb +14 -0
  48. data/lib/kayako_client/ticket_status.rb +14 -0
  49. data/lib/kayako_client/ticket_time_track.rb +14 -0
  50. data/lib/kayako_client/ticket_type.rb +14 -0
  51. data/lib/kayako_client/troubleshooter_attachment.rb +68 -0
  52. data/lib/kayako_client/troubleshooter_category.rb +51 -0
  53. data/lib/kayako_client/troubleshooter_comment.rb +32 -0
  54. data/lib/kayako_client/troubleshooter_step.rb +100 -0
  55. data/lib/kayako_client/user.rb +42 -0
  56. data/lib/kayako_client/user_group.rb +14 -0
  57. data/lib/kayako_client/user_organization.rb +14 -0
  58. data/lib/kayako_client/xml/lib_xml.rb +14 -0
  59. data/lib/kayako_client/xml/rexml_document.rb +14 -0
  60. data/lib/kayako_client/xml/xml.rb +14 -0
  61. data/lib/kayako_client/xml/xml_backend.rb +14 -0
  62. data/test/test_attachment.rb +77 -0
  63. data/test/test_client.rb +191 -0
  64. data/test/test_configuration.rb +110 -0
  65. data/test/test_count.rb +162 -0
  66. data/test/test_custom_field.rb +86 -0
  67. data/test/test_department.rb +136 -0
  68. data/test/test_http.rb +34 -0
  69. data/test/test_knowledgebase.rb +155 -0
  70. data/test/test_news.rb +117 -0
  71. data/test/test_note.rb +64 -0
  72. data/test/test_post.rb +64 -0
  73. data/test/test_priority.rb +46 -0
  74. data/test/test_properties.rb +114 -0
  75. data/test/test_staff.rb +77 -0
  76. data/test/test_status.rb +52 -0
  77. data/test/test_ticket.rb +152 -0
  78. data/test/test_ticket_custom_field.rb +193 -0
  79. data/test/test_time_track.rb +68 -0
  80. data/test/test_troubleshooter.rb +106 -0
  81. data/test/test_type.rb +65 -0
  82. data/test/test_user.rb +95 -0
  83. data/test/test_xml.rb +183 -0
  84. metadata +89 -42
@@ -1,3 +1,17 @@
1
+ #######################################################################
2
+ #
3
+ # Kayako Ruby REST API library
4
+ # _____________________________________________________________________
5
+ #
6
+ # @author Andriy Lesyuk
7
+ #
8
+ # @package KayakoClient
9
+ # @copyright Copyright (c) 2011-2013, Kayako
10
+ # @license FreeBSD
11
+ # @link http://forge.kayako.com/projects/kayako-ruby-api-library
12
+ #
13
+ #######################################################################
14
+
1
15
  require 'kayako_client/http/http_response'
2
16
  require 'kayako_client/http/http_backend'
3
17
  require 'kayako_client/http/http'
@@ -10,6 +24,11 @@ require 'kayako_client/mixins/object'
10
24
  require 'kayako_client/mixins/client'
11
25
  require 'kayako_client/mixins/ticket_client'
12
26
  require 'kayako_client/mixins/post_client'
27
+ require 'kayako_client/mixins/article_client'
28
+ require 'kayako_client/mixins/knowledgebase_category_client'
29
+ require 'kayako_client/mixins/news_category_client'
30
+ require 'kayako_client/mixins/news_client'
31
+ require 'kayako_client/mixins/troubleshooter_step_client'
13
32
  require 'kayako_client/mixins/logger'
14
33
  require 'kayako_client/mixins/authentication'
15
34
  require 'kayako_client/mixins/attachment'
@@ -20,6 +39,14 @@ require 'kayako_client/mixins/staff_visibility_api'
20
39
  require 'kayako_client/base'
21
40
  require 'kayako_client/custom_field'
22
41
  require 'kayako_client/department'
42
+ require 'kayako_client/knowledgebase_article'
43
+ require 'kayako_client/knowledgebase_attachment'
44
+ require 'kayako_client/knowledgebase_category'
45
+ require 'kayako_client/knowledgebase_comment'
46
+ require 'kayako_client/news_category'
47
+ require 'kayako_client/news_comment'
48
+ require 'kayako_client/news_item'
49
+ require 'kayako_client/news_subscriber'
23
50
  require 'kayako_client/staff'
24
51
  require 'kayako_client/staff_group'
25
52
  require 'kayako_client/ticket'
@@ -32,6 +59,10 @@ require 'kayako_client/ticket_status'
32
59
  require 'kayako_client/ticket_time_track'
33
60
  require 'kayako_client/ticket_type'
34
61
  require 'kayako_client/ticket_count'
62
+ require 'kayako_client/troubleshooter_attachment'
63
+ require 'kayako_client/troubleshooter_category'
64
+ require 'kayako_client/troubleshooter_comment'
65
+ require 'kayako_client/troubleshooter_step'
35
66
  require 'kayako_client/user'
36
67
  require 'kayako_client/user_group'
37
68
  require 'kayako_client/user_organization'
@@ -1,3 +1,17 @@
1
+ #######################################################################
2
+ #
3
+ # Kayako Ruby REST API library
4
+ # _____________________________________________________________________
5
+ #
6
+ # @author Andriy Lesyuk
7
+ #
8
+ # @package KayakoClient
9
+ # @copyright Copyright (c) 2011-2013, Kayako
10
+ # @license FreeBSD
11
+ # @link http://forge.kayako.com/projects/kayako-ruby-api-library
12
+ #
13
+ #######################################################################
14
+
1
15
  module KayakoClient
2
16
 
3
17
  class Base
@@ -95,4 +109,13 @@ module KayakoClient
95
109
  class Tickets < Base
96
110
  end
97
111
 
112
+ class Knowledgebase < Base
113
+ end
114
+
115
+ class News < Base
116
+ end
117
+
118
+ class Troubleshooter < Base
119
+ end
120
+
98
121
  end
@@ -1,3 +1,17 @@
1
+ #######################################################################
2
+ #
3
+ # Kayako Ruby REST API library
4
+ # _____________________________________________________________________
5
+ #
6
+ # @author Andriy Lesyuk
7
+ #
8
+ # @package KayakoClient
9
+ # @copyright Copyright (c) 2011-2013, Kayako
10
+ # @license FreeBSD
11
+ # @link http://forge.kayako.com/projects/kayako-ruby-api-library
12
+ #
13
+ #######################################################################
14
+
1
15
  module KayakoClient
2
16
 
3
17
  class CustomFieldOption < KayakoClient::Base
@@ -1,3 +1,17 @@
1
+ #######################################################################
2
+ #
3
+ # Kayako Ruby REST API library
4
+ # _____________________________________________________________________
5
+ #
6
+ # @author Andriy Lesyuk
7
+ #
8
+ # @package KayakoClient
9
+ # @copyright Copyright (c) 2011-2013, Kayako
10
+ # @license FreeBSD
11
+ # @link http://forge.kayako.com/projects/kayako-ruby-api-library
12
+ #
13
+ #######################################################################
14
+
1
15
  require 'kayako_client/mixins/user_visibility_api'
2
16
 
3
17
  require 'kayako_client/user_group'
@@ -7,14 +21,15 @@ module KayakoClient
7
21
  include KayakoClient::UserVisibilityAPI
8
22
 
9
23
  DEPARTMENT_TYPES = [ :public, :private ].freeze
10
- DEPARTMENT_MODULES = [ :tickets, :livechat ].freeze
24
+ DEPARTMENT_APPS = [ :tickets, :livechat ].freeze
11
25
 
12
- # NOTE: if :parent_department_id is set :module should have the same value
26
+ # NOTE: if :parent_department_id is set :app should have the corresponding value
13
27
 
14
28
  property :id, :integer, :readonly => true
15
29
  property :title, :string, :required => [ :put, :post ]
16
30
  property :type, :symbol, :in => DEPARTMENT_TYPES, :required => :post
17
- property :module, :symbol, :in => DEPARTMENT_MODULES, :required => :post, :new => true
31
+ property :module, :symbol, :in => DEPARTMENT_APPS, :readonly => true
32
+ property :app, :symbol, :in => DEPARTMENT_APPS, :required => :post, :new => true
18
33
  property :display_order, :integer
19
34
  property :parent_department_id, :integer
20
35
  property :user_visibility_custom, :boolean
@@ -1,3 +1,17 @@
1
+ #######################################################################
2
+ #
3
+ # Kayako Ruby REST API library
4
+ # _____________________________________________________________________
5
+ #
6
+ # @author Andriy Lesyuk
7
+ #
8
+ # @package KayakoClient
9
+ # @copyright Copyright (c) 2011-2013, Kayako
10
+ # @license FreeBSD
11
+ # @link http://forge.kayako.com/projects/kayako-ruby-api-library
12
+ #
13
+ #######################################################################
14
+
1
15
  module KayakoClient
2
16
  module HTTP
3
17
 
@@ -1,3 +1,17 @@
1
+ #######################################################################
2
+ #
3
+ # Kayako Ruby REST API library
4
+ # _____________________________________________________________________
5
+ #
6
+ # @author Andriy Lesyuk
7
+ #
8
+ # @package KayakoClient
9
+ # @copyright Copyright (c) 2011-2013, Kayako
10
+ # @license FreeBSD
11
+ # @link http://forge.kayako.com/projects/kayako-ruby-api-library
12
+ #
13
+ #######################################################################
14
+
1
15
  require 'uri'
2
16
 
3
17
  module KayakoClient
@@ -1,3 +1,17 @@
1
+ #######################################################################
2
+ #
3
+ # Kayako Ruby REST API library
4
+ # _____________________________________________________________________
5
+ #
6
+ # @author Andriy Lesyuk
7
+ #
8
+ # @package KayakoClient
9
+ # @copyright Copyright (c) 2011-2013, Kayako
10
+ # @license FreeBSD
11
+ # @link http://forge.kayako.com/projects/kayako-ruby-api-library
12
+ #
13
+ #######################################################################
14
+
1
15
  require 'httpclient'
2
16
 
3
17
  module KayakoClient
@@ -1,3 +1,17 @@
1
+ #######################################################################
2
+ #
3
+ # Kayako Ruby REST API library
4
+ # _____________________________________________________________________
5
+ #
6
+ # @author Andriy Lesyuk
7
+ #
8
+ # @package KayakoClient
9
+ # @copyright Copyright (c) 2011-2013, Kayako
10
+ # @license FreeBSD
11
+ # @link http://forge.kayako.com/projects/kayako-ruby-api-library
12
+ #
13
+ #######################################################################
14
+
1
15
  module KayakoClient
2
16
 
3
17
  class HTTPResponse
@@ -1,3 +1,17 @@
1
+ #######################################################################
2
+ #
3
+ # Kayako Ruby REST API library
4
+ # _____________________________________________________________________
5
+ #
6
+ # @author Andriy Lesyuk
7
+ #
8
+ # @package KayakoClient
9
+ # @copyright Copyright (c) 2011-2013, Kayako
10
+ # @license FreeBSD
11
+ # @link http://forge.kayako.com/projects/kayako-ruby-api-library
12
+ #
13
+ #######################################################################
14
+
1
15
  require 'net/https'
2
16
 
3
17
  module KayakoClient
@@ -0,0 +1,131 @@
1
+ #######################################################################
2
+ #
3
+ # Kayako Ruby REST API library
4
+ # _____________________________________________________________________
5
+ #
6
+ # @author Andriy Lesyuk
7
+ #
8
+ # @package KayakoClient
9
+ # @copyright Copyright (c) 2011-2013, Kayako
10
+ # @license FreeBSD
11
+ # @link http://forge.kayako.com/projects/kayako-ruby-api-library
12
+ #
13
+ #######################################################################
14
+
15
+ require 'kayako_client/mixins/convert_api'
16
+ require 'kayako_client/mixins/creator_api'
17
+
18
+ require 'kayako_client/knowledgebase_category'
19
+
20
+ require 'kayako_client/staff'
21
+ require 'kayako_client/user'
22
+
23
+ module KayakoClient
24
+
25
+ class KnowledgebaseAttachment < KayakoClient::Knowledgebase
26
+ end
27
+
28
+ class KnowledgebaseArticle < KayakoClient::Knowledgebase
29
+ include KayakoClient::ConvertAPI
30
+ include KayakoClient::CreatorAPI
31
+ include KayakoClient::ArticleClient
32
+
33
+ path '/Knowledgebase/Article'
34
+
35
+ CREATOR_USER = 1
36
+ CREATOR_STAFF = 2
37
+
38
+ STATUS_PUBLISHED = 1
39
+ STATUS_DRAFT = 2
40
+ STATUS_PENDINGAPPROVAL = 3
41
+
42
+ property :kb_article_id, :integer, :readonly => true
43
+ property :contents, :string, :required => [ :put, :post ]
44
+ property :contents_text, :string, :readonly => true
45
+ property :category_ids, [ :integer ], :get => :categories, :set => :categoryid
46
+ property :creator_type, :integer, :readonly => true, :get => :creator, :range => 1..2
47
+ property :creator_id, :integer, :required => :post
48
+ property :is_edited, :boolean, :readonly => true
49
+ property :subject, :string, :required => [ :put, :post ]
50
+ property :edited_date_line, :date, :readonly => true
51
+ property :edited_staff_id, :integer, :required => :put
52
+ property :views, :integer, :readonly => true
53
+ property :is_featured, :boolean
54
+ property :allow_comments, :boolean
55
+ property :total_comments, :integer, :readonly => true
56
+ property :has_attachments, :boolean, :readonly => true
57
+ property :date_line, :date, :readonly => true
58
+ property :article_status, :integer, :range => 1..3
59
+ property :article_rating, :float, :readonly => true
60
+ property :rating_hits, :integer, :readonly => true
61
+ property :rating_count, :integer, :readonly => true
62
+
63
+ property :attachments, [ :object ], :class => KnowledgebaseAttachment
64
+
65
+ associate :categories, :category_ids, KnowledgebaseCategory
66
+ associate :edited_staff, :edited_staff_id, Staff
67
+
68
+ alias_method :id, :kb_article_id
69
+
70
+ def in_root_category?
71
+ !category_ids.nil? && category_ids.include?(0)
72
+ end
73
+
74
+ def in_category?(category)
75
+ category.respond_to?(:to_i) && !category_ids.nil? && category_ids.include?(category.to_i)
76
+ end
77
+
78
+ if method_defined?(:categories)
79
+ remove_method(:categories)
80
+ end
81
+
82
+ def categories
83
+ if @associated.has_key?(:category_ids)
84
+ @associated[:category_ids]
85
+ elsif instance_variable_defined?(:@category_ids)
86
+ category_ids = instance_variable_get(:@category_ids)
87
+ if category_ids.is_a?(Array)
88
+ @associated[:category_ids] = category_ids.inject([]) do |array, i|
89
+ array << KnowledgebaseCategory.get(i.to_i, inherited_options) unless i.to_i == 0
90
+ array
91
+ end
92
+ else
93
+ @associated[:category_ids] = nil
94
+ end
95
+ else
96
+ @associated[:category_ids] = nil
97
+ end
98
+ end
99
+
100
+ def self.all(*args)
101
+ options = args.last.is_a?(Hash) ? args.pop : {}
102
+ if args.size > 0
103
+ if args.size == 1
104
+ options.merge!(:e => "#{path}/ListAll/#{args.first.to_i}")
105
+ else
106
+ raise ArgumentError, "too many arguments"
107
+ end
108
+ end
109
+ super(options)
110
+ end
111
+
112
+ private
113
+
114
+ def validate(method, params)
115
+ if method == :put
116
+ unless changes.include?(:edited_staff_id) && params[:edited_staff_id].to_i > 0
117
+ raise ArgumentError, ":edited_staff_id is required"
118
+ end
119
+ end
120
+ end
121
+
122
+ def assign_value(type, value, options = {})
123
+ if type == :object && value.is_a?(Hash) && options[:class] == KnowledgebaseAttachment
124
+ value[:kb_article_id] = kb_article_id unless value.has_key?(:kbarticleid)
125
+ end
126
+ super(type, value, options)
127
+ end
128
+
129
+ end
130
+
131
+ end
@@ -0,0 +1,59 @@
1
+ #######################################################################
2
+ #
3
+ # Kayako Ruby REST API library
4
+ # _____________________________________________________________________
5
+ #
6
+ # @author Andriy Lesyuk
7
+ #
8
+ # @package KayakoClient
9
+ # @copyright Copyright (c) 2011-2013, Kayako
10
+ # @license FreeBSD
11
+ # @link http://forge.kayako.com/projects/kayako-ruby-api-library
12
+ #
13
+ #######################################################################
14
+
15
+ require 'kayako_client/mixins/knowledgebase_article_api'
16
+
17
+ require 'kayako_client/knowledgebase_article'
18
+
19
+ module KayakoClient
20
+ class KnowledgebaseAttachment < KayakoClient::Knowledgebase
21
+ include KayakoClient::KnowledgebaseArticleAPI
22
+ include KayakoClient::Attachment
23
+
24
+ path '/Knowledgebase/Attachment'
25
+
26
+ supports :all, :get, :post, :delete
27
+
28
+ property :id, :integer, :readonly => true
29
+ property :kb_article_id, :integer, :required => :post
30
+ property :file_name, :string, :required => :post
31
+ property :file_size, :integer, :readonly => true
32
+ property :file_type, :string, :readonly => true
33
+ property :date_line, :date, :readonly => true
34
+ property :contents, :binary, :required => :post, :new => true
35
+ property :link, :string, :readonly => true
36
+
37
+ associate :article, :kb_article_id, KnowledgebaseArticle
38
+
39
+ if method_defined?(:contents)
40
+ remove_method(:contents)
41
+ end
42
+
43
+ def contents
44
+ if instance_variable_defined?(:@contents)
45
+ instance_variable_get(:@contents)
46
+ elsif !new? && id && kb_article_id && id > 0 && kb_article_id > 0
47
+ logger.debug "contents are missing - trying to reload" if logger
48
+ if reload!(:e => "#{self.class.path}/#{kb_article_id.to_i}/#{id.to_i}") && instance_variable_defined?(:@contents)
49
+ instance_variable_get(:@contents)
50
+ else
51
+ instance_variable_set(:@contents, nil)
52
+ end
53
+ else
54
+ nil
55
+ end
56
+ end
57
+
58
+ end
59
+ end
@@ -0,0 +1,71 @@
1
+ #######################################################################
2
+ #
3
+ # Kayako Ruby REST API library
4
+ # _____________________________________________________________________
5
+ #
6
+ # @author Andriy Lesyuk
7
+ #
8
+ # @package KayakoClient
9
+ # @copyright Copyright (c) 2011-2013, Kayako
10
+ # @license FreeBSD
11
+ # @link http://forge.kayako.com/projects/kayako-ruby-api-library
12
+ #
13
+ #######################################################################
14
+
15
+ require 'kayako_client/mixins/convert_api'
16
+
17
+ require 'kayako_client/staff'
18
+ require 'kayako_client/user_group'
19
+ require 'kayako_client/staff_group'
20
+
21
+ module KayakoClient
22
+ class KnowledgebaseCategory < KayakoClient::Knowledgebase
23
+ include KayakoClient::ConvertAPI
24
+ include KayakoClient::UserVisibilityAPI
25
+ include KayakoClient::StaffVisibilityAPI
26
+ include KayakoClient::KnowledgebaseCategoryClient
27
+
28
+ path '/Knowledgebase/Category'
29
+
30
+ TYPE_GLOBAL = 1
31
+ TYPE_PUBLIC = 2
32
+ TYPE_PRIVATE = 3
33
+ TYPE_INHERIT = 4
34
+
35
+ SORT_INHERIT = 1
36
+ SORT_TITLE = 2
37
+ SORT_RATING = 3
38
+ SORT_CREATIONDATE = 4
39
+ SORT_DISPLAYORDER = 5
40
+
41
+ property :id, :integer, :readonly => true
42
+ property :parent_kb_category_id, :integer
43
+ property :staff_id, :integer, :new => true
44
+ property :title, :string, :required => [ :put, :post ]
45
+ property :total_articles, :integer, :readonly => true
46
+ property :category_type, :integer, :required => :post, :range => 1..4
47
+ property :display_order, :integer
48
+ property :allow_comments, :boolean
49
+ property :allow_rating, :boolean
50
+ property :is_published, :boolean
51
+ property :article_sort_order, :integer, :range => 1..5
52
+ property :user_visibility_custom, :boolean
53
+ property :user_group_ids, [ :integer ], :get => :usergroupidlist, :set => :usergroupidlist, :condition => { :user_visibility_custom => true }
54
+ property :staff_visibility_custom, :boolean
55
+ property :staff_group_ids, [ :integer ], :get => :staffgroupidlist, :set => :staffgroupidlist, :condition => { :staff_visibility_custom => true }
56
+
57
+ associate :parent_category, :parent_kb_category_id, KnowledgebaseCategory
58
+ associate :staff, :staff_id, Staff
59
+ associate :user_groups, :user_group_ids, UserGroup
60
+ associate :staff_groups, :staff_group_ids, StaffGroup
61
+
62
+ def has_parent_category?
63
+ !parent_kb_category_id.nil? && parent_kb_category_id > 0
64
+ end
65
+
66
+ def parent_is_root?
67
+ !parent_kb_category_id.nil? && parent_kb_category_id == 0
68
+ end
69
+
70
+ end
71
+ end