congress 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +1 -0
- data/.gemtest +0 -0
- data/.gitignore +41 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/.yardopts +3 -0
- data/Gemfile +7 -0
- data/LICENSE.md +10 -0
- data/README.md +99 -0
- data/Rakefile +18 -0
- data/congress.gemspec +31 -0
- data/lib/congress.rb +27 -0
- data/lib/congress/client.rb +86 -0
- data/lib/congress/connection.rb +17 -0
- data/lib/congress/request.rb +16 -0
- data/lib/congress/version.rb +3 -0
- data/spec/congress/client_spec.rb +116 -0
- data/spec/congress_spec.rb +18 -0
- data/spec/fixtures/amendments.json +1 -0
- data/spec/fixtures/bills.json +1 -0
- data/spec/fixtures/committee_hearings.json +1 -0
- data/spec/fixtures/documents.json +1 -0
- data/spec/fixtures/floor_updates.json +1 -0
- data/spec/fixtures/videos.json +1 -0
- data/spec/fixtures/votes.json +1 -0
- data/spec/helper.rb +23 -0
- metadata +221 -0
data/.autotest
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'autotest/bundler'
|
data/.gemtest
ADDED
File without changes
|
data/.gitignore
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
!.gitignore
|
2
|
+
*.gem
|
3
|
+
*.rbc
|
4
|
+
*.sw[a-p]
|
5
|
+
*.tmproj
|
6
|
+
*.tmproject
|
7
|
+
*.un~
|
8
|
+
*~
|
9
|
+
.DS_Store
|
10
|
+
.Spotlight-V100
|
11
|
+
.Trashes
|
12
|
+
._*
|
13
|
+
.bundle
|
14
|
+
.config
|
15
|
+
.directory
|
16
|
+
.elc
|
17
|
+
.redcar
|
18
|
+
.yardoc
|
19
|
+
/.emacs.desktop
|
20
|
+
/.emacs.desktop.lock
|
21
|
+
Desktop.ini
|
22
|
+
Gemfile.lock
|
23
|
+
Icon?
|
24
|
+
InstalledFiles
|
25
|
+
Session.vim
|
26
|
+
Thumbs.db
|
27
|
+
\#*\#
|
28
|
+
_yardoc
|
29
|
+
auto-save-list
|
30
|
+
coverage
|
31
|
+
doc/
|
32
|
+
lib/bundler/man
|
33
|
+
pkg
|
34
|
+
pkg/*
|
35
|
+
rdoc
|
36
|
+
spec/reports
|
37
|
+
test/tmp
|
38
|
+
test/version_tmp
|
39
|
+
tmp
|
40
|
+
tmtags
|
41
|
+
tramp
|
data/.rspec
ADDED
data/.travis.yml
ADDED
data/.yardopts
ADDED
data/Gemfile
ADDED
data/LICENSE.md
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
Copyright (c) 2011, Code for America
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
5
|
+
|
6
|
+
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
7
|
+
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
8
|
+
* Neither the name of Code for America nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
9
|
+
|
10
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
# Ruby wrapper for the Real-Time Congress API
|
2
|
+
|
3
|
+
The Real-Time Congress (RTC) API is a RESTful API over the artifacts of
|
4
|
+
Congress, in as close to real-time as possible.
|
5
|
+
|
6
|
+
Installation
|
7
|
+
------------
|
8
|
+
gem install congress
|
9
|
+
|
10
|
+
Documentation
|
11
|
+
-------------
|
12
|
+
[http://rdoc.info/gems/congress](http://rdoc.info/gems/congress)
|
13
|
+
|
14
|
+
Continuous Integration
|
15
|
+
----------------------
|
16
|
+
[![Build Status](http://travis-ci.org/codeforamerica/congress.png)](http://travis-ci.org/codeforamerica/congress)
|
17
|
+
|
18
|
+
Usage Examples
|
19
|
+
--------------
|
20
|
+
require 'rubygems'
|
21
|
+
require 'congress'
|
22
|
+
|
23
|
+
# An API key is required
|
24
|
+
# You can obtain one from http://services.sunlightlabs.com/accounts/register/
|
25
|
+
Congress.key = YOUR_RTC_API_KEY
|
26
|
+
|
27
|
+
# Fetch bills introduced bills and resolutions in Congress
|
28
|
+
puts Congress.bills
|
29
|
+
|
30
|
+
# Fetch votes taken in Congress
|
31
|
+
puts Congress.votes
|
32
|
+
|
33
|
+
# Fetch amendments to bills and resolutions offered in Congress
|
34
|
+
puts Congress.amendments
|
35
|
+
|
36
|
+
# Fetch videos from the U.S. House of Representatives and from the White House
|
37
|
+
puts Congress.videos
|
38
|
+
|
39
|
+
# Fetch updates from the floor of each chamber of Congress
|
40
|
+
puts Congress.floor_updates
|
41
|
+
|
42
|
+
# Fetch upcoming scheduled committee hearings in the House and Senate
|
43
|
+
puts Congress.committee_hearings
|
44
|
+
|
45
|
+
# Fetch links to various kinds of documents produced by agencies within Congress
|
46
|
+
puts Congress.documents
|
47
|
+
|
48
|
+
Contributing
|
49
|
+
------------
|
50
|
+
In the spirit of [free
|
51
|
+
software](http://www.fsf.org/licensing/essays/free-sw.html), **everyone** is
|
52
|
+
encouraged to help improve this project.
|
53
|
+
|
54
|
+
Here are some ways *you* can contribute:
|
55
|
+
|
56
|
+
* by using alpha, beta, and prerelease versions
|
57
|
+
* by reporting bugs
|
58
|
+
* by suggesting new features
|
59
|
+
* by writing or editing documentation
|
60
|
+
* by writing specifications
|
61
|
+
* by writing code (**no patch is too small**: fix typos, add comments, clean up
|
62
|
+
inconsistent whitespace)
|
63
|
+
* by refactoring code
|
64
|
+
* by closing [issues](https://github.com/codeforamerica/congress/issues)
|
65
|
+
* by reviewing patches
|
66
|
+
|
67
|
+
Submitting an Issue
|
68
|
+
-------------------
|
69
|
+
We use the [GitHub issue tracker](https://github.com/codeforamerica/congress/issues) to
|
70
|
+
track bugs and features. Before submitting a bug report or feature request,
|
71
|
+
check to make sure it hasn't already been submitted. You can indicate support
|
72
|
+
for an existing issuse by voting it up. When submitting a bug report, please
|
73
|
+
include a [Gist](https://gist.github.com/) that includes a stack trace and any
|
74
|
+
details that may be necessary to reproduce the bug, including your gem version,
|
75
|
+
Ruby version, and operating system. Ideally, a bug report should include a pull
|
76
|
+
request with failing specs.
|
77
|
+
|
78
|
+
Submitting a Pull Request
|
79
|
+
-------------------------
|
80
|
+
1. Fork the project.
|
81
|
+
2. Create a topic branch.
|
82
|
+
3. Implement your feature or bug fix.
|
83
|
+
4. Add documentation for your feature or bug fix.
|
84
|
+
5. Run <tt>bundle exec rake doc:yard</tt>. If your changes are not 100%
|
85
|
+
documented, go back to step 4.
|
86
|
+
6. Add specs for your feature or bug fix.
|
87
|
+
7. Run <tt>bundle exec rake spec</tt>. If your changes are not 100% covered, go
|
88
|
+
back to step 6.
|
89
|
+
8. Commit and push your changes.
|
90
|
+
9. Submit a pull request. Please do not include changes to the gemspec,
|
91
|
+
version, or history file. (If you want to create your own version for some
|
92
|
+
reason, please do so in a separate commit.)
|
93
|
+
|
94
|
+
Copyright
|
95
|
+
---------
|
96
|
+
Copyright (c) 2011, Code for America. All rights reserved.
|
97
|
+
See [LICENSE](https://github.com/codeforamerica/congress/blob/master/LICENSE.md) for details.
|
98
|
+
|
99
|
+
[![Code for America Tracker](http://stats.codeforamerica.org/codeforamerica/congress.png)](http://stats.codeforamerica.org/projects/congress)
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
|
3
|
+
require 'bundler'
|
4
|
+
Bundler::GemHelper.install_tasks
|
5
|
+
|
6
|
+
require 'rspec/core/rake_task'
|
7
|
+
RSpec::Core::RakeTask.new(:spec)
|
8
|
+
|
9
|
+
task :default => :spec
|
10
|
+
task :test => :spec
|
11
|
+
|
12
|
+
require 'yard'
|
13
|
+
namespace :doc do
|
14
|
+
YARD::Rake::YardocTask.new do |task|
|
15
|
+
task.files = ['LICENSE.md', 'lib/**/*.rb']
|
16
|
+
task.options = ['--markup', 'markdown']
|
17
|
+
end
|
18
|
+
end
|
data/congress.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/congress/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.name = 'congress'
|
6
|
+
gem.version = Congress::VERSION
|
7
|
+
gem.author = "Erik Michaels-Ober"
|
8
|
+
gem.email = 'sferik@gmail.com'
|
9
|
+
gem.homepage = 'https://github.com/sferik/congress'
|
10
|
+
gem.summary = %q{Ruby wrapper for the Real-Time Congress API}
|
11
|
+
gem.description = %q{Ruby wrapper for the Real-Time Congress API. The Real-Time Congress API is a RESTful API over the artifacts of Congress, in as close to real-time as possible.}
|
12
|
+
|
13
|
+
gem.files = `git ls-files`.split("\n")
|
14
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
15
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{|f| File.basename(f)}
|
16
|
+
gem.require_paths = ['lib']
|
17
|
+
|
18
|
+
gem.add_development_dependency 'ZenTest', '~> 4.5'
|
19
|
+
gem.add_development_dependency 'maruku', '~> 0.6'
|
20
|
+
gem.add_development_dependency 'rake', '~> 0.9'
|
21
|
+
gem.add_development_dependency 'rspec', '~> 2.6'
|
22
|
+
gem.add_development_dependency 'simplecov', '~> 0.4'
|
23
|
+
gem.add_development_dependency 'webmock', '~> 1.6'
|
24
|
+
gem.add_development_dependency 'yard', '~> 0.7'
|
25
|
+
|
26
|
+
gem.add_runtime_dependency 'faraday', '~> 0.6.1'
|
27
|
+
gem.add_runtime_dependency 'faraday_middleware', '~> 0.6.3'
|
28
|
+
gem.add_runtime_dependency 'hashie', '~> 1.0.0'
|
29
|
+
gem.add_runtime_dependency 'multi_json', '~> 1.0.3'
|
30
|
+
gem.add_runtime_dependency 'rash', '~> 0.3.0'
|
31
|
+
end
|
data/lib/congress.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'congress/client'
|
2
|
+
|
3
|
+
module Congress
|
4
|
+
class << self
|
5
|
+
attr_accessor :key
|
6
|
+
def configure
|
7
|
+
yield self
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# Alias for Congress::Client.new
|
12
|
+
#
|
13
|
+
# @return [Congress::Client]
|
14
|
+
def self.new
|
15
|
+
Congress::Client.new
|
16
|
+
end
|
17
|
+
|
18
|
+
# Delegate to Congress::Client
|
19
|
+
def self.method_missing(method, *args, &block)
|
20
|
+
return super unless new.respond_to?(method)
|
21
|
+
new.send(method, *args, &block)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.respond_to?(method, include_private=false)
|
25
|
+
new.respond_to?(method, include_private) || super(method, include_private)
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'congress/connection'
|
2
|
+
require 'congress/request'
|
3
|
+
|
4
|
+
module Congress
|
5
|
+
class Client
|
6
|
+
include Congress::Connection
|
7
|
+
include Congress::Request
|
8
|
+
|
9
|
+
# Fetch bills introduced bills and resolutions in Congress
|
10
|
+
#
|
11
|
+
# @return [Hashie::Rash]
|
12
|
+
# @example
|
13
|
+
# Congress.key = YOUR_RTC_API_KEY
|
14
|
+
# Congress.bills
|
15
|
+
def bills(options={})
|
16
|
+
get('/api/v1/bills.json', options.merge(api_key))
|
17
|
+
end
|
18
|
+
|
19
|
+
# Fetch votes taken in Congress
|
20
|
+
#
|
21
|
+
# @return [Hashie::Rash]
|
22
|
+
# @example
|
23
|
+
# Congress.key = YOUR_RTC_API_KEY
|
24
|
+
# Congress.votes
|
25
|
+
def votes(options={})
|
26
|
+
get('/api/v1/votes.json', options.merge(api_key))
|
27
|
+
end
|
28
|
+
|
29
|
+
# Fetch amendments to bills and resolutions offered in Congress
|
30
|
+
#
|
31
|
+
# @return [Hashie::Rash]
|
32
|
+
# @example
|
33
|
+
# Congress.key = YOUR_RTC_API_KEY
|
34
|
+
# Congress.amendments
|
35
|
+
def amendments(options={})
|
36
|
+
get('/api/v1/amendments.json', options.merge(api_key))
|
37
|
+
end
|
38
|
+
|
39
|
+
# Fetch videos from the U.S. House of Representatives and from the White House
|
40
|
+
#
|
41
|
+
# @return [Hashie::Rash]
|
42
|
+
# @example
|
43
|
+
# Congress.key = YOUR_RTC_API_KEY
|
44
|
+
# Congress.videos
|
45
|
+
def videos(options={})
|
46
|
+
get('/api/v1/videos.json', options.merge(api_key))
|
47
|
+
end
|
48
|
+
|
49
|
+
# Fetch updates from the floor of each chamber of Congress
|
50
|
+
#
|
51
|
+
# @return [Hashie::Rash]
|
52
|
+
# @example
|
53
|
+
# Congress.key = YOUR_RTC_API_KEY
|
54
|
+
# Congress.floor_updates
|
55
|
+
def floor_updates(options={})
|
56
|
+
get('/api/v1/floor_updates.json', options.merge(api_key))
|
57
|
+
end
|
58
|
+
|
59
|
+
# Fetch upcoming scheduled committee hearings in the House and Senate
|
60
|
+
#
|
61
|
+
# @return [Hashie::Rash]
|
62
|
+
# @example
|
63
|
+
# Congress.key = YOUR_RTC_API_KEY
|
64
|
+
# Congress.committee_hearings
|
65
|
+
def committee_hearings(options={})
|
66
|
+
get('/api/v1/committee_hearings.json', options.merge(api_key))
|
67
|
+
end
|
68
|
+
|
69
|
+
# Fetch links to various kinds of documents produced by agencies within Congress
|
70
|
+
#
|
71
|
+
# @return [Hashie::Rash]
|
72
|
+
# @example
|
73
|
+
# Congress.key = YOUR_RTC_API_KEY
|
74
|
+
# Congress.documents
|
75
|
+
def documents(options={})
|
76
|
+
get('/api/v1/documents.json', options.merge(api_key))
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def api_key
|
82
|
+
{:apikey => Congress.key}
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'faraday_middleware'
|
2
|
+
|
3
|
+
module Congress
|
4
|
+
module Connection
|
5
|
+
private
|
6
|
+
|
7
|
+
def connection
|
8
|
+
Faraday.new(:url => 'http://api.realtimecongress.org') do |connection|
|
9
|
+
connection.use Faraday::Request::UrlEncoded
|
10
|
+
connection.use Faraday::Response::RaiseError
|
11
|
+
connection.use Faraday::Response::Rashify
|
12
|
+
connection.use Faraday::Response::ParseJson
|
13
|
+
connection.adapter(Faraday.default_adapter)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Congress
|
2
|
+
module Request
|
3
|
+
def get(path, options={})
|
4
|
+
request(:get, path, options)
|
5
|
+
end
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def request(method, path, options)
|
10
|
+
response = connection.send(method) do |request|
|
11
|
+
request.url(path, options)
|
12
|
+
end
|
13
|
+
response.body
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Congress::Client do
|
4
|
+
before do
|
5
|
+
@client = Congress::Client.new
|
6
|
+
Congress.configure do |config|
|
7
|
+
config.key = "abc123"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '#bills' do
|
12
|
+
before do
|
13
|
+
stub_get('/api/v1/bills.json?apikey=abc123').
|
14
|
+
to_return(:status => 200, :body => fixture('bills.json'))
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should fetch bills introduced bills and resolutions in Congress" do
|
18
|
+
bills = @client.bills
|
19
|
+
a_get('/api/v1/bills.json?apikey=abc123').
|
20
|
+
should have_been_made
|
21
|
+
bills['count'].should == 17836
|
22
|
+
bills['bills'].first.bill_id.should == "hres314-112"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#votes' do
|
27
|
+
before do
|
28
|
+
stub_get('/api/v1/votes.json?apikey=abc123').
|
29
|
+
to_return(:status => 200, :body => fixture('votes.json'))
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should fetch votes taken in Congress" do
|
33
|
+
votes = @client.votes
|
34
|
+
a_get('/api/v1/votes.json?apikey=abc123').
|
35
|
+
should have_been_made
|
36
|
+
votes['count'].should == 5103
|
37
|
+
votes['votes'].first.roll_id.should == "s91-2011"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#amendments' do
|
42
|
+
before do
|
43
|
+
stub_get('/api/v1/amendments.json?apikey=abc123').
|
44
|
+
to_return(:status => 200, :body => fixture('amendments.json'))
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should fetch amendments to bills and resolutions offered in Congress" do
|
48
|
+
amendments = @client.amendments
|
49
|
+
a_get('/api/v1/amendments.json?apikey=abc123').
|
50
|
+
should have_been_made
|
51
|
+
amendments['count'].should == 6606
|
52
|
+
amendments['amendments'].first.bill_id.should == "s679-112"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '#videos' do
|
57
|
+
before do
|
58
|
+
stub_get('/api/v1/videos.json?apikey=abc123').
|
59
|
+
to_return(:status => 200, :body => fixture('videos.json'))
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should fetch videos from the U.S. House of Representatives and from the White House" do
|
63
|
+
videos = @client.videos
|
64
|
+
a_get('/api/v1/videos.json?apikey=abc123').
|
65
|
+
should have_been_made
|
66
|
+
videos['count'].should == 1034
|
67
|
+
videos['videos'].first.video_id.should == "whitehouse-1308389400-weekly-address-celebrating-fathers"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe '#floor_updates' do
|
72
|
+
before do
|
73
|
+
stub_get('/api/v1/floor_updates.json?apikey=abc123').
|
74
|
+
to_return(:status => 200, :body => fixture('floor_updates.json'))
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should fetch updates from the floor of each chamber of Congress" do
|
78
|
+
floor_updates = @client.floor_updates
|
79
|
+
a_get('/api/v1/floor_updates.json?apikey=abc123').
|
80
|
+
should have_been_made
|
81
|
+
floor_updates['count'].should == 2183
|
82
|
+
floor_updates['floor_updates'].first.chamber.should == "senate"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe '#committee_hearings' do
|
87
|
+
before do
|
88
|
+
stub_get('/api/v1/committee_hearings.json?apikey=abc123').
|
89
|
+
to_return(:status => 200, :body => fixture('committee_hearings.json'))
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should fetch upcoming scheduled committee hearings in the House and Senate" do
|
93
|
+
committee_hearings = @client.committee_hearings
|
94
|
+
a_get('/api/v1/committee_hearings.json?apikey=abc123').
|
95
|
+
should have_been_made
|
96
|
+
committee_hearings['count'].should == 482
|
97
|
+
committee_hearings['committee_hearings'].first.committee_id.should == "SSVA"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe '#documents' do
|
102
|
+
before do
|
103
|
+
stub_get('/api/v1/documents.json?apikey=abc123').
|
104
|
+
to_return(:status => 200, :body => fixture('documents.json'))
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should fetch links to various kinds of documents produced by agencies within Congress" do
|
108
|
+
documents = @client.documents
|
109
|
+
a_get('/api/v1/documents.json?apikey=abc123').
|
110
|
+
should have_been_made
|
111
|
+
documents['count'].should == 124
|
112
|
+
documents['documents'].first.document_type.should == "whip_notice"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|