ferris-bueller 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bd02010a5690c0772a134273d476c24e292d8b15
4
- data.tar.gz: b0e2d65aaa1b7bd1546c9681c322b4429e4a0f65
3
+ metadata.gz: bdfbffb726a39dad7e3cbef79559e7c00330d53f
4
+ data.tar.gz: 329a4fa79b56b17eb91378bf41d29de2c81c0d5a
5
5
  SHA512:
6
- metadata.gz: 41280791c72f6d5b32861eea7d9c588e533b76dce2485925f498b8a88e5a33dc89f3e959dedc46897350cf215924ce6ed7357598f220d66e8abd355dc8f61391
7
- data.tar.gz: ccdbaefb94e9c4ac5418857913c8db8c862c020f6e22c0c588226bf862313b8285fd565f9e7e4a971739b9f47fa2a11b78835eedc62b8c6d004c8c42877e142e
6
+ metadata.gz: 5cf95d2f4a02faa32358101b05902ecd2accf5dcc82a2a9062d15af11a587d7a1fd5e74f25fa5295bd50e8f0129c45fe586fbb13ae776083343cc1f0dd44d7d9
7
+ data.tar.gz: d386502333cfaf28a1990b2f51ff47db07b48fa8475c6945499ae955dd15e4264c9eb81fd9770a4f73f222954d8ad93b0838cefa0e81dae946e23b231ea8b556
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2015 Sean Clemmer and Blue Jeans Network
1
+ Copyright (c) 2016 Sean Clemmer and Blue Jeans Network
2
2
 
3
3
  Permission to use, copy, modify, and/or distribute this software for any
4
4
  purpose with or without fee is hereby granted, provided that the above
data/Readme.md CHANGED
@@ -1,3 +1,3 @@
1
- # Ferris
1
+ # Ferris Bueller ![Version](https://img.shields.io/gem/v/ferris-bueller.svg?style=flat-square)
2
2
 
3
- TODO
3
+ Successor to [Bender](https://github.com/sczizzo/bender), based on [Ferris](https://github.com/sczizzo/ferris)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.0
1
+ 0.0.1
data/bin/ferris-bueller CHANGED
@@ -1,3 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'ferris-bueller'
3
+ $stdout.sync = true
3
4
  FerrisBueller::Main.start
@@ -1,3 +1,7 @@
1
+ require 'json'
2
+ require 'net/http'
3
+
4
+ require 'ferris'
1
5
  require 'thin/logging'
2
6
  require 'queryparams'
3
7
 
@@ -19,6 +23,8 @@ module FerrisBueller
19
23
  Web.set :bind, options.bind
20
24
  Web.set :store, @store
21
25
  Web.set :logger, log
26
+ Web.set :verification_token, options.verification_token
27
+ Web.set :api, Ferris::API.new(token: options.api_token, logger: log)
22
28
 
23
29
  if log.level >= ::Logger::DEBUG
24
30
  Web.set :raise_errors, true
@@ -21,12 +21,18 @@ module FerrisBueller
21
21
 
22
22
 
23
23
  desc 'start', 'Start Bender HipChat bot and Web server'
24
- option :token, \
24
+ option :api_token, \
25
+ type: :string,
26
+ aliases: %w[ -a ],
27
+ desc: 'Set Slack API token',
28
+ required: true,
29
+ default: ENV['FERRIS_BUELLER_API_TOKEN']
30
+ option :verification_token, \
25
31
  type: :string,
26
32
  aliases: %w[ -t ],
27
- desc: 'Set Slack verificatino token',
33
+ desc: 'Set Slack verification token',
28
34
  required: true,
29
- default: ENV['FERRIS_BUELLER_TOKEN']
35
+ default: ENV['FERRIS_BUELLER_VERIFICATION_TOKEN']
30
36
  option :database, \
31
37
  type: :string,
32
38
  aliases: %w[ -d ],
@@ -0,0 +1,76 @@
1
+ module FerrisBueller
2
+ module Replies
3
+
4
+ def reply_whoami params
5
+ u = user_lookup(params)
6
+ if u
7
+ { text: "You're <@#{params['user_id']}>",
8
+ attachments: [
9
+ {
10
+ title: 'Slack User',
11
+ # pretext: 'User found via Slack APIs',
12
+ text: "```#{JSON.pretty_generate(u[:slack])}```",
13
+ mrkdwn_in: %w[ text pretext ]
14
+ },
15
+ {
16
+ title: 'Jira User',
17
+ # pretext: 'User found via Jira APIs',
18
+ text: "```#{JSON.pretty_generate(u[:jira])}```",
19
+ mrkdwn_in: %w[ text pretext ]
20
+ }
21
+ ]
22
+ }
23
+ else
24
+ {
25
+ text: "You're <@#{params['user_id']}>, but I can't say much more than that"
26
+ }
27
+ end
28
+ end
29
+
30
+
31
+ def reply_help params
32
+ { text: "Help!" }
33
+ end
34
+
35
+
36
+ def reply_dunno params
37
+ { text: "Invalid usage. Try the `help` command" }
38
+ end
39
+
40
+
41
+ def reply_list params
42
+ { text: 'list' }
43
+ end
44
+
45
+
46
+ def reply_summary params
47
+ { text: 'summary' }
48
+ end
49
+
50
+
51
+ def reply_show inc_num, params
52
+ { text: 'show %d' % inc_num }
53
+ end
54
+
55
+
56
+ def reply_resolve inc_num, params
57
+ { text: 'resolve %d' % inc_num }
58
+ end
59
+
60
+
61
+ def reply_close inc_num, params
62
+ { text: 'close %d' % inc_num }
63
+ end
64
+
65
+
66
+ def reply_open sev_num, summary, params
67
+ { text: 'open %d %s' % [ sev_num, summary ] }
68
+ end
69
+
70
+
71
+ def reply_comment inc_num, comment, params
72
+ { text: 'comment %d %s' % [ inc_num, comment ] }
73
+ end
74
+
75
+ end
76
+ end
@@ -1,46 +1,84 @@
1
1
  require 'json'
2
2
 
3
3
  require 'sinatra/base'
4
+ require 'fuzzystringmatch'
4
5
 
5
6
  require_relative 'metadata'
7
+ require_relative 'replies'
8
+ require_relative 'web_helpers'
6
9
 
7
10
  Thread.abort_on_exception = true
8
11
 
9
12
 
10
13
  module FerrisBueller
11
14
  class Web < Sinatra::Application
12
- def log ; settings.logger end
13
- def store ; settings.store end
14
-
15
+ include WebHelpers
16
+ include Replies
15
17
 
16
18
  get '/' do
17
- log.info event: 'get /'
19
+ log.debug event: 'get /'
18
20
  content_type :text
19
21
  'Sup.'
20
22
  end
21
23
 
22
24
 
23
25
  get '/v' do
24
- log.info event: 'get /v'
26
+ log.debug event: 'get /v'
25
27
  content_type :text
26
28
  VERSION
27
29
  end
28
30
 
29
31
 
30
32
  get '/s' do
31
- log.info event: 'get /s'
33
+ log.debug event: 'get /s'
32
34
  content_type :json
33
35
  store.to_json
34
36
  end
35
37
 
36
38
 
37
39
  post '/' do
38
- request.body.rewind
39
- body = request.body.read
40
- log.info event: 'post /', params: params, body: body
41
- # TODO
42
- content_type :json
43
- { params: params, body: body }.to_json
40
+ log.debug event: 'post /', params: params
41
+ unless params['token'] == settings.verification_token
42
+ log.error event: 'verification failed', params: params
43
+ halt 403
44
+ else
45
+ content_type :json
46
+ reply = respond(params)
47
+ JSON.generate reply if reply
48
+ end
49
+ end
50
+
51
+
52
+
53
+ private
54
+
55
+ def respond params
56
+ case params['text'].strip
57
+ when 'whoami'
58
+ reply_whoami params
59
+ when /^help/
60
+ reply_help params
61
+ when ''
62
+ reply_list params
63
+ when 'list'
64
+ reply_list params
65
+ when 'summary'
66
+ reply_summary params
67
+ when /^(\d+)$/
68
+ reply_show $1, params
69
+ when /^show (\d+)/
70
+ reply_show $1, params
71
+ when /^resolve (\d+)/
72
+ reply_resolve $1, params
73
+ when /^close (\d+)/
74
+ reply_close $1, params
75
+ when /^open (\d+) (.*)/m
76
+ reply_open $1, $2, params
77
+ when /^comment (\d+) (.*)/m
78
+ reply_comment $1, $2, params
79
+ else
80
+ reply_dunno params
81
+ end
44
82
  end
45
83
 
46
84
  end
@@ -0,0 +1,69 @@
1
+ module FerrisBueller
2
+ module WebHelpers
3
+
4
+ def store ; settings.store end
5
+
6
+ def log ; settings.logger end
7
+
8
+ def api ; settings.api end
9
+
10
+
11
+ def user_lookup params, threshold=0.75
12
+ data = api.send 'users.info', user: params['user_id']
13
+
14
+ slack_user = {
15
+ key: data['user']['id'],
16
+ name: (data['user']['real_name'] || data['user']['name']),
17
+ nick: data['user']['name'],
18
+ email: data['user']['email']
19
+ }
20
+
21
+ jira_matches = store['jira_users'].values.map do |jira_user|
22
+ distances = [ :name, :nick ].map do |k|
23
+ compare slack_user[k], jira_user[k]
24
+ end.compact
25
+ mean_distance = 1.0 * distances.inject(:+) / distances.size
26
+ if mean_distance > threshold
27
+ { user: jira_user, distance: mean_distance}
28
+ end
29
+ end.compact
30
+
31
+ jira_match = jira_matches.sort_by { |m| m[:distance] }.last
32
+
33
+ unless jira_match
34
+ log.warn \
35
+ event: 'unmatched user',
36
+ slack_user: slack_user
37
+ return nil
38
+ end
39
+
40
+ log.info \
41
+ event: 'matched user',
42
+ slack_user: slack_user,
43
+ jira_match: jira_match
44
+
45
+ return { slack: slack_user, jira: jira_match[:user] }
46
+
47
+ rescue StandardError => e
48
+ log.error \
49
+ error: 'could not lookup users',
50
+ event: 'exception',
51
+ exception: e.inspect,
52
+ class: e.class,
53
+ message: e.message,
54
+ backtrace: e.backtrace
55
+ return nil
56
+ end
57
+
58
+
59
+ def compare name1, name2
60
+ return nil if name1.nil? || name1.empty?
61
+ return nil if name2.nil? || name2.empty?
62
+ @@jaro ||= FuzzyStringMatch::JaroWinkler.create :native
63
+ n1 = name1.gsub(/\W/, '').downcase
64
+ n2 = name2.gsub(/\W/, '').downcase
65
+ @@jaro.getDistance n1, n2
66
+ end
67
+
68
+ end
69
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ferris-bueller
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Clemmer
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '1.4'
83
+ - !ruby/object:Gem::Dependency
84
+ name: ferris
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: eventmachine
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -138,7 +152,8 @@ dependencies:
138
152
  version: 1.9.6
139
153
  description: Successor to Bender, based on Ferris.
140
154
  email: sclemmer@bluejeans.com
141
- executables: []
155
+ executables:
156
+ - ferris-bueller
142
157
  extensions: []
143
158
  extra_rdoc_files: []
144
159
  files:
@@ -152,7 +167,9 @@ files:
152
167
  - lib/ferris-bueller/main.rb
153
168
  - lib/ferris-bueller/metadata.rb
154
169
  - lib/ferris-bueller/mjolnir.rb
170
+ - lib/ferris-bueller/replies.rb
155
171
  - lib/ferris-bueller/web.rb
172
+ - lib/ferris-bueller/web_helpers.rb
156
173
  homepage: https://github.com/sczizzo/ferris-bueller
157
174
  licenses:
158
175
  - ISC
@@ -178,4 +195,3 @@ signing_key:
178
195
  specification_version: 4
179
196
  summary: Successor to Bender, based on Ferris
180
197
  test_files: []
181
- has_rdoc: