mollom 0.1 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README +22 -10
- data/lib/mollom.rb +22 -8
- data/test/content_response_test.rb +33 -0
- data/test/mollom_test.rb +136 -0
- metadata +6 -5
data/README
CHANGED
@@ -1,25 +1,37 @@
|
|
1
1
|
== Mollom
|
2
2
|
|
3
|
-
This is a Ruby class for easy interfacing with the mollom.com open API for spam detection and content quality
|
3
|
+
This is a Ruby class for easy interfacing with the mollom.com open API for spam detection and content quality assessment.
|
4
|
+
|
5
|
+
== Installation
|
6
|
+
|
7
|
+
You can either install the library as a gem
|
8
|
+
gem install mollom
|
9
|
+
|
10
|
+
Or you can get the latest development version from GitHub:
|
11
|
+
git clone git://github.com/DefV/ruby-mollom.git
|
4
12
|
|
5
13
|
== Usage
|
6
14
|
|
7
|
-
After you have requested a public/private
|
15
|
+
After you have requested a public/private key-pair from Mollom (on http://www.mollom.com), you can start using this class.
|
8
16
|
|
9
|
-
require '
|
17
|
+
require 'rubygems'
|
18
|
+
require 'mollom'
|
10
19
|
|
11
|
-
m = Mollom.new(:private_key => '
|
20
|
+
m = Mollom.new(:private_key => 'your-private-key', :public_key => 'your-public-key')
|
12
21
|
|
13
22
|
content = m.check_content(:post_title => 'Mollem is an open API',
|
14
|
-
:post_body => "
|
23
|
+
:post_body => "Lorem Ipsum dolor...",
|
15
24
|
:author_name => 'Jan De Poorter',
|
16
25
|
:author_url => 'http://blog.defv.be')
|
17
|
-
if content.
|
18
|
-
|
19
|
-
|
20
|
-
|
26
|
+
if content.spam?
|
27
|
+
puts "You, sir, are a spammer.. Goodbye!"
|
28
|
+
elsif content.unsure?
|
29
|
+
# possible spam, possible ham, show CAPTCHA
|
30
|
+
puts "CAPTCHA: " + m.image_captcha(:session_id => content.session_id)["url"]
|
31
|
+
|
32
|
+
captcha_correct = m.check_captcha(:session_id => content.session_id, :solution => STDIN.gets.chomp)
|
21
33
|
else
|
22
34
|
puts "The post is perfect! No spam!"
|
23
35
|
end
|
24
36
|
|
25
|
-
Copyright (c) 2008 Jan De Poorter - Openminds BVBA, released under the MIT license
|
37
|
+
Copyright (c) 2008 Jan De Poorter - Openminds BVBA, released under the MIT license
|
data/lib/mollom.rb
CHANGED
@@ -2,6 +2,9 @@ require 'xmlrpc/client'
|
|
2
2
|
require 'openssl'
|
3
3
|
require 'base64'
|
4
4
|
|
5
|
+
# Mollom API requires this to change, but this gives a warning!
|
6
|
+
# XMLRPC::Client::USER_AGENT = "Ruby Mollom/0.1"
|
7
|
+
|
5
8
|
class Mollom
|
6
9
|
API_VERSION = '1.0'
|
7
10
|
module Errors
|
@@ -116,26 +119,36 @@ class Mollom
|
|
116
119
|
def send_command(command, data = {})
|
117
120
|
server_list.each do |server|
|
118
121
|
begin
|
119
|
-
return XMLRPC::Client.new(server, "/#{API_VERSION}").call(command, data.merge(authentication_hash))
|
122
|
+
return XMLRPC::Client.new(server[:ip], "/#{API_VERSION}").call(command, data.merge(authentication_hash))
|
123
|
+
# TODO: Rescue more stuff (Connection Timeout and such)
|
120
124
|
rescue XMLRPC::FaultException => error
|
121
125
|
case error.faultCode
|
122
126
|
when Errors::Standard
|
123
127
|
raise Error.new(error.faultString)
|
124
128
|
when Errors::Refresh
|
125
|
-
#
|
129
|
+
# we take this one out of our loop
|
130
|
+
raise
|
126
131
|
when Errors::Redirect
|
127
132
|
next
|
128
133
|
else
|
129
|
-
|
134
|
+
next
|
130
135
|
end
|
131
136
|
end
|
132
137
|
end
|
138
|
+
raise Mollom::NoAvailableServers
|
139
|
+
rescue XMLRPC::FaultException
|
140
|
+
# We know it is Errors::Refresh
|
141
|
+
server_list(true)
|
142
|
+
retry
|
133
143
|
end
|
134
144
|
|
135
145
|
# Gets a list of servers from Mollom
|
136
|
-
def server_list
|
137
|
-
|
138
|
-
@server_list ||= XMLRPC::Client.new("xmlrpc.mollom.com", "/#{API_VERSION}").call('mollom.getServerList', authentication_hash).collect
|
146
|
+
def server_list refresh = false
|
147
|
+
@server_list = nil if refresh
|
148
|
+
@server_list ||= XMLRPC::Client.new("xmlrpc.mollom.com", "/#{API_VERSION}").call('mollom.getServerList', authentication_hash).collect do |server|
|
149
|
+
proto, ip = server.split('://')
|
150
|
+
{:proto => proto, :ip => ip}
|
151
|
+
end
|
139
152
|
end
|
140
153
|
|
141
154
|
# Creates a HMAC-SHA1 Hash with the current timestamp, and your private key.
|
@@ -143,8 +156,8 @@ class Mollom
|
|
143
156
|
now = Time.now.gmtime.strftime('%Y-%m-%dT%H:%M:%S.000+0000')
|
144
157
|
|
145
158
|
hash = Base64.encode64(
|
146
|
-
|
147
|
-
)
|
159
|
+
OpenSSL::HMAC.digest(OpenSSL::Digest::SHA1.new, @private_key, now)
|
160
|
+
).chomp
|
148
161
|
|
149
162
|
return :public_key=> @public_key, :time => now, :hash => hash
|
150
163
|
end
|
@@ -196,4 +209,5 @@ class Mollom
|
|
196
209
|
end
|
197
210
|
|
198
211
|
class Error < StandardError; end
|
212
|
+
class NoAvailableServers < Error; end
|
199
213
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
|
3
|
+
require "mollom"
|
4
|
+
|
5
|
+
class TestContentResponse < Test::Unit::TestCase
|
6
|
+
def test_spam
|
7
|
+
cr = Mollom::ContentResponse.new('spam' => 3, 'session_id' => '1', 'quality' => '10')
|
8
|
+
assert cr.spam?
|
9
|
+
assert !cr.ham?
|
10
|
+
assert_equal 'spam', cr.to_s
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_ham
|
14
|
+
cr = Mollom::ContentResponse.new('spam' => 1, 'session_id' => '1', 'quality' => '10')
|
15
|
+
assert cr.ham?
|
16
|
+
assert !cr.spam?
|
17
|
+
assert_equal 'ham', cr.to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_unknown
|
21
|
+
cr = Mollom::ContentResponse.new('spam' => 0, 'session_id' => '1', 'quality' => '10')
|
22
|
+
assert cr.unknown?
|
23
|
+
assert !cr.unsure?
|
24
|
+
assert_equal 'unknown', cr.to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_unsure
|
28
|
+
cr = Mollom::ContentResponse.new('spam' => 2, 'session_id' => '1', 'quality' => '10')
|
29
|
+
assert cr.unsure?
|
30
|
+
assert !cr.unknown?
|
31
|
+
assert_equal 'unsure', cr.to_s
|
32
|
+
end
|
33
|
+
end
|
data/test/mollom_test.rb
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'mocha'
|
4
|
+
|
5
|
+
require 'mollom'
|
6
|
+
|
7
|
+
class Mollom
|
8
|
+
# Unprivate all methods
|
9
|
+
public :authentication_hash
|
10
|
+
public :server_list
|
11
|
+
public :send_command
|
12
|
+
end
|
13
|
+
|
14
|
+
class TestMollom < Test::Unit::TestCase
|
15
|
+
def setup
|
16
|
+
@mollom = Mollom.new(:private_key => 'xxxxxxxxx', :public_key => 'yyyyyyyyy')
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_initialize
|
20
|
+
assert_equal 'xxxxxxxxx', @mollom.private_key
|
21
|
+
assert_equal 'yyyyyyyyy', @mollom.public_key
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_authentication_hash
|
25
|
+
time = mock
|
26
|
+
time.expects(:strftime).with('%Y-%m-%dT%H:%M:%S.000+0000').returns('2008-04-01T13:54:26.000+0000')
|
27
|
+
Time.stubs(:now).returns(stub(:gmtime => time))
|
28
|
+
hash = @mollom.authentication_hash
|
29
|
+
assert_equal("24qAgAC1v1U+5NbKyrQSp/XKWAI=", hash[:hash])
|
30
|
+
assert_equal('yyyyyyyyy', hash[:public_key])
|
31
|
+
assert_equal('2008-04-01T13:54:26.000+0000', hash[:time])
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_server_list
|
35
|
+
xml_rpc = mock
|
36
|
+
xml_rpc.expects(:call).with('mollom.getServerList', is_a(Hash)).returns(['http://172.16.0.1', 'http://172.16.0.2', 'https://172.16.0.2'])
|
37
|
+
XMLRPC::Client.stubs(:new).with('xmlrpc.mollom.com', '/1.0').returns(xml_rpc)
|
38
|
+
|
39
|
+
assert_equal [{:ip => '172.16.0.1', :proto => 'http'}, {:ip => '172.16.0.2', :proto => 'http'}, {:ip => '172.16.0.2', :proto => 'https'}], @mollom.server_list
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_server_list_force_reload
|
43
|
+
xml_rpc = mock
|
44
|
+
xml_rpc.expects(:call).times(2).with('mollom.getServerList', is_a(Hash)).returns(['http://172.16.0.1', 'http://172.16.0.2', 'https://172.16.0.2'])
|
45
|
+
XMLRPC::Client.stubs(:new).with('xmlrpc.mollom.com', '/1.0').returns(xml_rpc)
|
46
|
+
|
47
|
+
@mollom.server_list
|
48
|
+
@mollom.server_list
|
49
|
+
@mollom.server_list(true)
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_send_command_with_good_server
|
53
|
+
Mollom.any_instance.stubs(:server_list).returns([{:ip => '172.16.0.1', :proto => 'http'}])
|
54
|
+
xml_rpc = mock
|
55
|
+
xml_rpc.expects(:call).with('mollom.testMessage', has_entry(:options => 'foo'))
|
56
|
+
XMLRPC::Client.stubs(:new).with('172.16.0.1', '/1.0').returns(xml_rpc)
|
57
|
+
|
58
|
+
@mollom.send_command('mollom.testMessage', {:options => 'foo'})
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
def test_send_command_with_bad_server
|
63
|
+
Mollom.any_instance.stubs(:server_list).returns([{:ip => '172.16.0.1', :proto => 'http'}, {:ip => '172.16.0.2', :proto => 'http'}])
|
64
|
+
xml_rpc = mock
|
65
|
+
xml_rpc.expects(:call).with('mollom.testMessage', has_entry(:options => 'foo')).raises(XMLRPC::FaultException.new(1200, "Redirect"))
|
66
|
+
xml_rpc2 = mock
|
67
|
+
xml_rpc2.expects(:call).with('mollom.testMessage', has_entry(:options => 'foo'))
|
68
|
+
|
69
|
+
XMLRPC::Client.stubs(:new).with('172.16.0.1', '/1.0').returns(xml_rpc)
|
70
|
+
XMLRPC::Client.stubs(:new).with('172.16.0.2', '/1.0').returns(xml_rpc2)
|
71
|
+
@mollom.send_command('mollom.testMessage', {:options => 'foo'})
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_send_command_with_reload_exception
|
75
|
+
# TODO: Test this
|
76
|
+
@mollom.send_command('mollom.testMessage', {:options => 'foo'})
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_send_command_with_bad_command
|
80
|
+
Mollom.any_instance.stubs(:server_list).returns([{:ip => '172.16.0.1', :proto => 'http'}])
|
81
|
+
xml_rpc = mock
|
82
|
+
xml_rpc.expects(:call).with('mollom.testMessage', has_entry(:options => 'foo')).raises(XMLRPC::FaultException.new(1000, "Fault String"))
|
83
|
+
XMLRPC::Client.stubs(:new).with('172.16.0.1', '/1.0').returns(xml_rpc)
|
84
|
+
|
85
|
+
assert_raise(Mollom::Error) { @mollom.send_command('mollom.testMessage', {:options => 'foo'}) }
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_send_command_with_bad_server_and_no_more_available
|
89
|
+
Mollom.any_instance.stubs(:server_list).returns([{:ip => '172.16.0.1', :proto => 'http'}])
|
90
|
+
xml_rpc = mock
|
91
|
+
xml_rpc.expects(:call).with('mollom.testMessage', has_entry(:options => 'foo')).raises(XMLRPC::FaultException.new(1200, "Redirect"))
|
92
|
+
|
93
|
+
XMLRPC::Client.stubs(:new).with('172.16.0.1', '/1.0').returns(xml_rpc)
|
94
|
+
|
95
|
+
assert_raise(Mollom::NoAvailableServers) { @mollom.send_command('mollom.testMessage', {:options => 'foo'}) }
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_check_content
|
99
|
+
Mollom.any_instance.expects(:send_command).with('mollom.checkContent', :author_ip => '172.16.0.1', :post_body => 'Lorem Ipsum').returns("spam" => 1, "quality" => 0.40, "session_id" => 1)
|
100
|
+
cr = @mollom.check_content(:author_ip => '172.16.0.1', :post_body => 'Lorem Ipsum')
|
101
|
+
assert cr.ham?
|
102
|
+
assert_equal 1, cr.session_id
|
103
|
+
assert_equal 0.40, cr.quality
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_image_captcha
|
107
|
+
Mollom.any_instance.expects(:send_command).with('mollom.getImageCaptcha', :author_ip => '172.16.0.1').returns('url' => 'http://xmlrpc1.mollom.com:80/a9616e6b4cd6a81ecdd509fa624d895d.png', 'session_id' => 'a9616e6b4cd6a81ecdd509fa624d895d')
|
108
|
+
@mollom.image_captcha(:author_ip => '172.16.0.1')
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_audio_captcha
|
112
|
+
Mollom.any_instance.expects(:send_command).with('mollom.getAudioCaptcha', :author_ip => '172.16.0.1').returns('url' => 'http://xmlrpc1.mollom.com:80/a9616e6b4cd6a81ecdd509fa624d895d.mp3', 'session_id' => 'a9616e6b4cd6a81ecdd509fa624d895d')
|
113
|
+
@mollom.audio_captcha(:author_ip => '172.16.0.1')
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_valid_captcha
|
117
|
+
Mollom.any_instance.expects(:send_command).with('mollom.checkCaptcha', :session_id => 'a9616e6b4cd6a81ecdd509fa624d895d', :solution => 'foo').returns(true)
|
118
|
+
@mollom.valid_captcha?(:session_id => 'a9616e6b4cd6a81ecdd509fa624d895d', :solution => 'foo')
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_key_ok
|
122
|
+
Mollom.any_instance.expects(:send_command).with('mollom.verifyKey').returns(true)
|
123
|
+
@mollom.key_ok?
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_statistics
|
127
|
+
Mollom.any_instance.expects(:send_command).with('mollom.getStatistics', :type => 'total_accepted').returns(123)
|
128
|
+
@mollom.statistics(:type => 'total_accepted')
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_send_feedback
|
132
|
+
Mollom.any_instance.expects(:send_command).with('mollom.sendFeedback', :session_id => 1, :feedback => 'profanity')
|
133
|
+
@mollom.send_feedback :session_id => 1, :feedback => 'profanity'
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mollom
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jan De Poorter
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-04-
|
12
|
+
date: 2008-04-04 00:00:00 +02:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -45,10 +45,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
45
45
|
version:
|
46
46
|
requirements: []
|
47
47
|
|
48
|
-
rubyforge_project:
|
48
|
+
rubyforge_project: mollom
|
49
49
|
rubygems_version: 1.0.1
|
50
50
|
signing_key:
|
51
51
|
specification_version: 2
|
52
52
|
summary: Ruby class for easy interfacing with the mollom.com open API for spam detection and content quality assesment.
|
53
|
-
test_files:
|
54
|
-
|
53
|
+
test_files:
|
54
|
+
- test/content_response_test.rb
|
55
|
+
- test/mollom_test.rb
|