akismet 1.0.2 → 2.0.0
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 +4 -4
- data/.yardopts +4 -0
- data/{MIT-LICENSE → LICENSE.txt} +0 -0
- data/README.md +123 -68
- data/lib/akismet.rb +62 -2
- data/lib/akismet/client.rb +217 -235
- data/lib/akismet/error.rb +1 -18
- data/lib/akismet/version.rb +1 -1
- metadata +53 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 00663d1516528ee39d7e814ea5393f177802be86
|
4
|
+
data.tar.gz: 99dccbfcabb40bd23a8e9239503eee9885e6c4f3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d235bdf6c5346a477295d3285d8fcfd56079edead6287b7001e1f5e4d6156920480fa4e066a8e8bcf12ba78f34a533b762e11b9c85068e1fee5faea47a6212ad
|
7
|
+
data.tar.gz: bcadc97707e2fe6a250e9cce4f2093cb3e6303a26536d9527a3eb07710cc79802c1663e6b13f77a8b5ea697c7ddb8053e27bda282427acdace04c9282803751a
|
data/.yardopts
ADDED
data/{MIT-LICENSE → LICENSE.txt}
RENAMED
File without changes
|
data/README.md
CHANGED
@@ -1,68 +1,123 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
1
|
+
# akismet
|
2
|
+
|
3
|
+
A Ruby client for the [Akismet API](http://akismet.com/development/api/).
|
4
|
+
|
5
|
+
[](http://badge.fury.io/rb/akismet)
|
6
|
+
[](https://travis-ci.org/jonahb/akismet)
|
7
|
+
|
8
|
+
## Getting Started
|
9
|
+
|
10
|
+
### Installation
|
11
|
+
|
12
|
+
```bash
|
13
|
+
gem install akismet
|
14
|
+
```
|
15
|
+
|
16
|
+
### Documentation
|
17
|
+
|
18
|
+
This README provides an overview of `akismet`. Full documentation is
|
19
|
+
available at [rubydoc.info](http://www.rubydoc.info/gems/akismet).
|
20
|
+
|
21
|
+
### API Key
|
22
|
+
|
23
|
+
Sign up at [akismet.com](https://akismet.com/) and retrieve your API
|
24
|
+
key from your [account page](https://akismet.com/account/).
|
25
|
+
|
26
|
+
## Usage
|
27
|
+
|
28
|
+
### Basics
|
29
|
+
|
30
|
+
Set your API key and app URL (a URL representing your app):
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
Akismet.api_key = '<your API key>'
|
34
|
+
Akismet.app_url = 'http://example.com'
|
35
|
+
```
|
36
|
+
|
37
|
+
Then check whether a comment is spam ...
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
# request is a Rack::Request
|
41
|
+
is_spam = Akismet.spam?(request.ip, request.user_agent, text: 'Poppycock!')
|
42
|
+
```
|
43
|
+
|
44
|
+
... file a spam report ...
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
Akismet.spam request.ip, request.user_agent, text: 'I earn $2,000 a week ...'
|
48
|
+
```
|
49
|
+
|
50
|
+
... or flag a false positive ("ham" is not-spam):
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
Akismet.ham request.ip, request.user_agent, text: '"Viagra" derives from the Sanskrit ...'
|
54
|
+
```
|
55
|
+
|
56
|
+
### Accuracy
|
57
|
+
|
58
|
+
To maximize the accuracy of the filter, submit as many of the [documented](http://www.rubydoc.info/gems/akismet) parameters as possible. Also submit environment variables related to the comment as a hash in the `env` parameter (Akismet suggests [these variables](http://php.net/manual/en/reserved.variables.server.php)):
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
vars = %w{
|
62
|
+
HTTP_ACCEPT
|
63
|
+
HTTP_ACCEPT_ENCODING
|
64
|
+
# ...
|
65
|
+
}
|
66
|
+
|
67
|
+
params = {
|
68
|
+
type: 'comment',
|
69
|
+
text: 'A new life awaits you in the Off-World colonies.',
|
70
|
+
created_at: DateTime.now,
|
71
|
+
author: 'Eldon',
|
72
|
+
author_email: 'eldont@aol.com',
|
73
|
+
author_url: 'http://geocities.com/eldont',
|
74
|
+
post_url: 'http://example.com/posts/1',
|
75
|
+
post_modified_at: DateTime.new(2015, 1, 1),
|
76
|
+
referrer: request.referrer,
|
77
|
+
env: request.env.slice(*vars) # slice courtesy of Active Support
|
78
|
+
}
|
79
|
+
|
80
|
+
is_spam = Akismet.spam?(request.ip, request.user_agent, params)
|
81
|
+
```
|
82
|
+
### Blatant Spam
|
83
|
+
|
84
|
+
Akismet flags blatant spam that should be deleted without review. This feature is exposed via `Akismet.check`:
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
is_spam, is_blatant = Akismet.check(request.ip, request.user_agent, text: 'Buy everything ... now!')
|
88
|
+
```
|
89
|
+
|
90
|
+
### Reusing Connections
|
91
|
+
|
92
|
+
`Akismet.spam?` and friends create a new TCP connection each time you call them. If you have many comments to check or report, use `Akismet.open` to reuse a single connection:
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
Akismet.open do |client|
|
96
|
+
for comment in comments
|
97
|
+
is_spam = client.spam?(comment.ip, comment.user_agent, text: comment.text)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
```
|
101
|
+
|
102
|
+
### Akismet::Client
|
103
|
+
|
104
|
+
In the example above, the object yielded to the block is an `Akismet::Client`. `Akismet::Client` underlies the `Akismet` class methods. Use it on its own to manually open and close connections or override the global API key:
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
begin
|
108
|
+
client = Akismet::Client.new('api-key-2', 'http://example2.com')
|
109
|
+
client.open
|
110
|
+
client.spam request.ip, request.user_agent, text: 'Bank error in your favor!'
|
111
|
+
ensure
|
112
|
+
client.close
|
113
|
+
end
|
114
|
+
```
|
115
|
+
|
116
|
+
## Tests
|
117
|
+
|
118
|
+
1. Set the environment variable AKISMET\_API\_KEY to your API key
|
119
|
+
2. `rake`
|
120
|
+
|
121
|
+
## Contributing
|
122
|
+
|
123
|
+
Please submit issues and pull requests to [jonahb/akismet](https://github.com/jonahb/akismet) on GitHub.
|
data/lib/akismet.rb
CHANGED
@@ -3,5 +3,65 @@
|
|
3
3
|
error
|
4
4
|
client
|
5
5
|
}.each do |file|
|
6
|
-
require
|
7
|
-
end
|
6
|
+
require "akismet/#{file}"
|
7
|
+
end
|
8
|
+
|
9
|
+
# {Akismet} provides convenience methods that instantiate a {Akismet::Client}
|
10
|
+
# and invoke the Akismet API in one call. Before calling these methods, set
|
11
|
+
# {api_key} and {app_url}.
|
12
|
+
#
|
13
|
+
module Akismet
|
14
|
+
class << self
|
15
|
+
|
16
|
+
# The API key obtained at akismet.com. Set before calling the {Akismet}
|
17
|
+
# class methods.
|
18
|
+
# @return [String]
|
19
|
+
attr_accessor :api_key
|
20
|
+
|
21
|
+
# A URL that identifies the application making the request. Set before
|
22
|
+
# calling the {Akismet} class methods.
|
23
|
+
# @return [String]
|
24
|
+
attr_accessor :app_url
|
25
|
+
|
26
|
+
# The name of the application making the request
|
27
|
+
# @return [String]
|
28
|
+
attr_accessor :app_name
|
29
|
+
|
30
|
+
# The version of the application making the request
|
31
|
+
# @return [String]
|
32
|
+
attr_accessor :app_version
|
33
|
+
|
34
|
+
# (see Client#check)
|
35
|
+
def check(user_ip, user_agent, params = {})
|
36
|
+
with_client { |client| client.check user_ip, user_agent, params }
|
37
|
+
end
|
38
|
+
|
39
|
+
# (see Client#spam?)
|
40
|
+
def spam?(user_ip, user_agent, params = {})
|
41
|
+
with_client { |client| client.spam? user_ip, user_agent, params }
|
42
|
+
end
|
43
|
+
|
44
|
+
# (see Client#spam)
|
45
|
+
def spam(user_ip, user_agent, params = {})
|
46
|
+
with_client { |client| client.spam user_ip, user_agent, params }
|
47
|
+
end
|
48
|
+
|
49
|
+
# (see Client#ham)
|
50
|
+
def ham(user_ip, user_agent, params = {})
|
51
|
+
with_client { |client| client.ham user_ip, user_agent, params }
|
52
|
+
end
|
53
|
+
|
54
|
+
# (see Client.open)
|
55
|
+
def open(&block)
|
56
|
+
with_client(&block)
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def with_client(&block)
|
62
|
+
raise "Set Akismet.api_key" unless api_key
|
63
|
+
raise "Set Akismet.app_url" unless app_url
|
64
|
+
Akismet::Client.open api_key, app_url, app_name: app_name, app_version: app_version, &block
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/akismet/client.rb
CHANGED
@@ -1,166 +1,108 @@
|
|
1
|
+
require 'date'
|
1
2
|
require 'net/http'
|
2
|
-
require '
|
3
|
+
require 'uri'
|
3
4
|
|
4
5
|
module Akismet
|
5
6
|
|
6
|
-
# A Ruby client for the Akismet API.
|
7
|
-
#
|
8
|
-
# @example
|
9
|
-
#
|
10
|
-
# # Verify an API key
|
11
|
-
# #
|
12
|
-
#
|
13
|
-
# Akismet::Client.new( 'apikey123', 'http://jonahb.com' ).verify_key
|
14
|
-
#
|
15
|
-
# @example
|
16
|
-
#
|
17
|
-
# # Check whether a comment is spam
|
18
|
-
# #
|
19
|
-
#
|
20
|
-
# client = Akismet::Client.new( 'apikey123',
|
21
|
-
# 'http://jonahb.com',
|
22
|
-
# :app_name => 'jonahb.com',
|
23
|
-
# :app_version => '1.0' )
|
24
|
-
#
|
25
|
-
# # assumes variables comment, post_url, request (a racklike HTTP request)
|
26
|
-
# spam = client.comment_check( request.remote_ip,
|
27
|
-
# request.user_agent,
|
28
|
-
# :content_type => 'comment',
|
29
|
-
# :referrer => request.headers[ 'HTTP_REFERER' ],
|
30
|
-
# :permalink => post_url,
|
31
|
-
# :comment_author => comment.author,
|
32
|
-
# :comment_author_email => comment.author_email,
|
33
|
-
# :comment_content => comment.body )
|
34
|
-
#
|
35
|
-
# if spam
|
36
|
-
# # ...
|
37
|
-
# end
|
38
|
-
#
|
39
|
-
# @example
|
40
|
-
#
|
41
|
-
# # Submit a batch of checks using a single TCP connection
|
42
|
-
# #
|
43
|
-
#
|
44
|
-
#
|
45
|
-
# client = Akismet::Client.new( 'apikey123',
|
46
|
-
# 'http://jonahb.com',
|
47
|
-
# :app_name => 'jonahb.com',
|
48
|
-
# :app_version => '1.0' )
|
49
|
-
#
|
50
|
-
# begin
|
51
|
-
# client.open
|
52
|
-
# comments.each do |comment|
|
53
|
-
# client.comment_check( ... ) # see example above
|
54
|
-
# end
|
55
|
-
# ensure
|
56
|
-
# client.close
|
57
|
-
# end
|
58
|
-
#
|
59
|
-
# # ... or ...
|
60
|
-
#
|
61
|
-
# Akismet::Client.open( 'apikey123',
|
62
|
-
# 'http://jonahb.com',
|
63
|
-
# :app_name => 'jonahb.com',
|
64
|
-
# :app_version => '1.0' ) do |client|
|
65
|
-
# comments.each do |comment|
|
66
|
-
# client.comment_check( ... ) # see example above
|
67
|
-
# end
|
68
|
-
# end
|
69
|
-
#
|
70
|
-
#
|
71
7
|
class Client
|
72
8
|
|
73
|
-
# The API key obtained at akismet.com
|
9
|
+
# The API key obtained at akismet.com
|
74
10
|
# @return [String]
|
75
|
-
#
|
76
11
|
attr_reader :api_key
|
77
12
|
|
78
|
-
|
79
|
-
# The URL of the home page of the application making the request.
|
13
|
+
# A URL that identifies the application making the request
|
80
14
|
# @return [String]
|
81
|
-
|
82
|
-
attr_reader :home_url
|
15
|
+
attr_reader :app_url
|
83
16
|
|
84
|
-
|
85
|
-
# The name of the application making the request, e.g "jonahb.com".
|
17
|
+
# The name of the application making the request
|
86
18
|
# @return [String]
|
87
|
-
#
|
88
19
|
attr_reader :app_name
|
89
20
|
|
90
|
-
|
91
|
-
# The version of the application making the request, e.g. "1.0".
|
21
|
+
# The version of the application making the request
|
92
22
|
# @return [String]
|
93
|
-
#
|
94
23
|
attr_reader :app_version
|
95
24
|
|
25
|
+
# @!group Constructors
|
96
26
|
|
97
27
|
# @param [String] api_key
|
98
|
-
# The API key obtained at akismet.com
|
99
|
-
# @param [String]
|
100
|
-
# The URL of the home page of the application making the request
|
28
|
+
# The API key obtained at akismet.com
|
29
|
+
# @param [String] app_url
|
30
|
+
# The URL of the home page of the application making the request
|
101
31
|
# @option options [String] :app_name
|
102
32
|
# The name of the application making the request, e.g. "jonahb.com".
|
103
33
|
# Forms part of the User-Agent header submitted to Akismet.
|
104
34
|
# @option options [String] :app_version
|
105
35
|
# The version of the application making the request, e.g. "1.0". Forms
|
106
36
|
# part of the User-Agent header submitted to Akismet. Ignored if
|
107
|
-
# :app_name is not
|
37
|
+
# :app_name is not provided.
|
108
38
|
#
|
109
|
-
def initialize(
|
39
|
+
def initialize(api_key, app_url, options = {})
|
110
40
|
@api_key = api_key
|
111
|
-
@
|
41
|
+
@app_url = app_url
|
112
42
|
@app_name = options[ :app_name ]
|
113
43
|
@app_version = options[ :app_version ]
|
44
|
+
@http_session = nil
|
114
45
|
end
|
115
46
|
|
47
|
+
# @!group Managing Connections
|
116
48
|
|
117
|
-
#
|
118
|
-
#
|
119
|
-
#
|
120
|
-
#
|
121
|
-
# @
|
122
|
-
# @
|
123
|
-
# @
|
49
|
+
# Initializes a client, opens it, yields it to the given block, and closes
|
50
|
+
# it when the block returns. Allows you to perform several operations over
|
51
|
+
# a single TCP connection.
|
52
|
+
# @param (see #initialize)
|
53
|
+
# @option (see #initialize)
|
54
|
+
# @yieldparam [Client] client
|
55
|
+
# @return [Object]
|
56
|
+
# The return value of the block
|
124
57
|
# @see #open
|
125
58
|
#
|
126
|
-
def self.open(
|
59
|
+
def self.open(api_key, app_url, options = {})
|
127
60
|
raise "Block required" unless block_given?
|
128
|
-
client =
|
129
|
-
|
130
|
-
client = new( api_key, home_url, options )
|
131
|
-
client.open
|
132
|
-
yield client
|
133
|
-
ensure
|
134
|
-
client.close if client
|
135
|
-
end
|
136
|
-
nil
|
61
|
+
client = new(api_key, app_url)
|
62
|
+
client.open { yield client }
|
137
63
|
end
|
138
64
|
|
139
|
-
|
140
|
-
# Opens the client. You may use this method in combination with {#close}
|
141
|
-
# to submit a batch of requests using a single TCP and HTTP session.
|
65
|
+
# Opens the client, creating a new TCP connection.
|
142
66
|
#
|
143
|
-
# If
|
144
|
-
#
|
145
|
-
#
|
67
|
+
# If a block is given, yields to the block, closes the client when the
|
68
|
+
# block returns, and returns the return value of the block. If a
|
69
|
+
# block is not given, returns self and leaves the client open, relying on
|
70
|
+
# the caller to close the client with {#close}.
|
146
71
|
#
|
147
|
-
# Note that
|
148
|
-
#
|
149
|
-
#
|
72
|
+
# Note that opening and closing the client is only required if you want to
|
73
|
+
# make several calls over one TCP connection. Otherwise, you can simply
|
74
|
+
# call {#spam?}, {#check}, {#ham}, or {#spam}, which call {#open} for you
|
75
|
+
# if necessary.
|
150
76
|
#
|
151
|
-
#
|
152
|
-
#
|
153
|
-
#
|
154
|
-
# @
|
155
|
-
#
|
77
|
+
# Due to a peculiarity of the Akismet API, {#verify_key} always creates its
|
78
|
+
# own connection.
|
79
|
+
#
|
80
|
+
# @overload open
|
81
|
+
# Opens the client, yields to the block, and closes the client when the
|
82
|
+
# block returns.
|
83
|
+
# @yield
|
84
|
+
# A block to be called when the client is open
|
85
|
+
# @return [Object]
|
86
|
+
# The return value of the block
|
87
|
+
# @raise [StandardError]
|
88
|
+
# The client is already open
|
89
|
+
# @overload open
|
90
|
+
# @return [self]
|
91
|
+
# @raise [StandardError]
|
92
|
+
# The client is already open
|
156
93
|
#
|
157
94
|
def open
|
158
95
|
raise "Already open" if open?
|
96
|
+
|
159
97
|
@http_session = Net::HTTP.new( "#{ api_key }.rest.akismet.com", 80 )
|
160
|
-
@http_session.start
|
161
|
-
self
|
162
|
-
end
|
163
98
|
|
99
|
+
begin
|
100
|
+
@http_session.start
|
101
|
+
block_given? ? yield : self
|
102
|
+
ensure
|
103
|
+
close if block_given?
|
104
|
+
end
|
105
|
+
end
|
164
106
|
|
165
107
|
# Closes the Client.
|
166
108
|
# @return [self]
|
@@ -172,122 +114,141 @@ module Akismet
|
|
172
114
|
self
|
173
115
|
end
|
174
116
|
|
175
|
-
|
176
117
|
# Whether the Client is open.
|
177
|
-
# @return [
|
118
|
+
# @return [Boolean]
|
178
119
|
#
|
179
120
|
def open?
|
180
121
|
@http_session && @http_session.started?
|
181
122
|
end
|
182
123
|
|
124
|
+
# @!group Verifying Keys
|
183
125
|
|
184
126
|
# Checks the validity of the API key.
|
185
|
-
# @return [
|
127
|
+
# @return [Boolean]
|
186
128
|
#
|
187
129
|
def verify_key
|
188
|
-
response = Net::HTTP.start(
|
189
|
-
invoke
|
130
|
+
response = Net::HTTP.start('rest.akismet.com', 80) do |session|
|
131
|
+
invoke session, 'verify-key', blog: app_url, key: api_key
|
190
132
|
end
|
191
133
|
|
192
|
-
unless %w{ valid invalid }.include?(
|
134
|
+
unless %w{ valid invalid }.include?(response.body)
|
193
135
|
raise_with_response response
|
194
136
|
end
|
195
137
|
|
196
138
|
response.body == 'valid'
|
197
139
|
end
|
198
140
|
|
199
|
-
|
200
|
-
#
|
201
|
-
#
|
202
|
-
#
|
203
|
-
#
|
141
|
+
# @!macro akismet_method
|
142
|
+
# @param [String] user_ip
|
143
|
+
# The comment author's IP address
|
144
|
+
# @param [String] user_agent
|
145
|
+
# The comment author's user-agent
|
146
|
+
# @param [Hash{Symbol => Object}] params
|
147
|
+
# Optional parameters. To maximize accuracy, pass as many as possible.
|
148
|
+
# @option params [String] :referrer
|
149
|
+
# The value of the HTTP_REFERER header. Note that the parameter is
|
150
|
+
# spelled with two consecutive 'r's.
|
151
|
+
# @option params [String] :post_url
|
152
|
+
# The URL of the post, article, etc. on which the comment was made
|
153
|
+
# @option params [DateTime] :post_modified_at
|
154
|
+
# The date and time the post was last modified
|
155
|
+
# @option params [String] :type
|
156
|
+
# Suggested values include 'comment', 'trackback', and 'pingback'
|
157
|
+
# @option params [String] :text
|
158
|
+
# The text of the comment
|
159
|
+
# @option params [DateTime] :created_at
|
160
|
+
# The date and time the comment was created
|
161
|
+
# @option params [String] :author
|
162
|
+
# The comment author's name
|
163
|
+
# @option params [String] :author_email
|
164
|
+
# The comment author's email address
|
165
|
+
# @option params [String] :author_url
|
166
|
+
# The comment author's personal URL
|
167
|
+
# @option params [Array<String>] :languages
|
168
|
+
# The ISO 639-1 codes of the languages in use on the site where the
|
169
|
+
# comment appears
|
170
|
+
# @option params [Boolean] :test
|
171
|
+
# When set to true, Akismet does not use the comment to train the filter
|
172
|
+
# @option params [Hash{Symbol, String => Object}] :env
|
173
|
+
# Environment variables such as HTTP headers related to the comment
|
174
|
+
# submission
|
175
|
+
# @raise [Akismet::Error]
|
176
|
+
# The Akismet service returned an error
|
177
|
+
# @raise [ArgumentError]
|
178
|
+
# An environment variable conflicts with a built-in parameter
|
179
|
+
# @raise [ArgumentError]
|
180
|
+
# Invalid param
|
181
|
+
|
182
|
+
# @!group Checking
|
183
|
+
|
184
|
+
# Checks whether a comment is spam and whether it is "blatant."
|
185
|
+
# @!macro akismet_method
|
186
|
+
# @return [(Boolean, Boolean)]
|
187
|
+
# An array containing two booleans. The first indicates whether the
|
188
|
+
# comment is spam. The second indicates whether it is "blatant,"
|
189
|
+
# i.e. whether it can be deleted without review.
|
204
190
|
#
|
205
|
-
|
206
|
-
|
207
|
-
# @return [boolean]
|
208
|
-
# @raise [Akismet::Error]
|
209
|
-
# @param [String] user_ip
|
210
|
-
# The IP address of the submitter of the comment.
|
211
|
-
# @param [String] user_agent
|
212
|
-
# The user agent of the web browser submitting the comment. Typically
|
213
|
-
# the HTTP_USER_AGENT CGI variable. Not to be confused with the user
|
214
|
-
# agent of the Akismet library.
|
215
|
-
# @option params [String] :referrer
|
216
|
-
# The value of the HTTP_REFERER header. Note that the parameter is
|
217
|
-
# spelled with two consecutive 'r's.
|
218
|
-
# @option params [String] :permalink
|
219
|
-
# The permanent URL of the entry to which the comment pertains.
|
220
|
-
# @option params [String] :comment_type
|
221
|
-
# 'comment', 'trackback', 'pingback', or a made-up value like
|
222
|
-
# 'registration'
|
223
|
-
# @option params [String] :comment_author
|
224
|
-
# The name of the author of the comment.
|
225
|
-
# @option params [String] :comment_author_email
|
226
|
-
# The email address of the author of the comment.
|
227
|
-
# @option params [String] :comment_author_url
|
228
|
-
# A URL submitted with the comment.
|
229
|
-
# @option params [String] :comment_content
|
230
|
-
# The text of the comment.
|
231
|
-
#
|
232
|
-
def comment_check( user_ip, user_agent, params = {} )
|
233
|
-
response = invoke_comment_method( 'comment-check',
|
191
|
+
def check(user_ip, user_agent, params = {})
|
192
|
+
response = invoke_comment_method('comment-check',
|
234
193
|
user_ip,
|
235
194
|
user_agent,
|
236
|
-
params
|
195
|
+
params)
|
237
196
|
|
238
|
-
unless %w{ true false }.include?(
|
197
|
+
unless %w{ true false }.include?(response.body)
|
239
198
|
raise_with_response response
|
240
199
|
end
|
241
200
|
|
242
|
-
|
201
|
+
[
|
202
|
+
response.body == 'true',
|
203
|
+
response['X-akismet-pro-tip'] == 'discard'
|
204
|
+
]
|
243
205
|
end
|
206
|
+
alias_method :comment_check, :check
|
244
207
|
|
245
|
-
|
246
|
-
#
|
247
|
-
#
|
248
|
-
# it for the duration of the call.
|
208
|
+
# Checks whether a comment is spam.
|
209
|
+
# @!macro akismet_method
|
210
|
+
# @return [Boolean]
|
249
211
|
#
|
250
|
-
|
251
|
-
|
252
|
-
|
212
|
+
def spam?(user_ip, user_agent, params = {})
|
213
|
+
check(user_ip, user_agent, params)[0]
|
214
|
+
end
|
215
|
+
|
216
|
+
# @!group Reporting
|
217
|
+
|
218
|
+
# Submits a comment that has been identified as not-spam (ham).
|
219
|
+
# @!macro akismet_method
|
220
|
+
# @return [void]
|
253
221
|
#
|
254
|
-
def
|
255
|
-
response = invoke_comment_method(
|
222
|
+
def ham(user_ip, user_agent, params = {})
|
223
|
+
response = invoke_comment_method('submit-ham',
|
256
224
|
user_ip,
|
257
225
|
user_agent,
|
258
|
-
params
|
226
|
+
params)
|
259
227
|
|
260
228
|
unless response.body == 'Thanks for making the web a better place.'
|
261
229
|
raise_with_response response
|
262
230
|
end
|
263
|
-
|
264
|
-
nil
|
265
231
|
end
|
232
|
+
alias_method :submit_ham, :ham
|
266
233
|
|
267
|
-
|
268
|
-
#
|
269
|
-
#
|
270
|
-
# the duration of the call.
|
234
|
+
# Submits a comment that has been identified as spam.
|
235
|
+
# @!macro akismet_method
|
236
|
+
# @return [void]
|
271
237
|
#
|
272
|
-
|
273
|
-
|
274
|
-
# @see #comment_check
|
275
|
-
#
|
276
|
-
def submit_spam( user_ip, user_agent, params = {} )
|
277
|
-
response = invoke_comment_method( 'submit-spam',
|
238
|
+
def spam(user_ip, user_agent, params = {})
|
239
|
+
response = invoke_comment_method('submit-spam',
|
278
240
|
user_ip,
|
279
241
|
user_agent,
|
280
|
-
params
|
242
|
+
params)
|
281
243
|
|
282
244
|
unless response.body == 'Thanks for making the web a better place.'
|
283
245
|
raise_with_response response
|
284
246
|
end
|
285
|
-
|
286
|
-
nil
|
287
247
|
end
|
248
|
+
alias_method :submit_spam, :spam
|
288
249
|
|
289
250
|
|
290
|
-
|
251
|
+
private
|
291
252
|
|
292
253
|
|
293
254
|
# Yields an HTTP session to the given block. Uses this instance's open
|
@@ -296,54 +257,49 @@ module Akismet
|
|
296
257
|
# @yield [Net::HTTP]
|
297
258
|
#
|
298
259
|
def in_http_session
|
299
|
-
raise "Block required" unless block_given?
|
300
260
|
if open?
|
301
261
|
yield @http_session
|
302
262
|
else
|
303
|
-
|
304
|
-
open
|
305
|
-
yield @http_session
|
306
|
-
ensure
|
307
|
-
close
|
308
|
-
end
|
263
|
+
open { yield @http_session }
|
309
264
|
end
|
310
265
|
end
|
311
266
|
|
312
|
-
|
313
|
-
# Raises an error given a response. The Akismet documentation states that
|
314
|
-
# the HTTP headers of the response may contain error strings. I can't
|
315
|
-
# seem to find them, so for now just raise an unknown error.
|
316
267
|
# @param [Net::HTTPResponse] response
|
317
|
-
#
|
318
268
|
def raise_with_response( response )
|
319
|
-
raise Error
|
269
|
+
raise Error, response['X-akismet-debug-help'] || 'Unknown error'
|
320
270
|
end
|
321
271
|
|
322
|
-
|
323
272
|
# @param [String] method_name
|
324
273
|
# @param [String] user_ip
|
325
274
|
# @param [String] user_agent
|
326
275
|
# @param [Hash] params
|
327
276
|
# @return [Net::HTTPResponse]
|
328
|
-
# @raise [
|
329
|
-
#
|
277
|
+
# @raise [ArgumentError]
|
278
|
+
# An environment variable conflicts with a built-in parameter
|
279
|
+
# @raise [ArgumentError]
|
280
|
+
# Invalid parameter
|
330
281
|
#
|
331
|
-
def invoke_comment_method(
|
332
|
-
|
333
|
-
:user_ip => user_ip,
|
334
|
-
:user_agent => user_agent
|
282
|
+
def invoke_comment_method(method_name, user_ip, user_agent, params = {})
|
283
|
+
env = params[:env] || {}
|
335
284
|
|
336
|
-
|
337
|
-
|
285
|
+
for key in env.keys
|
286
|
+
if PARAM_TO_API_PARAM.has_value?(key.to_sym)
|
287
|
+
raise ArgumentError, "Environment variable '#{key}' conflicts with built-in API parameter"
|
288
|
+
end
|
338
289
|
end
|
339
290
|
|
340
|
-
|
341
|
-
|
291
|
+
params = params.each_with_object(Hash.new) do |(name, value), api_params|
|
292
|
+
next if name == :env
|
293
|
+
api_name = PARAM_TO_API_PARAM[name] || raise(ArgumentError, "Invalid param: #{name}")
|
294
|
+
api_params[api_name] = value
|
342
295
|
end
|
343
296
|
|
344
|
-
|
345
|
-
end
|
297
|
+
params = env.merge(params).merge(blog: app_url, user_ip: user_ip, user_agent: user_agent)
|
346
298
|
|
299
|
+
in_http_session do |session|
|
300
|
+
invoke session, method_name, params
|
301
|
+
end
|
302
|
+
end
|
347
303
|
|
348
304
|
# @param [Net::HTTP] http_session
|
349
305
|
# A started HTTP session
|
@@ -352,10 +308,16 @@ module Akismet
|
|
352
308
|
# @raise [Akismet::Error]
|
353
309
|
# An HTTP response other than 200 is received.
|
354
310
|
#
|
355
|
-
def invoke(
|
356
|
-
|
357
|
-
|
358
|
-
|
311
|
+
def invoke(http_session, method_name, params = {})
|
312
|
+
params[:blog_charset] = 'UTF-8'
|
313
|
+
|
314
|
+
params = params.collect do |name, value|
|
315
|
+
[name.to_s.encode('UTF-8'), format(value).encode('UTF-8')]
|
316
|
+
end
|
317
|
+
|
318
|
+
response = http_session.post("/1.1/#{ method_name }",
|
319
|
+
URI.encode_www_form(params),
|
320
|
+
http_headers)
|
359
321
|
|
360
322
|
unless response.is_a?( Net::HTTPOK )
|
361
323
|
raise Error, "HTTP #{ response.code } received (expected 200)"
|
@@ -364,46 +326,66 @@ module Akismet
|
|
364
326
|
response
|
365
327
|
end
|
366
328
|
|
329
|
+
# @param [Object] object
|
330
|
+
# @return [String]
|
331
|
+
def format(object)
|
332
|
+
case object
|
333
|
+
when DateTime
|
334
|
+
object.iso8601
|
335
|
+
when TrueClass
|
336
|
+
'1'
|
337
|
+
when FalseClass
|
338
|
+
'0'
|
339
|
+
when Array
|
340
|
+
object.collect { |element| format(element) }.join(', ')
|
341
|
+
else
|
342
|
+
object.to_s
|
343
|
+
end
|
344
|
+
end
|
367
345
|
|
368
346
|
# @return [Hash]
|
369
|
-
#
|
370
347
|
def http_headers
|
371
|
-
{
|
348
|
+
{
|
349
|
+
'User-Agent' => user_agent,
|
350
|
+
'Content-Type' => 'application/x-www-form-urlencoded'
|
351
|
+
}
|
372
352
|
end
|
373
353
|
|
374
|
-
|
375
|
-
# @return [String]
|
376
|
-
#
|
377
|
-
def url_encode( hash = {} )
|
378
|
-
hash.collect do |k, v|
|
379
|
-
"#{ CGI.escape( k.to_s ) }=#{ CGI.escape( v.to_s ) }"
|
380
|
-
end.join( "&" )
|
381
|
-
end
|
382
|
-
|
383
|
-
|
384
354
|
# From the Akismet documentation:
|
385
355
|
# If possible, your user agent string should always use the following
|
386
356
|
# format: Application Name/Version | Plugin Name/Version
|
387
357
|
# @return [String]
|
388
358
|
#
|
389
359
|
def user_agent
|
390
|
-
[
|
360
|
+
[user_agent_app, user_agent_plugin].compact.join(" | ")
|
391
361
|
end
|
392
362
|
|
393
|
-
|
394
363
|
# Returns nil if the Client was instantiated without an app_name.
|
395
364
|
# @return [String]
|
396
365
|
#
|
397
366
|
def user_agent_app
|
398
|
-
app_name && [
|
367
|
+
app_name && [app_name, app_version].compact.join("/")
|
399
368
|
end
|
400
369
|
|
401
|
-
|
402
370
|
# @return [String]
|
403
|
-
#
|
404
371
|
def user_agent_plugin
|
405
372
|
"Ruby Akismet/#{ Akismet::VERSION }"
|
406
373
|
end
|
407
374
|
|
375
|
+
PARAM_TO_API_PARAM = {
|
376
|
+
referrer: :referrer,
|
377
|
+
post_url: :permalink,
|
378
|
+
post_modified_at: :comment_post_modified_gmt,
|
379
|
+
text: :comment_content,
|
380
|
+
created_at: :comment_date_gmt,
|
381
|
+
type: :comment_type,
|
382
|
+
author: :comment_author,
|
383
|
+
author_url: :comment_author_url,
|
384
|
+
author_email: :comment_author_email,
|
385
|
+
languages: :blog_lang,
|
386
|
+
user_role: :user_role,
|
387
|
+
test: :is_test,
|
388
|
+
}
|
389
|
+
|
408
390
|
end
|
409
|
-
end
|
391
|
+
end
|
data/lib/akismet/error.rb
CHANGED
@@ -1,23 +1,6 @@
|
|
1
1
|
module Akismet
|
2
2
|
|
3
3
|
class Error < StandardError
|
4
|
-
|
5
|
-
UNKNOWN = 1
|
6
|
-
INVALID_API_KEY = 2
|
7
|
-
|
8
|
-
# An error code corresponding to a constant in Akismet::Error.
|
9
|
-
# @return [Integer]
|
10
|
-
attr_reader :code
|
11
|
-
|
12
|
-
# @param [String] message
|
13
|
-
# A human-readable description of the error.
|
14
|
-
# @param [Integer] code
|
15
|
-
# An error code corresponding to a constant in Akismet::Error.
|
16
|
-
#
|
17
|
-
def initialize( code, message = nil )
|
18
|
-
super( message )
|
19
|
-
@code = code
|
20
|
-
end
|
21
4
|
end
|
22
5
|
|
23
|
-
end
|
6
|
+
end
|
data/lib/akismet/version.rb
CHANGED
metadata
CHANGED
@@ -1,22 +1,66 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: akismet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonah Burke
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
13
|
-
|
14
|
-
|
11
|
+
date: 2015-02-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: yard
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.8.7
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.8.7
|
55
|
+
description:
|
56
|
+
email:
|
57
|
+
- jonah@jonahb.com
|
15
58
|
executables: []
|
16
59
|
extensions: []
|
17
60
|
extra_rdoc_files: []
|
18
61
|
files:
|
19
|
-
-
|
62
|
+
- ".yardopts"
|
63
|
+
- LICENSE.txt
|
20
64
|
- README.md
|
21
65
|
- lib/akismet.rb
|
22
66
|
- lib/akismet/client.rb
|
@@ -34,7 +78,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
34
78
|
requirements:
|
35
79
|
- - ">="
|
36
80
|
- !ruby/object:Gem::Version
|
37
|
-
version:
|
81
|
+
version: 1.9.3
|
38
82
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
39
83
|
requirements:
|
40
84
|
- - ">="
|
@@ -42,8 +86,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
42
86
|
version: '0'
|
43
87
|
requirements: []
|
44
88
|
rubyforge_project:
|
45
|
-
rubygems_version: 2.4.
|
89
|
+
rubygems_version: 2.4.5
|
46
90
|
signing_key:
|
47
91
|
specification_version: 4
|
48
92
|
summary: A Ruby client for the Akismet API
|
49
93
|
test_files: []
|
94
|
+
has_rdoc:
|