Completed
Push — master ( 40af06...6a28b9 )
by John
01:17
created

Zendesk   A

Complexity

Total Complexity 35

Size/Duplication

Total Lines 205
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 205
rs 9
wmc 35

25 Methods

Rating   Name   Duplication   Size   Complexity  
A total_tickets_list() 0 3 1
A zendesk_request() 0 7 2
A ticket_details() 0 14 1
A zd_instance_info() 0 3 1
A onhold_tickets() 0 3 1
A tickets() 0 3 2
B check_client() 0 22 4
A unsolved_tickets_list() 0 3 1
A onhold_tickets_list() 0 3 1
A open_tickets() 0 3 1
A pending_tickets() 0 3 1
A ticket_count() 0 7 3
A escalated_tickets_list() 0 3 1
A escalated_tickets() 0 3 1
A search_tickets() 0 3 1
A open_tickets_list() 0 3 1
A ticket_search() 0 12 2
A ticket_list() 0 12 3
A new_tickets() 0 3 1
A total_tickets() 0 3 1
A basic_credentials() 0 3 1
A unsolved_tickets() 0 3 1
A base_url() 0 3 1
A pending_tickets_list() 0 3 1
A new_tickets_list() 0 3 1
1
require 'base64'
2
require 'faraday'
3
require 'faraday_middleware'
4
5
module Lita
6
  module Handlers
7
    class Zendesk < Handler
8
      is_command = false
9
10
      VERSION_URL = 'api/v2'
11
      QUERY_SEARCH_PREFIX = 'search.json?query='
12
      QUERY_SEARCH_TICKET = 'type:ticket'
13
      QUERY_TICKETS_ALL = 'tickets'
14
      QUERY_TICKETS_ESCALATED = 'search.json?query=tags:escalated+status:open+status:pending+type:ticket'
15
      QUERY_TICKETS_HOLD = 'search.json?query=status:hold+type:ticket'
16
      QUERY_TICKETS_OPEN = 'search.json?query=status:open+type:ticket'
17
      QUERY_TICKETS_NEW = 'search.json?query=status:new+type:ticket'
18
      QUERY_TICKETS_PENDING = 'search.json?query=status:pending+type:ticket'
19
      QUERY_TICKETS_UNSOLVED = 'search.json?query=status<solved+type:ticket'
20
      QUERY_USERS = 'users'
21
22
      config :subdomain, type: String, required: true
23
      config :auth_type, type: String, default: 'password' # or token
24
      config :user, type: String, required: true
25
      config :token, type: String, default: ''
26
      config :password, type: String, default: ''
27
28
      def check_client(reload = false)
29
        return if @conn && !reload
30
        @base_url = base_url
31
        @version_url = "#{@base_url}/#{VERSION_URL}"
32
        @tickets_url = "#{@base_url}/tickets"
33
34
        if config.auth_type == 'password'
35
          @conn = Faraday.new(url: @version_url) do |faraday|
36
            faraday.headers['Authorization'] = "Basic #{basic_credentials}"
37
            faraday.response :json                    # JSON response
38
            faraday.response :logger                  # log requests to STDOUT
39
            faraday.adapter  Faraday.default_adapter  # make requests with Net::HTTP
40
          end
41
        else
42
          @conn = Faraday.new(url: @version_url) do |faraday|
43
            faraday.response :json                    # JSON response
44
            faraday.response :logger                  # log requests to STDOUT
45
            faraday.adapter  Faraday.default_adapter  # make requests with Net::HTTP
46
          end
47
          @conn.basic_auth("#{config.user}/token", config.token) 
48
        end
49
      end
50
51
      def base_url
52
        "https://#{config.subdomain.to_s}.zendesk.com"
53
      end
54
55
      def basic_credentials
56
        Base64.encode64("#{config.user}:#{config.password}").gsub(/\s/,'')
57
      end
58
59
      def zendesk_request(url)
60
        check_client
61
        if url.index('http') != 0
62
          url = "#{@version_url}/#{url}"
63
        end
64
        @conn.get url
65
      end
66
67
      # Info
68
69
      route(/^(?:zd|zendesk)\s+connection\s*$/, :zd_instance_info, command: true, help: { 'zd connection' => 'returns information on the Zendesk connection' })
70
      def zd_instance_info(response)
71
        response.reply "Using Zendesk instance at: #{base_url}"
72
      end
73
74
      route(/^(?:zd|zendesk)\s+search\s+tickets?\s+(\S.*?)\s*$/, :search_tickets, command: true, help: { 'zd search tickets <QUERY>' => 'returns search results' })
75
      def search_tickets(response)
76
        ticket_search response, QUERY_SEARCH_PREFIX, response.matches[0][0]
77
      end
78
79
      # Ticket Counts
80
81
      route(/^(?:zd|zendesk)(\s+unsolved)?\s+tickets?\s*$/, :unsolved_tickets, command: true, help: { 'zd tickets' => 'returns the total count of all unsolved tickets' })
82
      def unsolved_tickets(response)
83
        ticket_count response, QUERY_TICKETS_UNSOLVED, 'unsolved'
84
      end
85
86
      route(/^(?:zd|zendesk)\s+(all|total)\s+tickets?\s*$/, :total_tickets, command: true, help: { 'zd all tickets' => 'returns the count of all tickets' })
87
      def total_tickets(response)
88
        ticket_count response, QUERY_TICKETS_ALL, 'total'
89
      end
90
91
      route(/^(?:zd|zendesk)\s+pending\s+tickets?\s*$/, :pending_tickets, command: true, help: { 'zd pending tickets' => 'returns a count of tickets that are pending' })
92
      def pending_tickets(response)
93
        ticket_count response, QUERY_TICKETS_PENDING, 'pending'
94
      end
95
96
      route(/^(?:zd|zendesk)\s+new\s+tickets?\s*$/, :new_tickets, command: true, help: { 'zd new tickets' => 'returns the count of all new (unassigned) tickets' })
97
      def new_tickets(response)
98
        ticket_count response, QUERY_TICKETS_NEW, 'new'
99
      end
100
101
      route(/^(?:zd|zendesk)\s+escalated\s+tickets?\s*$/, :escalated_tickets, command: true, help: { 'zd escalated tickets' => 'returns a count of tickets with escalated tag that are open or pending' })
102
      def escalated_tickets(response)
103
        ticket_count response, QUERY_TICKETS_ESCALATED, 'escalated'
104
      end
105
106
      route(/^(?:zd|zendesk)\s+open\s+tickets?\s*$/, :open_tickets, command: true, help: { 'zd open tickets' => 'returns the count of all open tickets' })
107
      def open_tickets(response)
108
        ticket_count response, QUERY_TICKETS_OPEN, 'open'
109
      end
110
111
      route(/^(?:zd|zendesk)\s+on\s+hold\s+tickets?\s*$/, :onhold_tickets, command: true, help: { 'zd on hold tickets' => 'returns the count of all on hold tickets' })
112
      def onhold_tickets(response)
113
        ticket_count response, QUERY_TICKETS_HOLD, 'on hold'
114
      end
115
116
      # Ticket Lists
117
118
      route(/^(?:zd|zendesk)\s+list(\s+unsolved)?\s+tickets?\s*$/, :unsolved_tickets_list, command: true, help: { 'zd list tickets' => 'returns a list of unsolved tickets' })
119
      def unsolved_tickets_list(response)
120
        ticket_list response, QUERY_TICKETS_UNSOLVED, 'unsolved'
121
      end
122
123
      route(/^(?:zd|zendesk)\s+list\s+(all|total)\s+tickets?\s*$/, :total_tickets_list, command: true, help: { 'zd list all tickets' => 'returns a list of all tickets' })
124
      def total_tickets_list(response)
125
        ticket_list response, QUERY_TICKETS_ALL, 'total'
126
      end
127
128
      route(/^(?:zd|zendesk)\s+list\s+pending\s+tickets?\s*$/, :pending_tickets_list, command: true, help: { 'zd list pending tickets' => 'returns a list of pending tickets' })
129
      def pending_tickets_list(response)
130
        ticket_list response, QUERY_TICKETS_PENDING, 'pending'
131
      end
132
133
      route(/^(?:zd|zendesk)\s+list\s+new\s+tickets?\s*$/, :new_tickets_list, command: true, help: { 'zd list new tickets' => 'returns a list of new tickets' })
134
      def new_tickets_list(response)
135
        ticket_list response, QUERY_TICKETS_NEW, 'new'
136
      end
137
138
      route(/^(?:zd|zendesk)\s+list\s+escalated\s+tickets?\s*$/, :escalated_tickets_list, command: true, help: { 'zd list esclated tickets' => 'returns a list of escalated tickets' })
139
      def escalated_tickets_list(response)
140
        ticket_list response, QUERY_TICKETS_ESCALATED, 'escalated'
141
      end
142
143
      route(/^(?:zd|zendesk)\s+list\s+open\s+tickets?\s*$/, :open_tickets_list, command: true, help: { 'zd list open tickets' => 'returns a list of open tickets' })
144
      def open_tickets_list(response)
145
        ticket_list response, QUERY_TICKETS_OPEN, 'open'
146
      end
147
148
      route(/^(?:zd|zendesk)\s+list\s+on\s+hold\s+tickets?\s*$/, :onhold_tickets_list, command: true, help: { 'zd list onhold tickets' => 'returns a list of on hold tickets' })
149
      def onhold_tickets_list(response)
150
        ticket_list response, QUERY_TICKETS_HOLD, 'on hold'
151
      end
152
153
      # Ticket Details
154
155
      route(/^(?:zd|zendesk)\s+ticket\s+(\d+)\s*$/, :ticket_details, command: true, help: { 'zd ticket <ID>' => 'returns information about the specified ticket' })
156
      def ticket_details(response)
157
        ticket_id = response.matches[0][0]
158
        url = "#{QUERY_TICKETS_ALL}/#{ticket_id}.json"
159
        res = zendesk_request url
160
        data = res.body
161
162
        message = "Ticket #{data['ticket']['id']}: #{@tickets_url}/#{data['ticket']['id']}"
163
        message += "\nStatus: #{data['ticket']['status'].upcase}"
164
        message += "\nUpdated: " + data['ticket']['updated_at']
165
        message += "\nAdded: #{data['ticket']['created_at']}"
166
        message += "\nSubject: #{data['ticket']['subject']}"
167
        message += "\nDescription:\n-----\n#{data['ticket']['description']}\n-----\n"
168
        response.reply message
169
      end
170
171
      private
172
173
      def ticket_search(response, url, query)
174
        url += query + '+' + QUERY_SEARCH_TICKET
175
        res = zendesk_request url
176
        tickets = res.body['results']
177
        tickets.each do |ticket|
178
          response.reply "Ticket #{ticket['id']} is #{ticket['status']}: #{@tickets_url}/#{ticket['id']} - #{ticket['subject']}"
179
        end
180
        ticket_length = tickets.length
181
        ticket_count = res.body['count']
182
        ticket_word  = ticket_count == 1 ? 'result' : 'results'
183
        response.reply "Listing #{ticket_length} of #{ticket_count} matching #{ticket_word}."
184
      end
185
186
      def ticket_count(response, url, ticket_type = '')
187
        res = zendesk_request url
188
        ticket_count = res.body['count']
189
        ticket_word  = ticket_count == 1 ? 'ticket' : 'tickets'
190
        ticket_desc  = ticket_type == '' ? '' : "#{ticket_type} "
191
        response.reply "#{ticket_count} #{ticket_desc}#{ticket_word}."
192
      end
193
194
      def ticket_list(response, url, ticket_type = '')
195
        res = zendesk_request url
196
        tickets = res.body['results']
197
        tickets.each do |ticket|
198
          response.reply "Ticket #{ticket['id']} is #{ticket['status']}: #{@tickets_url}/#{ticket['id']} - #{ticket['subject']}"
199
        end
200
        ticket_length = tickets.length
201
        ticket_count = res.body['count']
202
        ticket_word  = ticket_count == 1 ? 'ticket' : 'tickets'
203
        ticket_desc  = ticket_type == '' ? '' : "#{ticket_type} "
204
        response.reply "Listing #{ticket_length} of #{ticket_count} #{ticket_desc}#{ticket_word}."
205
      end
206
207
      def tickets(count)
208
        count == 1 ? 'ticket' : 'tickets'
209
      end
210
211
    end
212
213
    Lita.register_handler(Zendesk)
214
  end
215
end