lita-ping-me 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: b9741319f9d696dbcbb102797c2f4f1b5d37e553
4
+ data.tar.gz: 702b23b99a9da5de1c950a88cfd136449df3a6ec
5
+ SHA512:
6
+ metadata.gz: 0cbe3360914db7218877338b239d7841add16c3d7bdd635529844c4e7508ec76499bc103ec53862d8bda940077bd6c97446d4f4b3969585ce5a517e0f1097c46
7
+ data.tar.gz: 94f6ea544e715a665e5ad4652e136e27ede3d3347e18f7de4fbf83a1501e8b45d95f56f3a097d13b9147f423bff829f0817c38b8bbad72855624df432e3e590a
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in lita-keepalive.gemspec
4
+ gem 'pry'
5
+ gemspec
data/README.md ADDED
@@ -0,0 +1,48 @@
1
+ # lita-ping-me
2
+
3
+ **lita-ping-me** is a (slack) handler for [Lita](https://www.lita.io/) to ping a web service periodically and post to a channel if there is an error
4
+
5
+ ## Installation
6
+
7
+ Add **lita-ping-me** to your Lita instance's Gemfile:
8
+
9
+ ``` ruby
10
+ gem "lita-ping-me"
11
+ ```
12
+
13
+ ## Configuration
14
+
15
+ ### Required attributes
16
+
17
+ * `urls` (Array) – An array of urls for lita-ping-me to periodically check
18
+ * `frequency` (Integer) – How frequent to check for the service in minutes
19
+ * `channel` (String) – Which (slack) channel id to post alerts to.
20
+
21
+ To get the channel ID:
22
+
23
+ ```
24
+ channel find channel-name
25
+ ```
26
+
27
+ ### Example
28
+
29
+ ``` ruby
30
+ Lita.configure do |config|
31
+ config.handlers.ping_me.urls = ["http://google.com", "https://github.com"]
32
+ config.handlers.ping_me.room = 'C03EV32P*'
33
+ config.handlers.ping_me.frequency = 1
34
+ end
35
+ ```
36
+
37
+ ### Usage
38
+
39
+ * `lita status http://google.com` -> returns status of url
40
+ * `lita times http://google.com 200` -> returns last 10 times of url
41
+ * `lita any errors?` -> checks currently set urls for any 500's
42
+ * `lita sleep` -> stop checking for errors for 20 minutes
43
+ * `lita sleep 30` -> stop checking for errors for 30 minutes
44
+
45
+
46
+ ## License
47
+
48
+ [MIT](http://opensource.org/licenses/MIT)
@@ -0,0 +1,7 @@
1
+ require "lita"
2
+
3
+ Lita.load_locales Dir[File.expand_path(
4
+ File.join("..", "..", "locales", "*.yml"), __FILE__
5
+ )]
6
+
7
+ require "lita/handlers/ping-me"
@@ -0,0 +1,42 @@
1
+ require 'typhoeus'
2
+
3
+ module Lita
4
+ module Handlers
5
+ class Connection
6
+ attr_reader :urls, :redis, :log
7
+
8
+ def initialize(urls, redis, log)
9
+ @redis = redis
10
+ @log = log
11
+ @urls = Array(urls)
12
+ end
13
+
14
+ def current_status
15
+ requests = queue_requests
16
+ hydra.run
17
+ format_requests(requests)
18
+ end
19
+
20
+ private
21
+
22
+ def format_requests(requests)
23
+ requests.each_with_object({}) do |request, hash|
24
+ redis.append("#{request.base_url}-#{request.response.code}", "#{Time.now.strftime("%Y-%m-%d %H:%M:%S")}, #{request.response.time}" + "\n")
25
+ hash[request.base_url] = { code: request.response.code, time: request.response.time }
26
+ end
27
+ end
28
+
29
+ def queue_requests
30
+ urls.map do |url|
31
+ Typhoeus::Request.new(url).tap do |request|
32
+ hydra.queue(request)
33
+ end
34
+ end
35
+ end
36
+
37
+ def hydra
38
+ @hydra ||= Typhoeus::Hydra.new
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,139 @@
1
+ require 'json'
2
+ require 'time'
3
+ require_relative 'connection'
4
+
5
+ module Lita
6
+ module Handlers
7
+ class PingMe < Handler
8
+ SLEEP_TIME = 20
9
+ FIVE_MINUTES = 5
10
+ TWELVE_HOURS = 720
11
+
12
+ config :urls
13
+ config :room
14
+ config :frequency
15
+
16
+ route(/^channel find (.+)/) do |response|
17
+ response.reply(channels(response.args.last).fetch('id', 'not found'))
18
+ end
19
+
20
+ route(/^status[\s+]?(.+)?/) do |response|
21
+ urls = response.args.empty? ? config.urls : response.args
22
+ response.reply(format(current_status(clean_urls(urls))))
23
+ end
24
+
25
+ route(/^times[\s+]?(.+)?/) do |response|
26
+ url, code = response.args.first(2)
27
+ response.reply(format_times(redis.get("#{url}-#{code}")))
28
+ end
29
+
30
+ route(/^sleep[\s+]?(\d+)?/, :sleep)
31
+
32
+ route(/^any errors\?/, :check_for_errors)
33
+
34
+ on(:status) do |_|
35
+ check_for_errors(_)
36
+ end
37
+
38
+ on(:current_status) do |payload|
39
+ send_message(format(current_status))
40
+ end
41
+
42
+ on(:loaded) do
43
+ start_pinging
44
+
45
+ every(minutes_to_seconds(TWELVE_HOURS)) do |timer|
46
+ robot.trigger(:current_status)
47
+ end
48
+ end
49
+
50
+ def sleep(response)
51
+ time = parse_time(response.args.first.to_i)
52
+ timer.stop
53
+ after(time) { start_pinging }
54
+ response.reply("Sure, will sleep for #{seconds_to_minutes(time)} minutes")
55
+ end
56
+
57
+ def check_for_errors(_)
58
+ errors.each do |url, status|
59
+ send_message("#{url} is down: #{status.inspect}")
60
+ end
61
+ end
62
+
63
+ private
64
+
65
+ def errors
66
+ state = current_status
67
+ log.info(state)
68
+ state.select { |url, status| status[:code] >= 500 }
69
+ end
70
+
71
+ def parse_time(minutes)
72
+ minutes == 0 ? minutes_to_seconds(SLEEP_TIME) : minutes_to_seconds(minutes)
73
+ end
74
+
75
+ def seconds_to_minutes(seconds)
76
+ seconds / 60
77
+ end
78
+
79
+ def minutes_to_seconds(minutes)
80
+ minutes * 60
81
+ end
82
+
83
+ def start_pinging
84
+ every(frequency) do |timer|
85
+ robot.trigger(:status)
86
+ end
87
+ end
88
+
89
+ def current_status(urls = config.urls)
90
+ Connection.new(urls, redis, log).current_status
91
+ end
92
+
93
+ def target(payload = {})
94
+ @target ||= Source.new(room: config.room)
95
+ end
96
+
97
+ def send_message(msg)
98
+ robot.send_message(target, msg)
99
+ end
100
+
101
+ def frequency
102
+ minutes_to_seconds(config.frequency || FIVE_MINUTES)
103
+ end
104
+
105
+ def timer
106
+ ObjectSpace.each_object(Lita::Timer).to_a.find do |t|
107
+ t.instance_variable_get("@interval") == frequency
108
+ end
109
+ end
110
+
111
+ def format(status)
112
+ status.map do |url, status|
113
+ "#{url}: code #{status[:code]}, time: #{status[:time]}"
114
+ end.join("\n")
115
+ end
116
+
117
+ def clean_urls(urls)
118
+ return unless urls
119
+ urls.map do |url|
120
+ if url.match(/|/)
121
+ url = url.split('|').first.gsub("<", '').gsub(">", '')
122
+ end
123
+ url
124
+ end
125
+ end
126
+
127
+ def format_times(times)
128
+ times.split("\n").last(10)
129
+ end
130
+
131
+ def channels(channel_name)
132
+ channels = JSON.parse(http.get("https://slack.com/api/channels.list?token=#{Lita.config.adapters.slack.token}").body)
133
+ channels['channels'].find {|c| c["name"] == channel_name } || {}
134
+ end
135
+ end
136
+
137
+ Lita.register_handler(PingMe)
138
+ end
139
+ 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
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "lita-ping-me"
7
+ spec.version = '0.0.1'
8
+ spec.authors = ["Douglas Roper"]
9
+ spec.email = ["dougdroper@gmail.com"]
10
+ spec.summary = %q{Lita plugin for periodically checking statuses of websites}
11
+ spec.description = %q{
12
+ periodically checks status of website and alerts chat room if response error
13
+ }
14
+ spec.homepage = "http://github.com/dougdroper/lita-ping-me"
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_runtime_dependency "lita", "~> 4.0"
23
+ spec.add_runtime_dependency "typhoeus", "~> 0.7"
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.7"
26
+ spec.add_development_dependency "rake", "~> 10.0"
27
+ spec.add_development_dependency "rspec", "~> 3.3"
28
+ end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Lita::Handlers::PingMe, lita_handler: true do
4
+
5
+ context '#sleep' do
6
+ it 'with no args' do
7
+ send_message("sleep")
8
+ expect(replies.last).to eq("Sure, will sleep for 20 minutes")
9
+ end
10
+
11
+ it 'with args' do
12
+ send_message("sleep 30")
13
+ expect(replies.last).to eq("Sure, will sleep for 30 minutes")
14
+ end
15
+
16
+ it 'defaults with invalid args' do
17
+ send_message("sleep xxx")
18
+ expect(replies.last).to eq("Sure, will sleep for 20 minutes")
19
+ end
20
+ end
21
+
22
+ context '#status' do
23
+ let(:current_status) do
24
+ {
25
+ 'http://www.example.com/search' => { code: 500, time: 4.882903 },
26
+ 'http://www.example.com/other' => { code: 200, time: 6.882903 },
27
+ 'http://www.example.com/about' => { code: 503, time: 2.882 }
28
+ }
29
+ end
30
+
31
+ let(:response) { double(current_status: current_status) }
32
+
33
+ context 'default urls' do
34
+ let(:expected) do
35
+ <<-END
36
+ http://www.example.com/search: code 500, time: 4.882903
37
+ http://www.example.com/other: code 200, time: 6.882903
38
+ http://www.example.com/about: code 503, time: 2.882
39
+ END
40
+ end
41
+
42
+ before do
43
+ expect(Lita::Handlers::Connection).to receive(:new).and_return(response)
44
+ end
45
+
46
+ it 'responds with the correct status' do
47
+ send_message('status')
48
+ expect(replies.last).to eq(expected.split("\n").map(&:strip).join("\n"))
49
+ end
50
+
51
+ it 'checks for errors' do
52
+ send_message('any errors?')
53
+ expect(replies).to include("http://www.example.com/search is down: {:code=>500, :time=>4.882903}")
54
+ expect(replies).to include("http://www.example.com/about is down: {:code=>503, :time=>2.882}")
55
+ end
56
+ end
57
+
58
+ context 'custom url' do
59
+ let(:current_status) { {'http://test.com' => { code: 200, time: 4.882903 }} }
60
+
61
+ it 'responds with the correct status' do
62
+ expect(Lita::Handlers::Connection).to receive(:new).with(["http://test.com"]).and_return(response)
63
+ send_message("status <http://test.com|test.com>")
64
+ expect(replies.last).to eq("http://test.com: code 200, time: 4.882903")
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,7 @@
1
+ require 'pry'
2
+
3
+ require 'rspec'
4
+ require "lita/rspec"
5
+ require_relative '../lib/lita-ping-me.rb'
6
+
7
+ Lita.version_3_compatibility_mode = false
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lita-ping-me
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Douglas Roper
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-06-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: lita
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: typhoeus
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.7'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.7'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.7'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.3'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.3'
83
+ description: "\n periodically checks status of website and alerts chat room if
84
+ response error\n "
85
+ email:
86
+ - dougdroper@gmail.com
87
+ executables: []
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".gitignore"
92
+ - Gemfile
93
+ - README.md
94
+ - lib/lita-ping-me.rb
95
+ - lib/lita/handlers/connection.rb
96
+ - lib/lita/handlers/ping-me.rb
97
+ - lita-ping-me.gemspec
98
+ - spec/lib/handlers/ping-me_spec.rb
99
+ - spec/spec_helper.rb
100
+ homepage: http://github.com/dougdroper/lita-ping-me
101
+ licenses:
102
+ - MIT
103
+ metadata: {}
104
+ post_install_message:
105
+ rdoc_options: []
106
+ require_paths:
107
+ - lib
108
+ required_ruby_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ required_rubygems_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ requirements: []
119
+ rubyforge_project:
120
+ rubygems_version: 2.4.6
121
+ signing_key:
122
+ specification_version: 4
123
+ summary: Lita plugin for periodically checking statuses of websites
124
+ test_files:
125
+ - spec/lib/handlers/ping-me_spec.rb
126
+ - spec/spec_helper.rb