slack-ruby-bot-server-rtm 0.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 (60) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +15 -0
  5. data/.rubocop_todo.yml +29 -0
  6. data/.travis.yml +21 -0
  7. data/CHANGELOG.md +5 -0
  8. data/CONTRIBUTING.md +125 -0
  9. data/Dangerfile +3 -0
  10. data/Gemfile +40 -0
  11. data/LICENSE +21 -0
  12. data/README.md +61 -0
  13. data/RELEASING.md +61 -0
  14. data/Rakefile +16 -0
  15. data/lib/slack-ruby-bot-server-rtm.rb +10 -0
  16. data/lib/slack-ruby-bot-server-rtm/config.rb +29 -0
  17. data/lib/slack-ruby-bot-server-rtm/ext.rb +3 -0
  18. data/lib/slack-ruby-bot-server-rtm/ext/slack-ruby-bot.rb +4 -0
  19. data/lib/slack-ruby-bot-server-rtm/ext/slack-ruby-bot/client.rb +14 -0
  20. data/lib/slack-ruby-bot-server-rtm/ext/slack-ruby-bot/commands/base.rb +20 -0
  21. data/lib/slack-ruby-bot-server-rtm/lifecycle.rb +31 -0
  22. data/lib/slack-ruby-bot-server-rtm/rspec.rb +5 -0
  23. data/lib/slack-ruby-bot-server-rtm/server.rb +52 -0
  24. data/lib/slack-ruby-bot-server-rtm/version.rb +7 -0
  25. data/sample_apps/sample_app_activerecord/.rspec +3 -0
  26. data/sample_apps/sample_app_activerecord/.standalone_migrations +3 -0
  27. data/sample_apps/sample_app_activerecord/Gemfile +26 -0
  28. data/sample_apps/sample_app_activerecord/Procfile +1 -0
  29. data/sample_apps/sample_app_activerecord/README.md +12 -0
  30. data/sample_apps/sample_app_activerecord/Rakefile +16 -0
  31. data/sample_apps/sample_app_activerecord/commands.rb +4 -0
  32. data/sample_apps/sample_app_activerecord/commands/help.rb +21 -0
  33. data/sample_apps/sample_app_activerecord/commands/whoami.rb +8 -0
  34. data/sample_apps/sample_app_activerecord/config.ru +24 -0
  35. data/sample_apps/sample_app_activerecord/config/newrelic.yml +217 -0
  36. data/sample_apps/sample_app_activerecord/config/postgresql.yml +17 -0
  37. data/sample_apps/sample_app_activerecord/db/migrate/20170307164946_create_teams_table.rb +14 -0
  38. data/sample_apps/sample_app_activerecord/db/migrate/20190323181453_add_activated_fields.rb +9 -0
  39. data/sample_apps/sample_app_activerecord/db/schema.rb +31 -0
  40. data/sample_apps/sample_app_activerecord/spec/api/root_spec.rb +18 -0
  41. data/sample_apps/sample_app_activerecord/spec/commands/help_spec.rb +16 -0
  42. data/sample_apps/sample_app_activerecord/spec/commands/whoami_spec.rb +16 -0
  43. data/sample_apps/sample_app_activerecord/spec/spec_helper.rb +21 -0
  44. data/sample_apps/sample_app_mongoid/.rspec +3 -0
  45. data/sample_apps/sample_app_mongoid/Gemfile +22 -0
  46. data/sample_apps/sample_app_mongoid/Procfile +1 -0
  47. data/sample_apps/sample_app_mongoid/README.md +14 -0
  48. data/sample_apps/sample_app_mongoid/Rakefile +12 -0
  49. data/sample_apps/sample_app_mongoid/commands.rb +4 -0
  50. data/sample_apps/sample_app_mongoid/commands/help.rb +21 -0
  51. data/sample_apps/sample_app_mongoid/commands/whoami.rb +8 -0
  52. data/sample_apps/sample_app_mongoid/config.ru +16 -0
  53. data/sample_apps/sample_app_mongoid/config/mongoid.yml +27 -0
  54. data/sample_apps/sample_app_mongoid/config/newrelic.yml +217 -0
  55. data/sample_apps/sample_app_mongoid/spec/api/root_spec.rb +18 -0
  56. data/sample_apps/sample_app_mongoid/spec/commands/help_spec.rb +16 -0
  57. data/sample_apps/sample_app_mongoid/spec/commands/whoami_spec.rb +16 -0
  58. data/sample_apps/sample_app_mongoid/spec/spec_helper.rb +29 -0
  59. data/slack-ruby-bot-server-rtm.gemspec +22 -0
  60. metadata +142 -0
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SlackRubyBotServer
4
+ module RealTime
5
+ module Config
6
+ extend self
7
+
8
+ attr_accessor :server_class
9
+
10
+ def reset!
11
+ self.server_class = SlackRubyBotServer::RealTime::Server
12
+ end
13
+
14
+ reset!
15
+ end
16
+
17
+ class << self
18
+ def configure
19
+ block_given? ? yield(Config) : Config
20
+ end
21
+
22
+ def config
23
+ Config
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ SlackRubyBotServer::RealTime::Config.reset!
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'ext/slack-ruby-bot'
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'slack-ruby-bot/client'
4
+ require_relative 'slack-ruby-bot/commands/base'
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SlackRubyBot
4
+ class Client
5
+ # keep track of the team that the client is connected to
6
+ attr_accessor :owner
7
+ end
8
+ end
9
+
10
+ SlackRubyBot::Client.logger.level = Logger::WARN
11
+
12
+ Slack::RealTime::Client.configure do |config|
13
+ config.store_class = Slack::RealTime::Stores::Starter
14
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SlackRubyBot
4
+ module Commands
5
+ class Base
6
+ class << self
7
+ alias _invoke invoke
8
+
9
+ def invoke(client, data)
10
+ _invoke client, data
11
+ rescue StandardError => e
12
+ logger.info "#{name.demodulize.upcase}: #{client.owner}, #{e.class}: #{e}"
13
+ logger.debug e.backtrace.join("\n")
14
+ client.say(channel: data.channel, text: e.message)
15
+ true
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ SlackRubyBotServer.configure do |config|
4
+ config.oauth_scope ||= ['bot']
5
+ end
6
+
7
+ SlackRubyBotServer::Config.service_class.instance.on :starting do |team, _error, options|
8
+ SlackRubyBotServer::Config.service_class.instance.logger.info "Starting real-time team #{team}."
9
+ options = { team: team }
10
+ server = SlackRubyBotServer::RealTime::Config.server_class.new(options)
11
+ SlackRubyBotServer::RealTime::Server.start_server! team, server
12
+ end
13
+
14
+ SlackRubyBotServer::Config.service_class.instance.on :restarting do |team, _error, options|
15
+ SlackRubyBotServer::Config.service_class.instance.logger.info "Restarting real-time team #{team}."
16
+ SlackRubyBotServer::RealTime::Server.start_server! team, server, options[:wait]
17
+ end
18
+
19
+ SlackRubyBotServer::Config.service_class.instance.on :stopped do |team, _error, _options|
20
+ SlackRubyBotServer::Config.service_class.instance.logger.info "Stopping real-time team #{team}."
21
+ begin
22
+ team.server&.stop!
23
+ ensure
24
+ team.server = nil
25
+ end
26
+ end
27
+
28
+ SlackRubyBotServer::Config.service_class.instance.on :deactivated do |team, _error, _options|
29
+ SlackRubyBotServer::Config.service_class.instance.logger.info "De-activating real-time team #{team}."
30
+ team.server = nil
31
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'slack-ruby-bot/rspec'
4
+ require 'slack-ruby-bot-server/rspec'
5
+ require 'slack-ruby-bot-server-rtm'
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'ext/slack-ruby-bot/client'
4
+
5
+ module SlackRubyBotServer
6
+ module RealTime
7
+ class Server < ::SlackRubyBot::Server
8
+ attr_accessor :team
9
+
10
+ def initialize(attrs = {})
11
+ attrs = attrs.dup
12
+ @team = attrs.delete(:team)
13
+ raise 'Missing team' unless @team
14
+
15
+ attrs[:token] = @team.token
16
+ super(attrs)
17
+ open!
18
+ end
19
+
20
+ def self.start_server!(team, server, wait = 1)
21
+ team.server = server
22
+ server.start_async
23
+ rescue StandardError => e
24
+ SlackRubyBotServer::Config.service_class.instance.run_callbacks :error, team, e
25
+ case e.message
26
+ when 'account_inactive', 'invalid_auth' then
27
+ SlackRubyBotServer::Config.logger.error "#{team.name}: #{e.message}, team will be deactivated."
28
+ SlackRubyBotServer::RealTime::Service.instance.deactivate! team
29
+ elsef
30
+ wait = e.retry_after if e.is_a?(Slack::Web::Api::Errors::TooManyRequestsError)
31
+ SlackRubyBotServer::Config.logger.error "#{team.name}: #{e.message}, restarting in #{wait} second(s)."
32
+ sleep(wait)
33
+ start_server! team, server, [wait * 2, 60].min
34
+ end
35
+ end
36
+
37
+ def restart!(_wait = 1)
38
+ # when an integration is disabled, a live socket is closed, which causes the default behavior of the client to restart
39
+ # it would keep retrying without checking for account_inactive or such, we want to restart via service which will disable an inactive team
40
+ logger.info "#{team.name}: socket closed, restarting ..."
41
+ SlackRubyBotServer::RealTime::Service.instance.restart! team
42
+ open!
43
+ end
44
+
45
+ private
46
+
47
+ def open!
48
+ client.owner = team
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SlackRubyBotServer
4
+ module RealTime
5
+ VERSION = '0.1.0'
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ --color
2
+ --format=documentation
3
+
@@ -0,0 +1,3 @@
1
+ config:
2
+ database: config/postgresql.yml
3
+
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gem 'activerecord', '~> 5.0.0', require: 'active_record'
6
+ gem 'newrelic-slack-ruby-bot'
7
+ gem 'otr-activerecord', '~> 1.2.1'
8
+ gem 'pg'
9
+ gem 'rack-server-pages'
10
+ gem 'rack-test'
11
+ gem 'slack-ruby-bot-server-rtm', path: '../../'
12
+ gem 'unicorn'
13
+
14
+ group :development, :test do
15
+ gem 'standalone_migrations', '~> 5.2'
16
+ end
17
+
18
+ group :test do
19
+ gem 'database_cleaner'
20
+ gem 'fabrication'
21
+ gem 'faker'
22
+ gem 'rake'
23
+ gem 'rspec'
24
+ gem 'vcr'
25
+ gem 'webmock'
26
+ end
@@ -0,0 +1 @@
1
+ web: bundle exec unicorn -p $PORT
@@ -0,0 +1,12 @@
1
+ ### What's this?
2
+
3
+ This is a sample slack-ruby-bot-server with ActiveRecord.
4
+
5
+ ### Run
6
+
7
+ ```
8
+ bundle install
9
+ rake db:create db:migrate
10
+ RAILS_ENV=test rake db:migrate
11
+ rackup
12
+ ```
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubygems'
4
+ require 'bundler/setup'
5
+
6
+ require 'rspec/core'
7
+ require 'rspec/core/rake_task'
8
+
9
+ require 'standalone_migrations'
10
+ StandaloneMigrations::Tasks.load_tasks
11
+
12
+ RSpec::Core::RakeTask.new(:spec) do |spec|
13
+ spec.pattern = FileList['spec/**/*_spec.rb']
14
+ end
15
+
16
+ task default: ['db:create', 'db:migrate', :spec]
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'commands/help'
4
+ require_relative 'commands/whoami'
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Help < SlackRubyBot::Commands::Base
4
+ HELP = <<~EOS
5
+ ```
6
+ I am your friendly slack-ruby-bot-server, here to help.
7
+
8
+ General
9
+ -------
10
+
11
+ help - get this helpful message
12
+ whoami - print your username
13
+
14
+ ```
15
+ EOS
16
+ def self.call(client, data, _match)
17
+ client.say(channel: data.channel, text: [HELP, SlackRubyBotServer::INFO].join("\n"))
18
+ client.say(channel: data.channel)
19
+ logger.info "HELP: #{client.owner}, user=#{data.user}"
20
+ end
21
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Whoami < SlackRubyBot::Commands::Base
4
+ def self.call(client, data, _match)
5
+ client.say(channel: data.channel, text: "<@#{data.user}>")
6
+ logger.info "UNAME: #{client.owner}, user=#{data.user}"
7
+ end
8
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ ENV['RACK_ENV'] ||= 'development'
4
+
5
+ Bundler.require :default
6
+
7
+ require_relative 'commands'
8
+ require 'yaml'
9
+ require 'erb'
10
+
11
+ ActiveRecord::Base.establish_connection(
12
+ YAML.safe_load(
13
+ ERB.new(
14
+ File.read('config/postgresql.yml')
15
+ ).result, [], [], true
16
+ )[ENV['RACK_ENV']]
17
+ )
18
+
19
+ NewRelic::Agent.manual_start
20
+
21
+ SlackRubyBotServer::App.instance.prepare!
22
+ SlackRubyBotServer::Service.start!
23
+
24
+ run SlackRubyBotServer::Api::Middleware.instance
@@ -0,0 +1,217 @@
1
+ # Here are the settings that are common to all environments
2
+ common: &default_settings
3
+ # ============================== LICENSE KEY ===============================
4
+
5
+ # You must specify the license key associated with your New Relic
6
+ # account. This key binds your Agent's data to your account in the
7
+ # New Relic service.
8
+ license_key: '<%= ENV["NEW_RELIC_LICENSE_KEY"] %>'
9
+
10
+ # Application Name Set this to be the name of your application as
11
+ # you'd like it show up in New Relic. The service will then auto-map
12
+ # instances of your application into an "application" on your
13
+ # dashboard page. If you want to map this instance into multiple
14
+ # apps, like "AJAX Requests" and "All UI" then specify a semicolon
15
+ # separated list of up to three distinct names, or a yaml list.
16
+ app_name: <%= ENV["NEW_RELIC_APP_NAME"] || 'SlackRubyBotServer' %>
17
+
18
+ # When "true", the agent collects performance data about your
19
+ # application and reports this data to the New Relic service at
20
+ # newrelic.com. This global switch is normally overridden for each
21
+ # environment below. (formerly called 'enabled')
22
+ monitor_mode: true
23
+
24
+ # Developer mode should be off in every environment but
25
+ # development as it has very high overhead in memory.
26
+ developer_mode: false
27
+
28
+ # The newrelic agent generates its own log file to keep its logging
29
+ # information separate from that of your application. Specify its
30
+ # log level here.
31
+ log_level: info
32
+
33
+ # Optionally set the path to the log file This is expanded from the
34
+ # root directory (may be relative or absolute, e.g. 'log/' or
35
+ # '/var/log/') The agent will attempt to create this directory if it
36
+ # does not exist.
37
+ # log_file_path: 'log'
38
+
39
+ # Optionally set the name of the log file, defaults to 'newrelic_agent.log'
40
+ # log_file_name: 'newrelic_agent.log'
41
+
42
+ # The newrelic agent communicates with the service via http by
43
+ # default. If you want to communicate via https to increase
44
+ # security, then turn on SSL by setting this value to true. Note,
45
+ # this will result in increased CPU overhead to perform the
46
+ # encryption involved in SSL communication, but this work is done
47
+ # asynchronously to the threads that process your application code,
48
+ # so it should not impact response times.
49
+ ssl: false
50
+
51
+ # EXPERIMENTAL: enable verification of the SSL certificate sent by
52
+ # the server. This setting has no effect unless SSL is enabled
53
+ # above. This may block your application. Only enable it if the data
54
+ # you send us needs end-to-end verified certificates.
55
+ #
56
+ # This means we cannot cache the DNS lookup, so each request to the
57
+ # service will perform a lookup. It also means that we cannot
58
+ # use a non-blocking lookup, so in a worst case, if you have DNS
59
+ # problems, your app may block indefinitely.
60
+ # verify_certificate: true
61
+
62
+ # Set your application's Apdex threshold value with the 'apdex_t'
63
+ # setting, in seconds. The apdex_t value determines the buckets used
64
+ # to compute your overall Apdex score.
65
+ # Requests that take less than apdex_t seconds to process will be
66
+ # classified as Satisfying transactions; more than apdex_t seconds
67
+ # as Tolerating transactions; and more than four times the apdex_t
68
+ # value as Frustrating transactions.
69
+ # For more about the Apdex standard, see
70
+ # http://newrelic.com/docs/general/apdex
71
+
72
+ apdex_t: 0.5
73
+
74
+ #============================== Browser Monitoring ===============================
75
+ # New Relic Real User Monitoring gives you insight into the performance real users are
76
+ # experiencing with your website. This is accomplished by measuring the time it takes for
77
+ # your users' browsers to download and render your web pages by injecting a small amount
78
+ # of JavaScript code into the header and footer of each page.
79
+ browser_monitoring:
80
+ # By default the agent automatically injects the monitoring JavaScript
81
+ # into web pages. Set this attribute to false to turn off this behavior.
82
+ auto_instrument: true
83
+
84
+ # Proxy settings for connecting to the service.
85
+ #
86
+ # If a proxy is used, the host setting is required. Other settings
87
+ # are optional. Default port is 8080.
88
+ #
89
+ # proxy_host: hostname
90
+ # proxy_port: 8080
91
+ # proxy_user:
92
+ # proxy_pass:
93
+
94
+
95
+ # Tells transaction tracer and error collector (when enabled)
96
+ # whether or not to capture HTTP params. When true, frameworks can
97
+ # exclude HTTP parameters from being captured.
98
+ # Rails: the RoR filter_parameter_logging excludes parameters
99
+ # Java: create a config setting called "ignored_params" and set it to
100
+ # a comma separated list of HTTP parameter names.
101
+ # ex: ignored_params: credit_card, ssn, password
102
+ capture_params: true
103
+
104
+
105
+ # Transaction tracer captures deep information about slow
106
+ # transactions and sends this to the service once a
107
+ # minute. Included in the transaction is the exact call sequence of
108
+ # the transactions including any SQL statements issued.
109
+ transaction_tracer:
110
+
111
+ # Transaction tracer is enabled by default. Set this to false to
112
+ # turn it off. This feature is only available at the Professional
113
+ # and above product levels.
114
+ enabled: true
115
+
116
+ # Threshold in seconds for when to collect a transaction
117
+ # trace. When the response time of a controller action exceeds
118
+ # this threshold, a transaction trace will be recorded and sent to
119
+ # the service. Valid values are any float value, or (default)
120
+ # "apdex_f", which will use the threshold for an dissatisfying
121
+ # Apdex controller action - four times the Apdex T value.
122
+ transaction_threshold: apdex_f
123
+
124
+ # When transaction tracer is on, SQL statements can optionally be
125
+ # recorded. The recorder has three modes, "off" which sends no
126
+ # SQL, "raw" which sends the SQL statement in its original form,
127
+ # and "obfuscated", which strips out numeric and string literals
128
+ record_sql: obfuscated
129
+
130
+ # Threshold in seconds for when to collect stack trace for a SQL
131
+ # call. In other words, when SQL statements exceed this threshold,
132
+ # then capture and send the current stack trace. This is
133
+ # helpful for pinpointing where long SQL calls originate from
134
+ stack_trace_threshold: 0.500
135
+
136
+ # Determines whether the agent will capture query plans for slow
137
+ # SQL queries. Only supported in mysql and postgres. Should be
138
+ # set to false when using other adapters.
139
+ # explain_enabled: true
140
+
141
+ # Threshold for query execution time below which query plans will not
142
+ # not be captured. Relevant only when `explain_enabled` is true.
143
+ # explain_threshold: 0.5
144
+
145
+ # Error collector captures information about uncaught exceptions and
146
+ # sends them to the service for viewing
147
+ error_collector:
148
+
149
+ # Error collector is enabled by default. Set this to false to turn
150
+ # it off. This feature is only available at the Professional and above
151
+ # product levels
152
+ enabled: true
153
+
154
+ # Rails Only - tells error collector whether or not to capture a
155
+ # source snippet around the place of the error when errors are View
156
+ # related.
157
+ capture_source: true
158
+
159
+ # To stop specific errors from reporting to New Relic, set this property
160
+ # to comma separated values. Default is to ignore routing errors
161
+ # which are how 404's get triggered.
162
+ #
163
+ ignore_errors: ActionController::RoutingError
164
+
165
+ # (Advanced) Uncomment this to ensure the cpu and memory samplers
166
+ # won't run. Useful when you are using the agent to monitor an
167
+ # external resource
168
+ # disable_samplers: true
169
+
170
+ # If you aren't interested in visibility in these areas, you can
171
+ # disable the instrumentation to reduce overhead.
172
+ #
173
+ # disable_view_instrumentation: true
174
+ # disable_activerecord_instrumentation: true
175
+ # disable_memcache_instrumentation: true
176
+ # disable_dj: true
177
+
178
+ # If you're interested in capturing memcache keys as though they
179
+ # were SQL uncomment this flag. Note that this does increase
180
+ # overhead slightly on every memcached call, and can have security
181
+ # implications if your memcached keys are sensitive
182
+ # capture_memcache_keys: true
183
+
184
+ # Certain types of instrumentation such as GC stats will not work if
185
+ # you are running multi-threaded. Please let us know.
186
+ # multi_threaded = false
187
+
188
+ # Application Environments
189
+ # ------------------------------------------
190
+
191
+ development:
192
+ <<: *default_settings
193
+ # Turn off communication to New Relic service in development mode (also
194
+ # 'enabled').
195
+ # NOTE: for initial evaluation purposes, you may want to temporarily
196
+ # turn the agent on in development mode.
197
+ monitor_mode: false
198
+
199
+ # Rails Only - when running in Developer Mode, the New Relic Agent will
200
+ # present performance information on the last 100 transactions you have
201
+ # executed since starting the mongrel.
202
+ # NOTE: There is substantial overhead when running in developer mode.
203
+ # Do not use for production or load testing.
204
+ developer_mode: true
205
+
206
+ # Enable textmate links
207
+ # textmate: true
208
+
209
+ test:
210
+ <<: *default_settings
211
+ # It almost never makes sense to turn on the agent when running
212
+ # unit, functional or integration tests or the like.
213
+ monitor_mode: false
214
+
215
+ production:
216
+ <<: *default_settings
217
+ monitor_mode: true