fastprowl 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2010 Matthew Riley MacPherson
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,59 @@
1
+ # FastProwl
2
+ ## Ruby Prowl library that uses libcurl-multi for parallel requests
3
+
4
+ *FastProwl* is a Ruby library for interacting with the Prowl API **using Typhoeus** (a libcurl-multi interface written in Ruby). It is inspired heavily by [August Lilleaas](http://august.lilleaas.net/)'s [ruby-prowl](http://github.com/augustl/ruby-prowl) library (the class method `FastProwl.add()` still works if you include this library instead).
5
+
6
+ *FastProwl* lets you queue up many Prowl API requests then make them concurrently, which is handy if you make a bunch of requests in quick succession. It was developed for [Prey Fetcher](http://preyfetcher.com), which sends too many notifications requests to wait on blocking HTTP calls.
7
+
8
+ Please fork away and send me a pull request if you think you can make it better or whatnot.
9
+
10
+ ## Installation
11
+
12
+ Assuming you have [Gemcutter](http://gemcutter.org/) setup as a gem source, install like any other Ruby gem:
13
+
14
+ gem install fastprowl
15
+
16
+ If you don't already have [Gemcutter](http://gemcutter.org/) setup as one of your gem sources, install FastProwl with the following command:
17
+
18
+ gem install fastprowl --source http://gemcutter.org/
19
+
20
+ ## Usage
21
+
22
+ Pretty simple -- you can send single notifications without bothering with queuing and all that by using the class method `FastProwl.add()`:
23
+
24
+ FastProwl.add(
25
+ :apikey => 'valid_api_key',
26
+ :application => 'Car Repair Shop',
27
+ :event => 'Your car is now ready!',
28
+ :description => 'We had to replace a part. Bring your credit card.'
29
+ )
30
+
31
+ As mentioned, this is the same as using [ruby-prowl](http://github.com/augustl/ruby-prowl). It will return `true` on success; `false` otherwise.
32
+
33
+ If you want to send concurrent requests (presumably you do), create an instance object and use the `add()` method to queue up your requests. When all of your requests are ready, use the `run()` method to send all of your queued notifications:
34
+
35
+ # You can put any attributes you want in the constructor
36
+ # to save repeatly supplying them when you call add()
37
+ prowl = FastProwl.new(
38
+ :application => 'Car Repair Shop',
39
+ :event => 'Your car has been ready for ages!',
40
+ :description => 'Hurry up! Bring your credit card!'
41
+ )
42
+
43
+ users.each do |user|
44
+ prowl.add(
45
+ :apikey => user.prowl_apikey,
46
+ )
47
+ end
48
+
49
+ prowl.run
50
+
51
+ You get the idea.
52
+
53
+ ## License
54
+
55
+ This program is free software; it is distributed under an [MIT-style License](http://fosspass.org/license/mit?author=Matthew+Riley+MacPherson&year=2010).
56
+
57
+ ---
58
+
59
+ Copyright (c) 2010 [Matthew Riley MacPherson](http://lonelyvegan.com).
data/fastprowl.gemspec ADDED
@@ -0,0 +1,17 @@
1
+ require 'rake'
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "fastprowl"
5
+ s.version = "0.1"
6
+ s.date = Time.now
7
+ s.authors = ["Matthew Riley MacPherson"]
8
+ s.email = "matt@lonelyvegan.com"
9
+ s.has_rdoc = true
10
+ s.rdoc_options << '--title' << "FastProwl - Ruby Prowl library that uses libcurl-multi for parallel requests" << '--main' << 'README.markdown' << '--line-numbers'
11
+ s.summary = "Ruby Prowl library that uses libcurl-multi for parallel requests"
12
+ s.homepage = "http://github.com/tofumatt/FastProwl"
13
+ s.files = FileList['lib/*.rb', '[A-Z]*', 'fastprowl.gemspec', 'test/*.rb'].to_a
14
+ s.test_file = 'test/fastprowl_test.rb'
15
+ s.add_dependency('typhoeus')
16
+ s.add_development_dependency('mocha') # Used to run the tests, that's all...
17
+ end
data/lib/fastprowl.rb ADDED
@@ -0,0 +1,101 @@
1
+ require 'rubygems'
2
+ require 'typhoeus'
3
+
4
+ class FastProwl
5
+
6
+ class MissingAPIKey < Exception; end
7
+ class PriorityOutOfRange < Exception; end
8
+ class TooManyAPIKeys < Exception; end
9
+
10
+ API_URL = 'https://prowl.weks.net/publicapi/'
11
+ PRIORITY_RANGE = -2..2
12
+ # You can change this using the user_agent() method
13
+ USER_AGENT = 'FastProwl 0.1 (http://github.com/tofumatt/FastProwl)'
14
+
15
+ # Supply Prowl defaults in a hash (:apikey, :providerkey, etc.), along
16
+ # with optional Typhoeus Hydra options.
17
+ def initialize(defaults = {}, hydra = {})
18
+ @defaults = defaults
19
+ @responses = []
20
+ @hydra = Typhoeus::Hydra.new(hydra)
21
+ @user_agent = USER_AGENT
22
+ end
23
+
24
+ # Queue a notification request in the Hydra.
25
+ def add(params = {})
26
+ @hydra.queue(request('add', params))
27
+ end
28
+
29
+ # Modify this instance's defaults
30
+ def defaults(params)
31
+ @defaults = @defaults.merge(params)
32
+ end
33
+
34
+ # Run all queued Hydra requests.
35
+ def run
36
+ @hydra.run
37
+ status
38
+ end
39
+
40
+ # Change the user-agent sent to the Prowl server.
41
+ def user_agent(user_agent)
42
+ @user_agent = user_agent
43
+ end
44
+
45
+ # Send a single Prowl notification _immediately_ (don't queue it in
46
+ # the Hydra). Returns the response code of the action
47
+ def self.add(params = {})
48
+ prowl = new
49
+ prowl.add(params)
50
+ prowl.run
51
+ end
52
+
53
+ private
54
+
55
+ # Setup and return a Typhoeus HTTP request
56
+ def request(action, params = {})
57
+ # Merge the default params with any custom ones
58
+ params = @defaults.merge(params) unless !@defaults
59
+
60
+ # Exception checks
61
+ if !params[:apikey] || (params[:apikey].is_a?(Array) && params[:apikey].size < 1)
62
+ raise MissingAPIKey
63
+ end
64
+
65
+ if params[:priority] && !PRIORITY_RANGE.include?(params[:priority])
66
+ raise PriorityOutOfRange
67
+ end
68
+
69
+ # Raise an exception if we're trying to use more API keys than allowed for this action
70
+ if params[:apikey].is_a?(Array) && ((action == 'verify' && params[:apikey].size > 1) || params[:apikey].size > MAX_API_KEYS)
71
+ raise TooManyAPIKeys
72
+ end
73
+
74
+ # If there are multiple API Keys in an array, merge them into a comma-delimited string
75
+ if params[:apikey].is_a?(Array)
76
+ params[:apikey] = params[:apikey].collect{|v| v + ','}.to_s.chop
77
+ end
78
+
79
+ # Return the request (to either a Hydra or a quick Typhoeus action)
80
+ req = Typhoeus::Request.new(API_URL + action,
81
+ :user_agent => @user_agent,
82
+ :method => (action == 'add') ? :post : :get,
83
+ :params => (action == 'add') ? params : {:apikey => params[:apikey]}
84
+ )
85
+
86
+ req.on_complete do |response|
87
+ @responses << response.code
88
+ end
89
+
90
+ req
91
+ end
92
+
93
+ # Check to see if any notifications succeeded. Like the Prowl API with multiple
94
+ # API keys, we'll only return false if *zero* requests succeeded.
95
+ def status
96
+ return false if !@responses.include?(200)
97
+
98
+ true
99
+ end
100
+
101
+ end
@@ -0,0 +1,72 @@
1
+ require 'test/unit'
2
+
3
+ $LOAD_PATH << File.expand_path("#{File.dirname(__FILE__)}/../lib")
4
+ require 'fastprowl'
5
+
6
+ require 'rubygems'
7
+ require 'mocha'
8
+
9
+ class FastProwlTest < Test::Unit::TestCase
10
+
11
+ APPLICATION = 'FastProwl Unit Tests (http://github.com/tofumatt/FastProwl)'
12
+ BAD_API_KEY = 'badapikeyftw'
13
+ # This is a <b>valid API key</b> for an account with no devices. I'm not sure how
14
+ # you'd go about abusing it, but please don't.
15
+ VALID_API_KEY = 'c7634829dfafb02cc966df2f3dfc2c75fe2c9ef1'
16
+
17
+ # Priority range is -2..2
18
+ def test_invalid_priority
19
+ assert_raises(FastProwl::PriorityOutOfRange) { FastProwl.add(:apikey => VALID_API_KEY, :priority => 10) }
20
+ end
21
+
22
+ # API key(s) are _required_
23
+ def test_no_api_key
24
+ assert_raises(FastProwl::MissingAPIKey) { FastProwl.add(:apikey => nil) }
25
+ end
26
+
27
+ # This key will fail
28
+ def test_invalid_api_key
29
+ assert !FastProwl.add(:apikey => BAD_API_KEY, :application => APPLICATION, :event => 'test_invalid_api_key', :description => "This shouldn't work.")
30
+ end
31
+
32
+ # Sending works
33
+ def test_valid_api_key
34
+ assert FastProwl.add(:apikey => VALID_API_KEY, :application => APPLICATION, :event => 'test_valid_api_key', :description => "This should work.")
35
+ end
36
+
37
+ # Concurrency test -- try to send a bunch of notifications
38
+ def test_multi
39
+ prowl = FastProwl.new
40
+
41
+ 10.times do
42
+ prowl.add(:apikey => VALID_API_KEY, :application => APPLICATION, :event => 'test_multi', :description => "This is a concurrency test -- it should work.")
43
+ end
44
+
45
+ assert prowl.run
46
+ end
47
+
48
+ # Concurrency test -- try to send a bunch of notifications, including one with a bad API key
49
+ def test_multi_onefails
50
+ prowl = FastProwl.new
51
+
52
+ prowl.add(:apikey => BAD_API_KEY, :application => APPLICATION, :event => 'test_multi_onefails', :description => "This is a concurrency test -- it should work, but one key is bad.")
53
+
54
+ 9.times do
55
+ prowl.add(:apikey => VALID_API_KEY, :application => APPLICATION, :event => 'test_multi_onefails', :description => "This is a concurrency test -- it should work, but one key is bad.")
56
+ end
57
+
58
+ assert prowl.run
59
+ end
60
+
61
+ # Concurrency test -- try to send a bunch of notifications, all with a bad API keys
62
+ def test_multi_allfail
63
+ prowl = FastProwl.new
64
+
65
+ 10.times do
66
+ prowl.add(:apikey => BAD_API_KEY, :application => APPLICATION, :event => 'test_multi_allfail', :description => "This is a concurrency test -- it shouldn't work.")
67
+ end
68
+
69
+ assert !prowl.run
70
+ end
71
+
72
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fastprowl
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.1"
5
+ platform: ruby
6
+ authors:
7
+ - Matthew Riley MacPherson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-02-15 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: typhoeus
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: mocha
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ description:
36
+ email: matt@lonelyvegan.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files: []
42
+
43
+ files:
44
+ - lib/fastprowl.rb
45
+ - LICENSE
46
+ - README.markdown
47
+ - fastprowl.gemspec
48
+ - test/fastprowl_test.rb
49
+ has_rdoc: true
50
+ homepage: http://github.com/tofumatt/FastProwl
51
+ licenses: []
52
+
53
+ post_install_message:
54
+ rdoc_options:
55
+ - --title
56
+ - FastProwl - Ruby Prowl library that uses libcurl-multi for parallel requests
57
+ - --main
58
+ - README.markdown
59
+ - --line-numbers
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ version:
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: "0"
73
+ version:
74
+ requirements: []
75
+
76
+ rubyforge_project:
77
+ rubygems_version: 1.3.5
78
+ signing_key:
79
+ specification_version: 3
80
+ summary: Ruby Prowl library that uses libcurl-multi for parallel requests
81
+ test_files:
82
+ - test/fastprowl_test.rb