limdesk_api 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 98a9417eaadaf56f00c999cd56a4f54d86c82d15
4
+ data.tar.gz: fbccda463576a535adab7f5e0de327e7984202f9
5
+ SHA512:
6
+ metadata.gz: 1cfb8ffaade21c04901a4bd485c6c1ccfe7d698783fd91524ec3af437b1d6b65dbbc676854d3371212bee0dbcb02d2326df242f125fae655c70172abd2834990
7
+ data.tar.gz: f8a6610416d9eed8347a55301e033730b94c14e98e0ded7e24bfbc0dfe0e05480c677e234b9de788f7ff5c00926fb5bba1916b3e95a47f13bacf0ec94bf6d864
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in limdesk_api.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Grzegorz Siehień Limtel Sp. z o.o.
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,121 @@
1
+ # LimdeskApi
2
+
3
+ ## Installation
4
+
5
+ Add this line to your application's Gemfile:
6
+
7
+ gem 'limdesk_api'
8
+
9
+ And then execute:
10
+
11
+ $ bundle
12
+
13
+ Or install it yourself as:
14
+
15
+ $ gem install limdesk_api
16
+
17
+ ## Usage
18
+
19
+ This gem will allow you to interact with Limdesk API. [Limdesk.com](http://limdesk.com) is a lightweight, multichannel customer support solution.
20
+
21
+ API is available to free and premium users. You can generate your APIKEY in Settings/Integration/API section.
22
+
23
+ This gem wrappes Limdesk API into OpenStruct (RecursiveOpenStruct) objects. For more information about API check the [official docs](http://help.limdesk.com/en/category/458/API_documentation). Current API covers basic, most common actions. More advanced version is currenty under development.
24
+
25
+ #### Connecting to API
26
+
27
+ ```ruby
28
+ LimdeskApi.configure do |lim|
29
+ lim.key = '<YOUR API KEY>'
30
+ lim.version = 1
31
+ end
32
+ ```
33
+
34
+ #### Tickets
35
+
36
+ ```ruby
37
+
38
+ tickets = LimdeskApi::Ticket.all
39
+
40
+ tickets.count
41
+ 63
42
+
43
+ tickets.first.title
44
+ "Hello World"
45
+
46
+ ticket = LimdeskApi::Ticket.get(44)
47
+
48
+ ticket.title
49
+ "Hello"
50
+
51
+ ticket.client.name
52
+ "John Smith"
53
+
54
+ ticket.answer(content: 'this is a private comment', answer_type: :priv)
55
+ ticket.answer(content: 'dear customer, it is solved', answer_type: :pub)
56
+
57
+ ticket.close(content: 'its solved', type: :resolved)
58
+ ticket.reopen
59
+ ticket.close(content: 'spam', type: :rejected)
60
+
61
+ ticket2 = LimdeskApi::Ticket.create title: "a ticket", content: "client's probem", reported_by: :mail, client_id: -1
62
+
63
+ # reported_by can be mail, phone, other, chat
64
+ # client_id => -1 means "new anonymous clinet"
65
+
66
+ ticket2.ok?
67
+ true
68
+ ticket2.title
69
+ "a ticket"
70
+
71
+ ```
72
+
73
+ #### Activities
74
+
75
+ ```ruby
76
+
77
+ acts = LimdeskApi::Activity.all
78
+
79
+ act = LimdeskApi::Activity.create( :content=>"client has logged into website",
80
+ :client_id=>55 )
81
+ ```
82
+
83
+
84
+ #### Clients
85
+
86
+
87
+ ```ruby
88
+
89
+ cls = LimdeskApi::Client.all
90
+
91
+ cls.first.name
92
+ "John Smith"
93
+
94
+ client = LimdeskApi::Client.create( :name =>"John Smith",
95
+ :nippesel =>"15012406496",
96
+ :phone =>"223111789",
97
+ :email =>"email@example.com",
98
+ :adress =>"Plain Street 149 85-058 Warsaw" )
99
+ client.ok?
100
+ true
101
+
102
+ client.delete!
103
+ true
104
+
105
+ client2 = LimdeskApi::Client.get(55)
106
+ client2.contacts.first
107
+
108
+ ```
109
+
110
+ ## TODO
111
+
112
+ * tests
113
+ * lazy loading
114
+
115
+ ## Contributing
116
+
117
+ 1. Fork it ( https://github.com/[my-github-username]/limdesk/fork )
118
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
119
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
120
+ 4. Push to the branch (`git push origin my-new-feature`)
121
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,129 @@
1
+ require "faraday"
2
+ require "recursive_open_struct"
3
+ require "faraday_middleware"
4
+ require "json"
5
+ require "limdesk_api/version"
6
+ require "limdesk_api/client"
7
+ require "limdesk_api/activity"
8
+ require "limdesk_api/ticket"
9
+
10
+ module LimdeskApi
11
+
12
+ ENDPOINT = 'https://cloud.limdesk.com'
13
+
14
+ KNOWN_OBJS = {
15
+ ticket: :tickets,
16
+ activity: :activities,
17
+ client: :clients,
18
+ }
19
+
20
+ def self.configure
21
+ yield self
22
+ @connection = Faraday.new(:url => ENDPOINT) do |faraday|
23
+ faraday.response :json, :content_type => /\bjson$/
24
+ faraday.adapter Faraday.default_adapter
25
+ faraday.use Faraday::Response::Logger if @debug
26
+ end
27
+ @prefix = "/api/v#{@version}"
28
+ return self
29
+ end
30
+
31
+ def self.key=(key)
32
+ return @key = key
33
+ end
34
+
35
+ def self.version=(version)
36
+ return @version = version
37
+ end
38
+
39
+ def self.debug=(debug)
40
+ return @debug = debug
41
+ end
42
+
43
+ def self.get_one(params)
44
+ resp = @connection.get do |req|
45
+ req.url "#{@prefix}/#{LimdeskApi::KNOWN_OBJS[params[:object]]}/#{params[:id]}"
46
+ req.params[:key] = @key
47
+ end
48
+ case resp.status
49
+ when 200
50
+ raise "LimdeskApiError" unless resp.body.kind_of?(Hash) && resp.body['status'] == "ok"
51
+ return nil if resp.body[params[:object].to_s].nil?
52
+ return resp.body[params[:object].to_s]
53
+ when 404
54
+ return nil
55
+ else
56
+ raise "LimdeskApiErrorFatal"
57
+ end
58
+ end
59
+
60
+ def self.get_many(params)
61
+ resp = @connection.get do |req|
62
+ req.url "#{@prefix}/#{LimdeskApi::KNOWN_OBJS[params[:object]]}"
63
+ req.params[:key] = @key
64
+ req.params[:page] = params[:page] if params[:page].to_i > 0
65
+ end
66
+ case resp.status
67
+ when 200
68
+ raise "LimdeskApiError" unless resp.body.kind_of?(Hash) && resp.body['status'] == "ok"
69
+ raise "LimdeskApiError" unless resp.body['page'] && resp.body['total_pages']
70
+ raise "LimdeskApiError" unless resp.body[LimdeskApi::KNOWN_OBJS[params[:object]].to_s]
71
+ return { :page=>resp.body['page'],
72
+ :total_pages=>resp.body['total_pages'],
73
+ :objects=>resp.body[LimdeskApi::KNOWN_OBJS[params[:object]].to_s] }
74
+ else
75
+ raise "LimdeskApiErrorFatal"
76
+ end
77
+ end
78
+
79
+ def self.create(params)
80
+ resp = @connection.post do |req|
81
+ req.url "#{@prefix}/#{LimdeskApi::KNOWN_OBJS[params[:object]]}"
82
+ req.params[:key] = @key
83
+ req.body = params[:params].to_json
84
+ end
85
+ case resp.status
86
+ when 200
87
+ raise "LimdeskApiError" unless resp.body.kind_of?(Hash) && resp.body['status']
88
+ return { error: true, msg: resp.body['msg'] } if resp.body['status'] == "error"
89
+ raise "LimdeskApiError" if resp.body[params[:object].to_s].nil?
90
+ return resp.body[params[:object].to_s]
91
+ else
92
+ raise "LimdeskApiErrorFatal"
93
+ end
94
+ end
95
+
96
+ def self.put(params)
97
+ self.update(:put, params)
98
+ end
99
+
100
+ def self.post_simple(params)
101
+ self.update(:post, params)
102
+ end
103
+
104
+ def self.delete(params)
105
+ self.update(:delete, params)
106
+ end
107
+
108
+ def self.update(method, params)
109
+ url = "#{@prefix}/#{LimdeskApi::KNOWN_OBJS[params[:object]]}/#{params[:id]}"
110
+ url += "/#{params[:action]}" if params[:action]
111
+ resp = @connection.send(method) do |req|
112
+ req.url url
113
+ req.params[:key] = @key
114
+ req.body = params[:params].to_json
115
+ end
116
+ case resp.status
117
+ when 200
118
+ raise "LimdeskApiError" unless resp.body.kind_of?(Hash) && resp.body['status']
119
+ if resp.body['status'] == "ok"
120
+ return { error: false }
121
+ else
122
+ return { error: true, msg: resp.body['msg'] }
123
+ end
124
+ else
125
+ raise "LimdeskApiErrorFatal"
126
+ end
127
+ end
128
+
129
+ end
@@ -0,0 +1,31 @@
1
+ module LimdeskApi
2
+
3
+ class Activity < RecursiveOpenStruct
4
+
5
+ def self.create(params)
6
+ response = LimdeskApi.create(:object=>:activity , :params=>params)
7
+ Activity.new response
8
+ end
9
+
10
+ def self.all
11
+ query_options = { page: 1, object: :activity }
12
+ results = {}
13
+ activities = []
14
+ loop do
15
+ unless results[:total_pages].nil?
16
+ raise StopIteration if results[:total_pages] == results[:page]
17
+ end
18
+ results = LimdeskApi.get_many(query_options)
19
+ query_options[:page] += 1
20
+ activities+=results[:objects].map { |x| Activity.new x }
21
+ end
22
+ activities
23
+ end
24
+
25
+ def ok?
26
+ error == true ? false : true
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -0,0 +1,44 @@
1
+ module LimdeskApi
2
+
3
+ class Client < RecursiveOpenStruct
4
+
5
+ def self.get(id)
6
+ response = LimdeskApi.get_one(:object=>:client, :id=>id)
7
+ response ? Client.new(response) : nil
8
+ end
9
+
10
+ def self.create(params)
11
+ response = LimdeskApi.create(:object=>:client, :params=>params)
12
+ Client.new response
13
+ end
14
+
15
+ def self.all
16
+ query_options = { page: 1, object: :client }
17
+ results = {}
18
+ clients = []
19
+ loop do
20
+ unless results[:total_pages].nil?
21
+ raise StopIteration if results[:total_pages] == results[:page]
22
+ end
23
+ results = LimdeskApi.get_many(query_options)
24
+ query_options[:page] += 1
25
+ clients+=results[:objects].map { |x| Client.new x }
26
+ end
27
+ clients
28
+ end
29
+
30
+ def ok?
31
+ error == true ? false : true
32
+ end
33
+
34
+ def refresh!
35
+ self.marshal_load(Client.get(self['id']).marshal_dump)
36
+ end
37
+
38
+ def delete!
39
+ response = LimdeskApi.delete( id: self.id, object: :client )
40
+ return not(response[:error])
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,89 @@
1
+ module LimdeskApi
2
+
3
+ class Ticket < RecursiveOpenStruct
4
+
5
+ CLOSE_TYPES = {
6
+ rejected: 2,
7
+ resolved: 1
8
+ }
9
+
10
+ MEDIA_TYPES = {
11
+ mail: 1,
12
+ chat: 2,
13
+ phone: 3,
14
+ other: 4,
15
+ }
16
+
17
+ ANSWER_TYPES = {
18
+ pub: 0,
19
+ priv: 1
20
+ }
21
+
22
+ def self.get(no)
23
+ response = LimdeskApi.get_one(:object=>:ticket, :id=>no)
24
+ response ? Ticket.new(response) : nil
25
+ end
26
+
27
+ def self.create(params)
28
+ raise "BadMediaType" unless Ticket::MEDIA_TYPES.keys.include?(params[:reported_by])
29
+ params["reportedBy"] = Ticket::MEDIA_TYPES[params.delete(:reported_by)]
30
+ response = LimdeskApi.create(:object=>:ticket, :params=>params)
31
+ Ticket.new response
32
+ end
33
+
34
+ def self.all
35
+ query_options = { page: 1, object: :ticket }
36
+ results = {}
37
+ tickets = []
38
+ loop do
39
+ unless results[:total_pages].nil?
40
+ raise StopIteration if results[:total_pages] == results[:page]
41
+ end
42
+ results = LimdeskApi.get_many(query_options)
43
+ query_options[:page] += 1
44
+ tickets+=results[:objects].map { |x| Ticket.new x }
45
+ end
46
+ tickets
47
+ end
48
+
49
+ def ok?
50
+ error == true ? false : true
51
+ end
52
+
53
+ def refresh!
54
+ self.marshal_load(Ticket.get(self['number']).marshal_dump)
55
+ end
56
+
57
+ def close(params)
58
+ raise "BadCloseType" unless Ticket::CLOSE_TYPES.keys.include?(params[:type])
59
+ raise "NoContentGiven" unless params[:content]
60
+ response = LimdeskApi.put( id: self.number,
61
+ object: :ticket,
62
+ action: :close,
63
+ params: { content: params[:content], type: Ticket::CLOSE_TYPES[params[:type]] } )
64
+ refresh!
65
+ return not(response[:error])
66
+ end
67
+
68
+ def reopen
69
+ response = LimdeskApi.put( id: self.number,
70
+ object: :ticket,
71
+ action: :reopen,
72
+ params: {} )
73
+ refresh!
74
+ return not(response[:error])
75
+ end
76
+
77
+ def answer(params)
78
+ raise "BadAnswerType" unless Ticket::ANSWER_TYPES.keys.include?(params[:answer_type])
79
+ params["type"] = Ticket::ANSWER_TYPES[params.delete(:answer_type)]
80
+ response = LimdeskApi.post_simple( id: self.number,
81
+ object: :ticket,
82
+ action: :answer,
83
+ params: params )
84
+ refresh!
85
+ return not(response[:error])
86
+ end
87
+
88
+ end
89
+ end
@@ -0,0 +1,3 @@
1
+ module LimdeskApi
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'limdesk_api/version'
5
+
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "limdesk_api"
9
+ spec.version = LimdeskApi::VERSION
10
+ spec.authors = ["Grzegorz Siehień"]
11
+ spec.email = ["grzegorz.siehien@limtel.com"]
12
+ spec.summary = %q{Gem for interacting with Limdesk.com}
13
+ spec.description = %q{Limdesk.com is a multichannel, web-based customer support solution. This gem lets you integrate your software using Limdesk's API.}
14
+ spec.homepage = "https://www.limdesk.com"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.6"
23
+ spec.add_development_dependency "rake", '~> 0'
24
+ spec.add_dependency 'faraday', '~> 0.9.0', '>= 0.9.0'
25
+ spec.add_dependency 'faraday_middleware', '~> 0.9.1', '>= 0.9.0'
26
+ spec.add_dependency 'recursive-open-struct', '~> 0.5.0', '>= 0.5.0'
27
+ spec.add_dependency 'json', '~> 1.8.1', '>= 1.8.0'
28
+ end
metadata ADDED
@@ -0,0 +1,164 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: limdesk_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Grzegorz Siehień
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: faraday
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.9.0
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: 0.9.0
51
+ type: :runtime
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - "~>"
56
+ - !ruby/object:Gem::Version
57
+ version: 0.9.0
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 0.9.0
61
+ - !ruby/object:Gem::Dependency
62
+ name: faraday_middleware
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: 0.9.1
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: 0.9.0
71
+ type: :runtime
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - "~>"
76
+ - !ruby/object:Gem::Version
77
+ version: 0.9.1
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: 0.9.0
81
+ - !ruby/object:Gem::Dependency
82
+ name: recursive-open-struct
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: 0.5.0
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: 0.5.0
91
+ type: :runtime
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: 0.5.0
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: 0.5.0
101
+ - !ruby/object:Gem::Dependency
102
+ name: json
103
+ requirement: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - "~>"
106
+ - !ruby/object:Gem::Version
107
+ version: 1.8.1
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: 1.8.0
111
+ type: :runtime
112
+ prerelease: false
113
+ version_requirements: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 1.8.1
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: 1.8.0
121
+ description: Limdesk.com is a multichannel, web-based customer support solution. This
122
+ gem lets you integrate your software using Limdesk's API.
123
+ email:
124
+ - grzegorz.siehien@limtel.com
125
+ executables: []
126
+ extensions: []
127
+ extra_rdoc_files: []
128
+ files:
129
+ - ".gitignore"
130
+ - Gemfile
131
+ - LICENSE.txt
132
+ - README.md
133
+ - Rakefile
134
+ - lib/limdesk_api.rb
135
+ - lib/limdesk_api/activity.rb
136
+ - lib/limdesk_api/client.rb
137
+ - lib/limdesk_api/ticket.rb
138
+ - lib/limdesk_api/version.rb
139
+ - limdesk_api.gemspec
140
+ homepage: https://www.limdesk.com
141
+ licenses:
142
+ - MIT
143
+ metadata: {}
144
+ post_install_message:
145
+ rdoc_options: []
146
+ require_paths:
147
+ - lib
148
+ required_ruby_version: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ required_rubygems_version: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ requirements: []
159
+ rubyforge_project:
160
+ rubygems_version: 2.2.2
161
+ signing_key:
162
+ specification_version: 4
163
+ summary: Gem for interacting with Limdesk.com
164
+ test_files: []