bobble 0.0.4 → 0.0.5

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.
@@ -0,0 +1,112 @@
1
+ require 'bobble/notifier/twilio'
2
+ require 'bobble/notifier/google_voice'
3
+ require 'bobble/notifier/gmail'
4
+
5
+ module Bobble
6
+ class Checker
7
+ class << self
8
+
9
+ def check(url, options={})
10
+ {
11
+ # The status that is considered a success.
12
+ # If nil, any status other than 50x is success.
13
+ :success_status => nil,
14
+ # Specified headers are required for the response
15
+ # to be considered a success.
16
+ # Regex values can be specified.
17
+ :success_header => nil,
18
+ # Response body must match the specified body.
19
+ # Can be a regex.
20
+ :success_body => nil
21
+ }.update(options)
22
+
23
+ begin
24
+ response = http_request(url)
25
+ assert_success(response, options)
26
+ puts "Successful!: #{url}"
27
+ rescue Exception => e
28
+ message = "FAILED: #{url} - #{e.message}"
29
+ puts message
30
+
31
+ self.send_notification(message, url)
32
+ end
33
+ end
34
+
35
+ def http_request(url)
36
+ uri = URI.parse(url)
37
+ http = Net::HTTP.new(uri.host, uri.port)
38
+ request = Net::HTTP::Get.new(uri.request_uri)
39
+ return http.request(request)
40
+ end
41
+
42
+ # raises an exception if not successful
43
+ def assert_success(response, options)
44
+ if response.code.to_i >= 500
45
+ raise Exception.new("Response status code error: #{response.code}")
46
+ end
47
+
48
+ if options[:success_status]
49
+ unless response.code.to_i == options[:success_status].to_i
50
+ raise Exception.new("Response status code error. Is: #{response.code} Expected: #{options[:success_status]}")
51
+ end
52
+ end
53
+
54
+ if options[:success_header]
55
+ options[:success_header].each do |k,v|
56
+ header_value = response.header[k.to_s]
57
+ if v.is_a?(Regexp)
58
+ unless header_value =~ v
59
+ raise Exception.new("Response header '#{k}' should match regexp #{v} ('#{header_value}' does not match)")
60
+ end
61
+ else
62
+ unless header_value == v
63
+ raise Exception.new("Response header '#{k}' should have value '#{v}' (instead is #{header_value})")
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ if options[:success_body]
70
+ match = options[:success_body]
71
+ if match.is_a?(Regexp)
72
+ unless response.body =~ match
73
+ raise Exception.new("Response body should match regexp #{match}, but does not.")
74
+ end
75
+ else
76
+ unless response.body.strip == match.strip
77
+ raise Exception.new("Response body should be '#{match}', instead is '#{response.body}'")
78
+ end
79
+ end
80
+ end
81
+
82
+ end
83
+
84
+ def send_notification(message, url)
85
+ if Bobble.option(:gmail)
86
+ begin
87
+ Notifier::Gmail.send(message, url)
88
+ rescue Exception => e
89
+ puts "Gmail Notifier failed: #{e.message}"
90
+ end
91
+ end
92
+
93
+ if Bobble.option(:twilio)
94
+ begin
95
+ Notifier::Twilio.send(message)
96
+ rescue Exception => e
97
+ puts "Twilio Notifier failed: #{e.message}"
98
+ end
99
+ end
100
+
101
+ if Bobble.option(:google_voice)
102
+ begin
103
+ Notifier::GoogleVoice.send(message)
104
+ rescue Exception => e
105
+ puts "Google Voice Notifier failed: #{e.message}"
106
+ end
107
+ end
108
+ end
109
+
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,29 @@
1
+ require 'pony'
2
+
3
+ module Bobble
4
+ module Notifier
5
+ class Gmail
6
+ class << self
7
+
8
+ def send(message, url)
9
+ Pony.mail({
10
+ :to => ENV["BOBBLE_GMAIL_TO_EMAIL"],
11
+ :via => :smtp,
12
+ :via_options => {
13
+ :address => 'smtp.gmail.com',
14
+ :port => '587',
15
+ :enable_starttls_auto => true,
16
+ :user_name => ENV["BOBBLE_GMAIL_USERNAME"],
17
+ :password => ENV["BOBBLE_GMAIL_PASSWORD"],
18
+ :authentication => :plain, # :plain, :login, :cram_md5, no auth by default
19
+ :domain => "localhost.localdomain" # the HELO domain provided by the client to the server
20
+ },
21
+ :body => message,
22
+ :subject => "Bobble: #{url} is down"
23
+ })
24
+ end
25
+
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,85 @@
1
+ require 'bobble/util'
2
+
3
+ #
4
+ # Google Voice Notifier
5
+ # Adapted from: http://brettterpstra.com/sms-from-the-command-line-with-google-voice/
6
+ #
7
+ module Bobble
8
+ module Notifier
9
+ class GoogleVoice
10
+ class << self
11
+
12
+ def postit(uri_str, data, header = nil, limit = 3)
13
+ raise ArgumentError, 'HTTP redirect too deep' if limit == 0
14
+ url = URI.parse(uri_str)
15
+ http = Net::HTTP.new(url.host,443)
16
+ http.use_ssl = true
17
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
18
+ response,content = http.post(url.path,data,header)
19
+ case response
20
+ when Net::HTTPSuccess then content
21
+ when Net::HTTPRedirection then postit(response['location'],data,header, limit - 1)
22
+ else
23
+ puts response.inspect
24
+ response.error!
25
+ end
26
+ end
27
+
28
+ def getit(uri_str, header, limit = 3)
29
+ raise ArgumentError, 'HTTP redirect too deep' if limit == 0
30
+ url = URI.parse(uri_str)
31
+ http = Net::HTTP.new(url.host,url.port)
32
+ http.use_ssl = true
33
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
34
+ response,content = http.get(url.path,header)
35
+ case response
36
+ when Net::HTTPSuccess then content
37
+ when Net::HTTPRedirection then getit(response['location'],header, limit - 1)
38
+ else
39
+ response.error!
40
+ end
41
+ end
42
+
43
+ def send(message)
44
+ message = Bobble::Util.shorten_to_text_message(message)
45
+
46
+ username = ENV["BOBBLE_GVOICE_USERNAME"]
47
+ password = ENV["BOBBLE_GVOICE_PASSWORD"]
48
+ # TODO: support multiple numbers
49
+ number = ENV["BOBBLE_GVOICE_TO_PHONENUMBER"]
50
+ numbers = [number]
51
+
52
+ data = "accountType=GOOGLE&Email=#{username}&Passwd=#{password}&service=grandcentral&source=brettterpstra-CLISMS-2.0"
53
+ res = postit('https://www.google.com/accounts/ClientLogin',data)
54
+
55
+ if res
56
+ authcode = res.match(/Auth=(.+)/)[1]
57
+ header = {'Authorization' => "GoogleLogin auth=#{authcode.strip}",'Content-Length' => '0'}
58
+ newres = getit('https://www.google.com/voice',header)
59
+
60
+ if newres
61
+ rnrse = newres.match(/'_rnr_se': '([^']+)'/)[1]
62
+ numbers.each do |num|
63
+ data = "_rnr_se=#{rnrse}&phoneNumber=#{num.strip}&text=#{message}&id="
64
+ finalres = postit('https://www.google.com/voice/sms/send/',data,header)
65
+
66
+ if finalres["ok"]
67
+ puts "Message sent to #{num}"
68
+ else
69
+ puts "Error sending to #{num}"
70
+ end
71
+ end
72
+
73
+ else
74
+ newres.error!
75
+ end
76
+
77
+ else
78
+ res.error!
79
+ end
80
+ end
81
+
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,35 @@
1
+ require 'twilio-ruby'
2
+ require 'bobble/util'
3
+
4
+ module Bobble
5
+ module Notifier
6
+ class Twilio
7
+ class << self
8
+
9
+ @@client = nil
10
+
11
+ def create_client
12
+ return if @@client
13
+
14
+ account_sid = ENV['BOBBLE_TWILIO_SID']
15
+ auth_token = ENV['BOBBLE_TWILIO_TOKEN']
16
+
17
+ @@client = Twilio::REST::Client.new account_sid, auth_token
18
+ end
19
+
20
+ def send(message)
21
+ create_client
22
+ message = Bobble::Util.shorten_to_text_message(message)
23
+
24
+ params = {
25
+ :from => ENV['BOBBLE_TWILIO_FROM_PHONENUMBER'],
26
+ :to => ENV['BOBBLE_TWILIO_TO_PHONENUMBER'],
27
+ :body => message
28
+ }
29
+ @@client.account.sms.messages.create(params)
30
+ end
31
+
32
+ end
33
+ end
34
+ end
35
+ end
data/lib/bobble/util.rb CHANGED
@@ -1,13 +1,15 @@
1
- class Bobble::Util
2
- class << self
1
+ module Bobble
2
+ class Util
3
+ class << self
3
4
 
4
- def shorten_to_text_message(message)
5
- text_message = message
6
- if message.length > 140
7
- text_message = message[0..136] + "..."
5
+ def shorten_to_text_message(message)
6
+ text_message = message
7
+ if message.length > 140
8
+ text_message = message[0..136] + "..."
9
+ end
10
+ return message
8
11
  end
9
- return message
10
- end
11
12
 
13
+ end
12
14
  end
13
15
  end
data/lib/bobble.rb CHANGED
@@ -1,4 +1,6 @@
1
- class Bobble
1
+ require 'bobble/checker'
2
+
3
+ module Bobble
2
4
  class << self
3
5
 
4
6
  # default options are guessed based on what environment variables are present
@@ -8,56 +10,15 @@ class Bobble
8
10
  :gmail => !!ENV["BOBBLE_GMAIL_USERNAME"]
9
11
  }
10
12
 
11
- def options(o)
12
- @@options.update(o)
13
+ def option(key)
14
+ @@options[key]
13
15
  end
14
16
 
15
- def check(url)
16
- begin
17
- response = Net::HTTP.get(URI.parse(url))
18
- raise Exception.new("empty response") if response == ""
19
- puts "Successful!: #{url}"
20
- rescue Exception => e
21
- message = "FAILED: #{url} - #{e.message}"
22
- puts message
23
-
24
- send_notification(message, url)
25
- end
26
- end
27
-
28
- def send_notification(message, url)
29
-
30
- if @@options[:gmail]
31
- begin
32
- GmailNotifier.send(message, url)
33
- rescue Exception => e
34
- puts "Gmail Notifier failed: #{e.message}"
35
- end
36
- end
37
-
38
- if @@options[:twilio]
39
- begin
40
- TwilioNotifier.send(message)
41
- rescue Exception => e
42
- puts "Twilio Notifier failed: #{e.message}"
43
- end
44
- end
45
-
46
- if @@options[:google_voice]
47
- begin
48
- GoogleVoiceNotifier.send(message)
49
- rescue Exception => e
50
- puts "Google Voice Notifier failed: #{e.message}"
51
- end
52
- end
53
-
17
+ def check(url, options={})
18
+ Bobble::Checker.check(url, options)
54
19
  end
55
20
 
56
21
  end
57
22
  end
58
23
 
59
- require 'bobble/twilio_notifier'
60
- require 'bobble/google_voice_notifier'
61
- require 'bobble/gmail_notifier'
62
-
63
24
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bobble
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-24 00:00:00.000000000Z
12
+ date: 2012-07-06 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: twilio-ruby
16
- requirement: &70329909850180 !ruby/object:Gem::Requirement
16
+ requirement: &70256347466300 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 3.6.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70329909850180
24
+ version_requirements: *70256347466300
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: pony
27
- requirement: &70329909849480 !ruby/object:Gem::Requirement
27
+ requirement: &70256347465820 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,19 +32,20 @@ dependencies:
32
32
  version: '1.4'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70329909849480
36
- description: For freely pinging your favorite web services & freely or cheaply getting
37
- email/SMS notifications when they're down.
35
+ version_requirements: *70256347465820
36
+ description: For pinging your web services (any URL) & freely or cheaply getting email/SMS
37
+ notifications when they're down.
38
38
  email: ahfarmer@gmail.com
39
39
  executables: []
40
40
  extensions: []
41
41
  extra_rdoc_files: []
42
42
  files:
43
43
  - lib/bobble.rb
44
- - lib/bobble/gmail_notifier.rb
45
- - lib/bobble/google_voice_notifier.rb
46
- - lib/bobble/twilio_notifier.rb
44
+ - lib/bobble/checker.rb
47
45
  - lib/bobble/util.rb
46
+ - lib/bobble/notifier/gmail.rb
47
+ - lib/bobble/notifier/google_voice.rb
48
+ - lib/bobble/notifier/twilio.rb
48
49
  homepage: https://github.com/ahfarmer/bobble
49
50
  licenses: []
50
51
  post_install_message:
@@ -1,25 +0,0 @@
1
- require 'pony'
2
-
3
- class Bobble::GmailNotifier
4
- class << self
5
-
6
- def send(message, url)
7
- Pony.mail({
8
- :to => ENV["BOBBLE_GMAIL_TO_EMAIL"],
9
- :via => :smtp,
10
- :via_options => {
11
- :address => 'smtp.gmail.com',
12
- :port => '587',
13
- :enable_starttls_auto => true,
14
- :user_name => ENV["BOBBLE_GMAIL_USERNAME"],
15
- :password => ENV["BOBBLE_GMAIL_PASSWORD"],
16
- :authentication => :plain, # :plain, :login, :cram_md5, no auth by default
17
- :domain => "localhost.localdomain" # the HELO domain provided by the client to the server
18
- },
19
- :body => message,
20
- :subject => "Bobble: #{url} is down"
21
- })
22
- end
23
-
24
- end
25
- end
@@ -1,81 +0,0 @@
1
- require 'bobble/util'
2
-
3
- #
4
- # Google Voice Notifier
5
- # Adapted from: http://brettterpstra.com/sms-from-the-command-line-with-google-voice/
6
- #
7
- class Bobble::GoogleVoiceNotifier
8
- class << self
9
-
10
- def postit(uri_str, data, header = nil, limit = 3)
11
- raise ArgumentError, 'HTTP redirect too deep' if limit == 0
12
- url = URI.parse(uri_str)
13
- http = Net::HTTP.new(url.host,443)
14
- http.use_ssl = true
15
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
16
- response,content = http.post(url.path,data,header)
17
- case response
18
- when Net::HTTPSuccess then content
19
- when Net::HTTPRedirection then postit(response['location'],data,header, limit - 1)
20
- else
21
- puts response.inspect
22
- response.error!
23
- end
24
- end
25
-
26
- def getit(uri_str, header, limit = 3)
27
- raise ArgumentError, 'HTTP redirect too deep' if limit == 0
28
- url = URI.parse(uri_str)
29
- http = Net::HTTP.new(url.host,url.port)
30
- http.use_ssl = true
31
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
32
- response,content = http.get(url.path,header)
33
- case response
34
- when Net::HTTPSuccess then content
35
- when Net::HTTPRedirection then getit(response['location'],header, limit - 1)
36
- else
37
- response.error!
38
- end
39
- end
40
-
41
- def send(message)
42
- message = Bobble::Util.shorten_to_text_message(message)
43
-
44
- username = ENV["BOBBLE_GVOICE_USERNAME"]
45
- password = ENV["BOBBLE_GVOICE_PASSWORD"]
46
- # TODO: support multiple numbers
47
- number = ENV["BOBBLE_GVOICE_TO_PHONENUMBER"]
48
- numbers = [number]
49
-
50
- data = "accountType=GOOGLE&Email=#{username}&Passwd=#{password}&service=grandcentral&source=brettterpstra-CLISMS-2.0"
51
- res = postit('https://www.google.com/accounts/ClientLogin',data)
52
-
53
- if res
54
- authcode = res.match(/Auth=(.+)/)[1]
55
- header = {'Authorization' => "GoogleLogin auth=#{authcode.strip}",'Content-Length' => '0'}
56
- newres = getit('https://www.google.com/voice',header)
57
-
58
- if newres
59
- rnrse = newres.match(/'_rnr_se': '([^']+)'/)[1]
60
- numbers.each do |num|
61
- data = "_rnr_se=#{rnrse}&phoneNumber=#{num.strip}&text=#{message}&id="
62
- finalres = postit('https://www.google.com/voice/sms/send/',data,header)
63
-
64
- if finalres["ok"]
65
- puts "Message sent to #{num}"
66
- else
67
- puts "Error sending to #{num}"
68
- end
69
- end
70
-
71
- else
72
- newres.error!
73
- end
74
-
75
- else
76
- res.error!
77
- end
78
- end
79
-
80
- end
81
- end
@@ -1,31 +0,0 @@
1
- require 'twilio-ruby'
2
- require 'bobble/util'
3
-
4
- class Bobble::TwilioNotifier
5
- class << self
6
-
7
- @@client = nil
8
-
9
- def create_client
10
- return if @@client
11
-
12
- account_sid = ENV['BOBBLE_TWILIO_SID']
13
- auth_token = ENV['BOBBLE_TWILIO_TOKEN']
14
-
15
- @@client = Twilio::REST::Client.new account_sid, auth_token
16
- end
17
-
18
- def send(message)
19
- create_client
20
- message = Bobble::Util.shorten_to_text_message(message)
21
-
22
- params = {
23
- :from => ENV['BOBBLE_TWILIO_FROM_PHONENUMBER'],
24
- :to => ENV['BOBBLE_TWILIO_TO_PHONENUMBER'],
25
- :body => message
26
- }
27
- @@client.account.sms.messages.create(params)
28
- end
29
-
30
- end
31
- end