ferris-bueller 0.0.2 → 0.0.3
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 +4 -4
- data/VERSION +1 -1
- data/lib/ferris-bueller/helpers.rb +21 -11
- data/lib/ferris-bueller/jira_api.rb +45 -0
- data/lib/ferris-bueller/main.rb +1 -1
- data/lib/ferris-bueller/replies.rb +274 -10
- data/lib/ferris-bueller/slack_api.rb +2 -2
- data/lib/ferris-bueller/web_helpers.rb +7 -7
- metadata +3 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: e42b63a6a4a472e0a57bf203fd2b40df207691f0
         | 
| 4 | 
            +
              data.tar.gz: e17b58dd6390318e6540015e1d5ead60a8b5fd27
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 5e63ebf4b536ae282d08365cd580796e843a89685d53ef498f936bee99e592fd04a484cd6a9398296882ff17b3602a0eb373e0bc991dc9c379e4359d17f39a84
         | 
| 7 | 
            +
              data.tar.gz: ae7e81ccd67840d08b36d0855fd7adcfb441e9249d7ede8916f8fb0f148e4722e6b208ce6c0dfe81e676e5d454735856b9a44eded1cafbf5c140c178e0305731
         | 
    
        data/VERSION
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            0.0. | 
| 1 | 
            +
            0.0.3
         | 
| @@ -6,6 +6,7 @@ require 'queryparams' | |
| 6 6 |  | 
| 7 7 | 
             
            require_relative 'constants'
         | 
| 8 8 | 
             
            require_relative 'web'
         | 
| 9 | 
            +
            require_relative 'jira_api'
         | 
| 9 10 | 
             
            require_relative 'slack_api'
         | 
| 10 11 |  | 
| 11 12 |  | 
| @@ -25,6 +26,15 @@ module FerrisBueller | |
| 25 26 | 
             
                  Web.set :logger, log
         | 
| 26 27 | 
             
                  Web.set :verification_token, options.verification_token
         | 
| 27 28 | 
             
                  Web.set :api, SlackAPI.new(token: options.api_token, logger: log)
         | 
| 29 | 
            +
                  Web.set :jira, JiraAPI.new(
         | 
| 30 | 
            +
                    api_url: options.jira_url,
         | 
| 31 | 
            +
                    user: options.jira_user,
         | 
| 32 | 
            +
                    pass: options.jira_pass,
         | 
| 33 | 
            +
                    logger: log
         | 
| 34 | 
            +
                  )
         | 
| 35 | 
            +
                  Web.set :jira_project, options.jira_project
         | 
| 36 | 
            +
                  Web.set :jira_type, options.jira_type
         | 
| 37 | 
            +
                  Web.set :refresh_rate, options.incident_refresh
         | 
| 28 38 |  | 
| 29 39 | 
             
                  if log.level >= ::Logger::DEBUG
         | 
| 30 40 | 
             
                    Web.set :raise_errors, true
         | 
| @@ -76,15 +86,15 @@ module FerrisBueller | |
| 76 86 | 
             
                    maxResults: 1_000_000
         | 
| 77 87 |  | 
| 78 88 | 
             
                  users = data.inject({}) do |h, user|
         | 
| 79 | 
            -
                    h[user[ | 
| 80 | 
            -
                      key: user[ | 
| 81 | 
            -
                      nick: user[ | 
| 82 | 
            -
                      name: user[ | 
| 83 | 
            -
                      email: user[ | 
| 89 | 
            +
                    h[user[:name]] = {
         | 
| 90 | 
            +
                      key: user[:key],
         | 
| 91 | 
            +
                      nick: user[:name],
         | 
| 92 | 
            +
                      name: user[:displayName],
         | 
| 93 | 
            +
                      email: user[:emailAddress]
         | 
| 84 94 | 
             
                    } ; h
         | 
| 85 95 | 
             
                  end
         | 
| 86 96 |  | 
| 87 | 
            -
                  store[ | 
| 97 | 
            +
                  store[:jira_users] = users
         | 
| 88 98 |  | 
| 89 99 | 
             
                rescue StandardError => e
         | 
| 90 100 | 
             
                  log.error \
         | 
| @@ -105,8 +115,8 @@ module FerrisBueller | |
| 105 115 | 
             
                    groupname: options.jira_group,
         | 
| 106 116 | 
             
                    expand: 'users'
         | 
| 107 117 |  | 
| 108 | 
            -
                  user_names = data[ | 
| 109 | 
            -
                  store[ | 
| 118 | 
            +
                  user_names = data[:users][:items].map { |u| u[:name] }
         | 
| 119 | 
            +
                  store[:jira_members] = user_names
         | 
| 110 120 |  | 
| 111 121 | 
             
                rescue StandardError => e
         | 
| 112 122 | 
             
                  log.error \
         | 
| @@ -129,8 +139,8 @@ module FerrisBueller | |
| 129 139 | 
             
                    startAt: 0,
         | 
| 130 140 | 
             
                    maxResults: 1_000_000
         | 
| 131 141 |  | 
| 132 | 
            -
                  store[ | 
| 133 | 
            -
                    i[ | 
| 142 | 
            +
                  store[:jira_incidents] = data[:issues].map do |i|
         | 
| 143 | 
            +
                    i[:num] = i[:key].split('-', 2).last ; i
         | 
| 134 144 | 
             
                  end
         | 
| 135 145 |  | 
| 136 146 | 
             
                rescue StandardError => e
         | 
| @@ -169,7 +179,7 @@ module FerrisBueller | |
| 169 179 | 
             
                    params: params,
         | 
| 170 180 | 
             
                    api_url: api_url,
         | 
| 171 181 | 
             
                    response: resp
         | 
| 172 | 
            -
                  JSON.parse resp.body
         | 
| 182 | 
            +
                  JSON.parse resp.body, symbolize_names: true
         | 
| 173 183 | 
             
                end
         | 
| 174 184 |  | 
| 175 185 | 
             
              end
         | 
| @@ -0,0 +1,45 @@ | |
| 1 | 
            +
            require 'json'
         | 
| 2 | 
            +
            require 'net/http'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            require 'slog'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            Thread.abort_on_exception = true
         | 
| 7 | 
            +
             | 
| 8 | 
            +
             | 
| 9 | 
            +
            module FerrisBueller
         | 
| 10 | 
            +
              class JiraAPI
         | 
| 11 | 
            +
                def initialize options={}
         | 
| 12 | 
            +
                  @user      = options.fetch :user
         | 
| 13 | 
            +
                  @pass      = options.fetch :pass
         | 
| 14 | 
            +
                  @api_url   = options.fetch :api_url
         | 
| 15 | 
            +
                  @base_path = options.fetch :base_path, '/rest/api/2'
         | 
| 16 | 
            +
                  @logger    = options.fetch :logger, Slog.new
         | 
| 17 | 
            +
                  log.trace event: 'Jira API client initialized'
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                def send path, data={}
         | 
| 21 | 
            +
                  uri = URI File.join(@api_url, @base_path, path)
         | 
| 22 | 
            +
                  http = Net::HTTP.new uri.hostname, uri.port
         | 
| 23 | 
            +
                  http.use_ssl if uri.scheme == 'https'
         | 
| 24 | 
            +
                  req = Net::HTTP::Post.new uri
         | 
| 25 | 
            +
                  req.basic_auth @user, @pass
         | 
| 26 | 
            +
                  req['Content-Type'] = 'application/json'
         | 
| 27 | 
            +
                  req['Accept'] = 'application/json'
         | 
| 28 | 
            +
                  req.body = JSON.generate data
         | 
| 29 | 
            +
                  log.trace \
         | 
| 30 | 
            +
                    event: 'sending Jira API request',
         | 
| 31 | 
            +
                    path: path,
         | 
| 32 | 
            +
                    data: data
         | 
| 33 | 
            +
                  res = JSON.parse http.request(req).body, symbolize_names: true
         | 
| 34 | 
            +
                  log.debug \
         | 
| 35 | 
            +
                    event: 'Jira API request returned',
         | 
| 36 | 
            +
                    path: path,
         | 
| 37 | 
            +
                    data: data,
         | 
| 38 | 
            +
                    response: res
         | 
| 39 | 
            +
                  res
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
              private
         | 
| 43 | 
            +
                def log ; @logger end
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
            end
         | 
    
        data/lib/ferris-bueller/main.rb
    CHANGED
    
    | @@ -84,7 +84,7 @@ module FerrisBueller | |
| 84 84 | 
             
                  type: :numeric,
         | 
| 85 85 | 
             
                  aliases: %w[ -i ],
         | 
| 86 86 | 
             
                  desc: 'Set JIRA incident refresh rate',
         | 
| 87 | 
            -
                  default: (ENV['FERRIS_BUELLER_INCIDENT_REFRESH'] ||  | 
| 87 | 
            +
                  default: (ENV['FERRIS_BUELLER_INCIDENT_REFRESH'] || 2)
         | 
| 88 88 | 
             
                option :member_refresh, \
         | 
| 89 89 | 
             
                  type: :numeric,
         | 
| 90 90 | 
             
                  aliases: %w[ -g ],
         | 
| @@ -1,10 +1,15 @@ | |
| 1 | 
            +
            require_relative 'constants'
         | 
| 2 | 
            +
            require_relative 'main'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
             | 
| 1 5 | 
             
            module FerrisBueller
         | 
| 2 6 | 
             
              module Replies
         | 
| 7 | 
            +
                include Constants
         | 
| 3 8 |  | 
| 4 9 | 
             
                def reply_whoami params
         | 
| 5 10 | 
             
                  u = user_lookup(params)
         | 
| 6 11 | 
             
                  if u
         | 
| 7 | 
            -
                    { text: "You're <@#{params[ | 
| 12 | 
            +
                    { text: "You're <@#{params[:user_id]}>",
         | 
| 8 13 | 
             
                      attachments: [
         | 
| 9 14 | 
             
                        {
         | 
| 10 15 | 
             
                          title: 'Slack User',
         | 
| @@ -22,7 +27,7 @@ module FerrisBueller | |
| 22 27 | 
             
                    }
         | 
| 23 28 | 
             
                  else
         | 
| 24 29 | 
             
                    {
         | 
| 25 | 
            -
                      text: "You're <@#{params[ | 
| 30 | 
            +
                      text: "You're <@#{params[:user_id]}>, but I can't say much more than that"
         | 
| 26 31 | 
             
                    }
         | 
| 27 32 | 
             
                  end
         | 
| 28 33 | 
             
                end
         | 
| @@ -39,38 +44,297 @@ module FerrisBueller | |
| 39 44 |  | 
| 40 45 |  | 
| 41 46 | 
             
                def reply_list params
         | 
| 42 | 
            -
                   | 
| 47 | 
            +
                  incidents = open_incidents
         | 
| 48 | 
            +
                  return { text: 'Could not list incidents' } if incidents.nil?
         | 
| 49 | 
            +
                  return { text: 'No open incidents at the moment' } if incidents.empty?
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  attachments = incidents.map do |i|
         | 
| 52 | 
            +
                    attach_incident(incident)
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
                  {
         | 
| 55 | 
            +
                    text: 'Found %d open incidents' % attachments.size,
         | 
| 56 | 
            +
                    attachments: attachments
         | 
| 57 | 
            +
                  }
         | 
| 43 58 | 
             
                end
         | 
| 44 59 |  | 
| 45 60 |  | 
| 46 61 | 
             
                def reply_summary params
         | 
| 47 | 
            -
                   | 
| 62 | 
            +
                  incidents = recent_incidents
         | 
| 63 | 
            +
                  return { text: 'Could not list incidents' } if incidents.nil?
         | 
| 64 | 
            +
                  return { text: 'No recent incidents' } if incidents.empty?
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                  attachments = incidents.map do |i|
         | 
| 67 | 
            +
                    attach_incident i
         | 
| 68 | 
            +
                  end
         | 
| 69 | 
            +
                  {
         | 
| 70 | 
            +
                    text: 'Found %d recent incidents' % attachments.size,
         | 
| 71 | 
            +
                    attachments: attachments
         | 
| 72 | 
            +
                  }
         | 
| 48 73 | 
             
                end
         | 
| 49 74 |  | 
| 50 75 |  | 
| 51 76 | 
             
                def reply_show inc_num, params
         | 
| 52 | 
            -
                   | 
| 77 | 
            +
                  incident = select_incident inc_num
         | 
| 78 | 
            +
                  return { text: 'Could not list incidents' } unless incident
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                  {
         | 
| 81 | 
            +
                    attachments: [
         | 
| 82 | 
            +
                      attach_incident(incident)
         | 
| 83 | 
            +
                    ]
         | 
| 84 | 
            +
                  }
         | 
| 53 85 | 
             
                end
         | 
| 54 86 |  | 
| 55 87 |  | 
| 56 88 | 
             
                def reply_resolve inc_num, params
         | 
| 57 | 
            -
                  { text: ' | 
| 89 | 
            +
                  return { text: "You're not allowed to do that" } unless allowed? params
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                  incident = select_incident inc_num
         | 
| 92 | 
            +
                  return { text: 'Could not list incidents' } unless incident
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                  resolution = resolve_incident incident
         | 
| 95 | 
            +
                  return { text: 'Could not resolve incident' } if resolution.nil?
         | 
| 96 | 
            +
                  return { text: 'Already resolved' } if resolution == false
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                  {
         | 
| 99 | 
            +
                    text: 'Resolved incident',
         | 
| 100 | 
            +
                    attachments: [
         | 
| 101 | 
            +
                      attach_incident(incident)
         | 
| 102 | 
            +
                    ]
         | 
| 103 | 
            +
                  }
         | 
| 58 104 | 
             
                end
         | 
| 59 105 |  | 
| 60 106 |  | 
| 61 107 | 
             
                def reply_close inc_num, params
         | 
| 62 | 
            -
                  { text: ' | 
| 108 | 
            +
                  return { text: "You're not allowed to do that" } unless allowed? params
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                  incident = select_incident inc_num
         | 
| 111 | 
            +
                  return { text: 'Could not list incidents' } unless incident
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                  resolution = close_incident incident
         | 
| 114 | 
            +
                  return { text: 'Could not close incident' } unless resolution
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                  {
         | 
| 117 | 
            +
                    text: 'Closed incident',
         | 
| 118 | 
            +
                    attachments: [
         | 
| 119 | 
            +
                      attach_incident(incident)
         | 
| 120 | 
            +
                    ]
         | 
| 121 | 
            +
                  }
         | 
| 63 122 | 
             
                end
         | 
| 64 123 |  | 
| 65 124 |  | 
| 66 125 | 
             
                def reply_open sev_num, summary, params
         | 
| 67 | 
            -
                  { text: ' | 
| 126 | 
            +
                  return { text: "You're not allowed to do that" } unless allowed? params
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                  new_incident = construct_incident sev_num, summary, params
         | 
| 129 | 
            +
                  incident = open_incident new_incident, summary
         | 
| 130 | 
            +
                  return { text: 'Could not open incident' } unless incident
         | 
| 131 | 
            +
             | 
| 132 | 
            +
                  incident = new_incident.merge incident
         | 
| 133 | 
            +
                  {
         | 
| 134 | 
            +
                    text: 'Opened incident',
         | 
| 135 | 
            +
                    attachments: [
         | 
| 136 | 
            +
                      attach_incident(incident)
         | 
| 137 | 
            +
                    ]
         | 
| 138 | 
            +
                  }
         | 
| 68 139 | 
             
                end
         | 
| 69 140 |  | 
| 70 141 |  | 
| 71 | 
            -
                def reply_comment inc_num,  | 
| 72 | 
            -
                   | 
| 142 | 
            +
                def reply_comment inc_num, message, params
         | 
| 143 | 
            +
                  incident = select_incident inc_num
         | 
| 144 | 
            +
                  return { text: 'Could not list incidents' } unless incident
         | 
| 145 | 
            +
             | 
| 146 | 
            +
                  comment = construct_comment message, params
         | 
| 147 | 
            +
                  annotation = comment_on_incident incident, comment
         | 
| 148 | 
            +
                  return { text: 'Could not comment on incident' } unless annotation
         | 
| 149 | 
            +
             | 
| 150 | 
            +
                  {
         | 
| 151 | 
            +
                    text: 'Commented on incident',
         | 
| 152 | 
            +
                    attachments: [
         | 
| 153 | 
            +
                      attach_incident(incident)
         | 
| 154 | 
            +
                    ]
         | 
| 155 | 
            +
                  }
         | 
| 73 156 | 
             
                end
         | 
| 74 157 |  | 
| 158 | 
            +
             | 
| 159 | 
            +
             | 
| 160 | 
            +
              private
         | 
| 161 | 
            +
             | 
| 162 | 
            +
                def attach_incident i
         | 
| 163 | 
            +
                  {
         | 
| 164 | 
            +
                    title: i[:key],
         | 
| 165 | 
            +
                    text: i[:fields][:summary],
         | 
| 166 | 
            +
                    mrkdwn_in: %w[ text pretext ]
         | 
| 167 | 
            +
                  }
         | 
| 168 | 
            +
                end
         | 
| 169 | 
            +
             | 
| 170 | 
            +
             | 
| 171 | 
            +
                def resolve_incident i
         | 
| 172 | 
            +
                  status = normalize_value i[:fields][:status]
         | 
| 173 | 
            +
                  return false if status =~ RESOLVED_STATE
         | 
| 174 | 
            +
             | 
| 175 | 
            +
                  log.trace \
         | 
| 176 | 
            +
                    event: 'resolving incident',
         | 
| 177 | 
            +
                    incident: i
         | 
| 178 | 
            +
             | 
| 179 | 
            +
                  RESOLVED_TRANSITIONS.map do |tid|
         | 
| 180 | 
            +
                    Thread.new do
         | 
| 181 | 
            +
                      jira.send "/issue/#{i[:key]}/transitions?expand=transitions.fields", \
         | 
| 182 | 
            +
                        transition: { id: tid }
         | 
| 183 | 
            +
                    end
         | 
| 184 | 
            +
                  end.join
         | 
| 185 | 
            +
             | 
| 186 | 
            +
                  sleep 1.5 * settings.refresh_rate
         | 
| 187 | 
            +
             | 
| 188 | 
            +
                  incident = select_incident i[:key].split('-',2).last
         | 
| 189 | 
            +
                  status   = normalize_value incident[:fields][:status]
         | 
| 190 | 
            +
             | 
| 191 | 
            +
                  log.debug \
         | 
| 192 | 
            +
                    event: 'transitioned incident for resolve',
         | 
| 193 | 
            +
                    incident: i,
         | 
| 194 | 
            +
                    status: status
         | 
| 195 | 
            +
             | 
| 196 | 
            +
                  return incident if status =~ RESOLVED_STATE
         | 
| 197 | 
            +
                end
         | 
| 198 | 
            +
             | 
| 199 | 
            +
             | 
| 200 | 
            +
                def close_incident i
         | 
| 201 | 
            +
                  status = normalize_value i[:fields][:status]
         | 
| 202 | 
            +
                  return false if status =~ CLOSED_STATE
         | 
| 203 | 
            +
             | 
| 204 | 
            +
                  log.trace \
         | 
| 205 | 
            +
                    event: 'closing incident',
         | 
| 206 | 
            +
                    incident: i
         | 
| 207 | 
            +
             | 
| 208 | 
            +
                  CLOSED_TRANSITIONS.map do |tid|
         | 
| 209 | 
            +
                    Thread.new do
         | 
| 210 | 
            +
                      jira.send "/issue/#{i[:key]}/transitions?expand=transitions.fields", \
         | 
| 211 | 
            +
                        transition: { id: tid }
         | 
| 212 | 
            +
                    end
         | 
| 213 | 
            +
                  end.join
         | 
| 214 | 
            +
             | 
| 215 | 
            +
                  sleep 1.5 * settings.refresh_rate
         | 
| 216 | 
            +
             | 
| 217 | 
            +
                  incident = select_incident i[:key].split('-',2).last
         | 
| 218 | 
            +
                  status   = normalize_value incident[:fields][:status]
         | 
| 219 | 
            +
             | 
| 220 | 
            +
                  log.debug \
         | 
| 221 | 
            +
                    event: 'transitioned incident for close',
         | 
| 222 | 
            +
                    incident: i,
         | 
| 223 | 
            +
                    status: status
         | 
| 224 | 
            +
             | 
| 225 | 
            +
                  return incident if status =~ CLOSED_STATE
         | 
| 226 | 
            +
                end
         | 
| 227 | 
            +
             | 
| 228 | 
            +
             | 
| 229 | 
            +
                def construct_incident sev_num, summary, params
         | 
| 230 | 
            +
                  u = user_lookup params
         | 
| 231 | 
            +
                  return unless u
         | 
| 232 | 
            +
                  {
         | 
| 233 | 
            +
                    fields: {
         | 
| 234 | 
            +
                      project: { key: settings.jira_project },
         | 
| 235 | 
            +
                      issuetype: { name: settings.jira_type },
         | 
| 236 | 
            +
                      reporter: { name: u[:jira][:nick] },
         | 
| 237 | 
            +
                      summary: summary,
         | 
| 238 | 
            +
                      SHOW_FIELDS.key('Severity') => {
         | 
| 239 | 
            +
                        id: SEVERITIES[sev_num.to_i]
         | 
| 240 | 
            +
                      }
         | 
| 241 | 
            +
                    }
         | 
| 242 | 
            +
                  }
         | 
| 243 | 
            +
                end
         | 
| 244 | 
            +
             | 
| 245 | 
            +
             | 
| 246 | 
            +
                def open_incident i, summary
         | 
| 247 | 
            +
                  return unless i
         | 
| 248 | 
            +
                  incident = jira.send 'issue', i
         | 
| 249 | 
            +
                  return unless incident.include? :key
         | 
| 250 | 
            +
                  log.info \
         | 
| 251 | 
            +
                    event: 'opened incident',
         | 
| 252 | 
            +
                    incident: incident
         | 
| 253 | 
            +
                  incident
         | 
| 254 | 
            +
                end
         | 
| 255 | 
            +
             | 
| 256 | 
            +
             | 
| 257 | 
            +
                def construct_comment message, params
         | 
| 258 | 
            +
                  u = user_lookup params
         | 
| 259 | 
            +
                  return unless u
         | 
| 260 | 
            +
                  {
         | 
| 261 | 
            +
                    body: '_[~%s]_ says: %s' % [ u[:jira][:nick], message ]
         | 
| 262 | 
            +
                  }
         | 
| 263 | 
            +
                end
         | 
| 264 | 
            +
             | 
| 265 | 
            +
             | 
| 266 | 
            +
                def comment_on_incident i, c
         | 
| 267 | 
            +
                  return unless i
         | 
| 268 | 
            +
                  return unless c
         | 
| 269 | 
            +
                  resp = jira.send "/issue/#{i[:key]}/comment", c
         | 
| 270 | 
            +
                  return unless resp.include? :id
         | 
| 271 | 
            +
                  log.info \
         | 
| 272 | 
            +
                    event: 'comment on incident',
         | 
| 273 | 
            +
                    incident: i,
         | 
| 274 | 
            +
                    comment: c
         | 
| 275 | 
            +
                  resp
         | 
| 276 | 
            +
                end
         | 
| 277 | 
            +
             | 
| 278 | 
            +
             | 
| 279 | 
            +
                def recent_incidents
         | 
| 280 | 
            +
                  return if store[:jira_incidents].nil?
         | 
| 281 | 
            +
                  store[:jira_incidents].select do |i|
         | 
| 282 | 
            +
                    Time.now - Time.parse(i[:fields][:created]) < one_day
         | 
| 283 | 
            +
                  end
         | 
| 284 | 
            +
                end
         | 
| 285 | 
            +
             | 
| 286 | 
            +
             | 
| 287 | 
            +
                def open_incidents
         | 
| 288 | 
            +
                  return if store[:jira_incidents].nil?
         | 
| 289 | 
            +
                  store[:jira_incidents].select do |i|
         | 
| 290 | 
            +
                    status = normalize_value i[:fields][:status]
         | 
| 291 | 
            +
                    !(status =~ /resolved|closed/i)
         | 
| 292 | 
            +
                  end
         | 
| 293 | 
            +
                end
         | 
| 294 | 
            +
             | 
| 295 | 
            +
             | 
| 296 | 
            +
                def select_incident num
         | 
| 297 | 
            +
                  return if store[:jira_incidents].nil?
         | 
| 298 | 
            +
                  store[:jira_incidents].select do |i|
         | 
| 299 | 
            +
                    i[:key] =~ /-#{num}$/
         | 
| 300 | 
            +
                  end.shift
         | 
| 301 | 
            +
                end
         | 
| 302 | 
            +
             | 
| 303 | 
            +
             | 
| 304 | 
            +
                def normalize_value val
         | 
| 305 | 
            +
                  case val
         | 
| 306 | 
            +
                  when Hash
         | 
| 307 | 
            +
                    val[:name] || val[:value] || val
         | 
| 308 | 
            +
                  when Array
         | 
| 309 | 
            +
                    val.map { |v| v[:value] }.join(', ')
         | 
| 310 | 
            +
                  when /^\d{4}\-\d{2}\-\d{2}/
         | 
| 311 | 
            +
                    '%s (%s)' % [ val, normalize_date(val) ]
         | 
| 312 | 
            +
                  else
         | 
| 313 | 
            +
                    val
         | 
| 314 | 
            +
                  end
         | 
| 315 | 
            +
                end
         | 
| 316 | 
            +
             | 
| 317 | 
            +
             | 
| 318 | 
            +
                def normalize_date val
         | 
| 319 | 
            +
                  Time.parse(val).utc.iso8601(0).sub(/Z$/, 'UTC')
         | 
| 320 | 
            +
                end
         | 
| 321 | 
            +
             | 
| 322 | 
            +
             | 
| 323 | 
            +
                def friendly_date val
         | 
| 324 | 
            +
                  Time.parse(val).strftime('%Y-%m-%d %H:%M %Z')
         | 
| 325 | 
            +
                end
         | 
| 326 | 
            +
             | 
| 327 | 
            +
             | 
| 328 | 
            +
                def one_day
         | 
| 329 | 
            +
                  24 * 60 * 60 # seconds/day
         | 
| 330 | 
            +
                end
         | 
| 331 | 
            +
             | 
| 332 | 
            +
                def allowed? params
         | 
| 333 | 
            +
                  u = user_lookup params
         | 
| 334 | 
            +
                  u && store[:jira_members] \
         | 
| 335 | 
            +
                    && store[:jira_members].include?(u[:jira][:nick])
         | 
| 336 | 
            +
                end
         | 
| 337 | 
            +
             | 
| 338 | 
            +
             | 
| 75 339 | 
             
              end
         | 
| 76 340 | 
             
            end
         | 
| @@ -12,7 +12,7 @@ module FerrisBueller | |
| 12 12 | 
             
                  @token   = options.fetch :token
         | 
| 13 13 | 
             
                  @logger  = options.fetch :logger, Slog.new
         | 
| 14 14 | 
             
                  @api_url = options.fetch :api_url, 'https://slack.com/api'
         | 
| 15 | 
            -
                  log.trace event: 'API client initialized'
         | 
| 15 | 
            +
                  log.trace event: 'Slack API client initialized'
         | 
| 16 16 | 
             
                end
         | 
| 17 17 |  | 
| 18 18 | 
             
                def send method, options={}
         | 
| @@ -21,7 +21,7 @@ module FerrisBueller | |
| 21 21 | 
             
                  log.trace event: 'sending api request', method: method, options: options
         | 
| 22 22 | 
             
                  res = Net::HTTP.post_form uri, options
         | 
| 23 23 | 
             
                  log.debug event: 'sent api request', method: method, options: options, response: res
         | 
| 24 | 
            -
                  JSON.parse res.body
         | 
| 24 | 
            +
                  JSON.parse res.body, symbolize_names: true
         | 
| 25 25 | 
             
                end
         | 
| 26 26 |  | 
| 27 27 | 
             
              private
         | 
| @@ -5,7 +5,7 @@ module FerrisBueller | |
| 5 5 | 
             
              module WebHelpers
         | 
| 6 6 | 
             
                JARO_WINKLER = FuzzyStringMatch::JaroWinklerPure.new
         | 
| 7 7 |  | 
| 8 | 
            -
                def  | 
| 8 | 
            +
                def jira ; settings.jira end
         | 
| 9 9 |  | 
| 10 10 | 
             
                def store ; settings.store end
         | 
| 11 11 |  | 
| @@ -15,16 +15,16 @@ module FerrisBueller | |
| 15 15 |  | 
| 16 16 |  | 
| 17 17 | 
             
                def user_lookup params, threshold=0.75
         | 
| 18 | 
            -
                  data = api.send 'users.info', user: params[ | 
| 18 | 
            +
                  data = api.send 'users.info', user: params[:user_id]
         | 
| 19 19 |  | 
| 20 20 | 
             
                  slack_user = {
         | 
| 21 | 
            -
                    key: data[ | 
| 22 | 
            -
                    name: (data[ | 
| 23 | 
            -
                    nick: data[ | 
| 24 | 
            -
                    email: data[ | 
| 21 | 
            +
                    key: data[:user][:id],
         | 
| 22 | 
            +
                    name: (data[:user][:real_name] || data[:user][:name]),
         | 
| 23 | 
            +
                    nick: data[:user][:name],
         | 
| 24 | 
            +
                    email: data[:user][:email]
         | 
| 25 25 | 
             
                  }
         | 
| 26 26 |  | 
| 27 | 
            -
                  jira_matches = store[ | 
| 27 | 
            +
                  jira_matches = store[:jira_users].values.map do |jira_user|
         | 
| 28 28 | 
             
                    distances = [ :name, :nick ].map do |k|
         | 
| 29 29 | 
             
                      compare slack_user[k], jira_user[k]
         | 
| 30 30 | 
             
                    end.compact
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: ferris-bueller
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.0. | 
| 4 | 
            +
              version: 0.0.3
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Sean Clemmer
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2016-01- | 
| 11 | 
            +
            date: 2016-01-22 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: slog
         | 
| @@ -150,6 +150,7 @@ files: | |
| 150 150 | 
             
            - lib/ferris-bueller.rb
         | 
| 151 151 | 
             
            - lib/ferris-bueller/constants.rb
         | 
| 152 152 | 
             
            - lib/ferris-bueller/helpers.rb
         | 
| 153 | 
            +
            - lib/ferris-bueller/jira_api.rb
         | 
| 153 154 | 
             
            - lib/ferris-bueller/main.rb
         | 
| 154 155 | 
             
            - lib/ferris-bueller/metadata.rb
         | 
| 155 156 | 
             
            - lib/ferris-bueller/mjolnir.rb
         |