lita-ping-me 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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