mollom 0.1 → 0.1.1

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.
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 assesment.
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 keypair from Mollom (on http://www.mollom.com), you can start using this class.
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 'lib/mollom'
17
+ require 'rubygems'
18
+ require 'mollom'
10
19
 
11
- m = Mollom.new(:private_key => 'azkaozdkoakdzkodazdz', :public_key => '34342ikdiozeezioez')
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 => "Mollem is an open API for spam detection and content quality assessment.",
23
+ :post_body => "Lorem Ipsum dolor...",
15
24
  :author_name => 'Jan De Poorter',
16
25
  :author_url => 'http://blog.defv.be')
17
- if content.unsure? or content.spam?
18
- puts "Captcha: " + m.image_captcha(:session_id => content.session_id)["url"]
19
- print "Captcha is: "
20
- puts m.check_captcha(:session_id => content.session_id, :solution => STDIN.gets.chomp)
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
- # TO IMPLEMENT
129
+ # we take this one out of our loop
130
+ raise
126
131
  when Errors::Redirect
127
132
  next
128
133
  else
129
- raise
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
- # Mollom prepends 'http://' to the IP.. Ruby doesn't like that
138
- @server_list ||= XMLRPC::Client.new("xmlrpc.mollom.com", "/#{API_VERSION}").call('mollom.getServerList', authentication_hash).collect { |s| s.sub('http://', '') }
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
- OpenSSL::HMAC.digest(OpenSSL::Digest::SHA1.new, @private_key, now)
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
@@ -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: "0.1"
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-01 00:00:00 +02:00
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