akismet 1.0.2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Gem Version](https://badge.fury.io/rb/akismet.svg)](http://badge.fury.io/rb/akismet)
|
6
|
+
[![Build Status](https://travis-ci.org/jonahb/akismet.svg?branch=master)](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:
|