public
Description: A mirror of the mephisto code-base
Homepage: http://mephistoblog.com/
Clone URL: git://github.com/halorgium/mephisto.git
Search Repo:
Adding the Viking plugin.

Commit: 2de08dc6e4899791563ddaabce8dbc3f1c7d56da
francois (author)
Mon Mar 10 20:32:38 -0700 2008
commit  5528126ec61fdffc7cb5e6f20769f98876d002f1
tree    594598c7159812e653312a3c19380b4b12899c38
parent  a845a68630cb4c6f3c6827fac5d34709afd047ec
...
 
 
...
1
2
0
@@ -1 +1,3 @@
0
+*.swp
0
+coverage
...
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
0
@@ -1 +1,12 @@
0
+require "rubygems"
0
+require "rake/testtask"
0
+
0
+Rake::TestTask.new do |t|
0
+ t.libs << "test"
0
+ t.test_files = FileList['test/**/*_test.rb']
0
+ t.verbose = true
0
+ t.warning = true
0
+end
0
+
0
+task :default => :test
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
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
0
@@ -1 +1,29 @@
0
+module Viking
0
+ class Error < StandardError; end
0
+
0
+ class << self
0
+ attr_accessor :logger
0
+ attr_accessor :default_engine
0
+ attr_accessor :connect_options
0
+ attr_writer :default_instance
0
+
0
+ def default_instance
0
+ @default_instance ||= connect(default_engine, connect_options)
0
+ end
0
+
0
+ def connect(engine, options)
0
+ require "viking/#{engine}"
0
+ Viking.const_get(engine.to_s.capitalize).new(options)
0
+ end
0
+
0
+ def verified?() default_instance.verified?; end
0
+ def check_article(options = {}) default_instance.check_article(options); end
0
+ def check_comment(options = {}) default_instance.check_comment(options); end
0
+ def mark_as_spam(options = {}) default_instance.mark_as_spam(options); end
0
+ def mark_as_ham(options = {}) default_instance.mark_as_ham(options); end
0
+ def stats() default_instance.stats; end
0
+ end
0
+end
0
+
0
+require 'viking/base'
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
0
@@ -1 +1,134 @@
0
+require 'net/http'
0
+require 'uri'
0
+require 'set'
0
+
0
+# Akismet
0
+#
0
+# Author:: David Czarnecki
0
+# Copyright:: Copyright (c) 2005 - David Czarnecki
0
+# License:: BSD
0
+#
0
+# rewritten to be more rails-like
0
+module Viking
0
+ class Akismet < Base
0
+ class << self
0
+ attr_accessor :valid_responses, :normal_responses, :standard_headers, :host, :port
0
+ end
0
+
0
+ self.host = 'rest.akismet.com'
0
+ self.port = 80
0
+ self.valid_responses = Set.new(['false', ''])
0
+ self.normal_responses = valid_responses.dup << 'true'
0
+ self.standard_headers = {
0
+ 'User-Agent' => 'Viking (Rails Plugin) v0.5',
0
+ 'Content-Type' => 'application/x-www-form-urlencoded'
0
+ }
0
+
0
+ # Create a new instance of the Akismet class
0
+ #
0
+ # :api_key
0
+ # Your Akismet API key
0
+ # :blog
0
+ # The blog associated with your api key
0
+ # :proxy_port
0
+ # :proxy_host
0
+ def initialize(options)
0
+ super
0
+ @verified_key = false
0
+ end
0
+
0
+ # Returns <tt>true</tt> if the API key has been verified, <tt>false</tt> otherwise
0
+ def verified?
0
+ (@verified_key ||= verify_api_key) != :false
0
+ end
0
+
0
+ # This is basically the core of everything. This call takes a number of arguments and characteristics about the submitted content and then returns a thumbs up or thumbs down. Almost everything is optional, but performance can drop dramatically if you exclude certain elements.
0
+ #
0
+ # user_ip (required)
0
+ # IP address of the comment submitter.
0
+ # user_agent (required)
0
+ # User agent information.
0
+ # referrer (note spelling)
0
+ # The content of the HTTP_REFERER header should be sent here.
0
+ # permalink
0
+ # The permanent location of the entry the comment was submitted to.
0
+ # comment_type
0
+ # May be blank, comment, trackback, pingback, or a made up value like "registration".
0
+ # comment_author
0
+ # Submitted name with the comment
0
+ # comment_author_email
0
+ # Submitted email address
0
+ # comment_author_url
0
+ # Commenter URL.
0
+ # comment_content
0
+ # The content that was submitted.
0
+ # Other server enviroment variables
0
+ # In PHP there is an array of enviroment variables called $_SERVER which contains information about the web server itself as well as a key/value for every HTTP header sent with the request. This data is highly useful to Akismet as how the submited content interacts with the server can be very telling, so please include as much information as possible.
0
+ def check_comment(options = {})
0
+ return false if @options[:api_key].nil? || @options[:blog].nil?
0
+ message = call_akismet('comment-check', options)
0
+ {:spam => !self.class.valid_responses.include?(message), :message => message}
0
+ end
0
+
0
+ # This call is for submitting comments that weren't marked as spam but should have been. It takes identical arguments as comment check.
0
+ # The call parameters are the same as for the #commentCheck method.
0
+ def mark_as_spam(options = {})
0
+ return false if @options[:api_key].nil? || @options[:blog].nil?
0
+ {:message => call_akismet('submit-spam', options)}
0
+ end
0
+
0
+ # This call is intended for the marking of false positives, things that were incorrectly marked as spam. It takes identical arguments as comment check and submit spam.
0
+ # The call parameters are the same as for the #commentCheck method.
0
+ def mark_as_ham(options = {})
0
+ return false if @options[:api_key].nil? || @options[:blog].nil?
0
+ {:message => call_akismet('submit-ham', options)}
0
+ end
0
+
0
+ protected
0
+ # Internal call to Akismet. Prepares the data for posting to the Akismet service.
0
+ #
0
+ # akismet_function
0
+ # The Akismet function that should be called
0
+ # user_ip (required)
0
+ # IP address of the comment submitter.
0
+ # user_agent (required)
0
+ # User agent information.
0
+ # referrer (note spelling)
0
+ # The content of the HTTP_REFERER header should be sent here.
0
+ # permalink
0
+ # The permanent location of the entry the comment was submitted to.
0
+ # comment_type
0
+ # May be blank, comment, trackback, pingback, or a made up value like "registration".
0
+ # comment_author
0
+ # Submitted name with the comment
0
+ # comment_author_email
0
+ # Submitted email address
0
+ # comment_author_url
0
+ # Commenter URL.
0
+ # comment_content
0
+ # The content that was submitted.
0
+ # Other server enviroment variables
0
+ # In PHP there is an array of enviroment variables called $_SERVER which contains information about the web server itself as well as a key/value for every HTTP header sent with the request. This data is highly useful to Akismet as how the submited content interacts with the server can be very telling, so please include as much information as possible.
0
+ def call_akismet(akismet_function, options = {})
0
+ http = Net::HTTP.new("#{@options[:api_key]}.#{self.class.host}", self.class.port, @options[:proxy_host], @options[:proxy_port])
0
+ data = options.update(:blog => @options[:blog]).to_query
0
+ http_post(http, akismet_function, data)
0
+ end
0
+
0
+ # Call to check and verify your API key. You may then call the #hasVerifiedKey method to see if your key has been validated.
0
+ def verify_api_key
0
+ return :false if @options[:api_key].nil? || @options[:blog].nil?
0
+ http = Net::HTTP.new(self.class.host, self.class.port, @options[:proxy_host], @options[:proxy_port])
0
+ value = http_post(http, 'verify-key', {:key => @options[:api_key], :blog => @options[:blog]}.to_query)
0
+ @verified_key = (value == "valid") ? true : :false
0
+ end
0
+
0
+ def http_post(http, action, data)
0
+ url = "/1.1/#{action}"
0
+ resp = http.post(url, data, self.class.standard_headers)
0
+ log_request url, data, resp
0
+ resp.body
0
+ end
0
+ end
0
+end
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
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
0
@@ -1 +1,43 @@
0
+module Viking
0
+ class Base
0
+ attr_reader :options
0
+
0
+ def initialize(options)
0
+ @options = options
0
+ end
0
+
0
+ def verified?
0
+ end
0
+
0
+ def check_article(options = {})
0
+ end
0
+
0
+ def check_comment(options = {})
0
+ end
0
+
0
+ def mark_as_spam(options = {})
0
+ end
0
+
0
+ def mark_as_ham(options = {})
0
+ end
0
+
0
+ def stats
0
+ end
0
+
0
+ def self.logger
0
+ Viking.logger
0
+ end
0
+
0
+ def logger
0
+ Viking.logger
0
+ end
0
+
0
+ protected
0
+ def log_request(url, data, response)
0
+ return unless logger
0
+ logger.info("[#{self.class.name}] POST '%s' with %s" % [url, data])
0
+ logger.debug(">> #{response.body.inspect}")
0
+ end
0
+ end
0
+end
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
0
@@ -1 +1,87 @@
0
+require 'net/http'
0
+require 'uri'
0
+require 'yaml'
0
+
0
+module Viking
0
+ class Defensio < Base
0
+ class << self
0
+ attr_accessor :host, :port, :api_version, :standard_headers, :service_type
0
+ end
0
+
0
+ attr_accessor :proxy_port, :proxy_host
0
+ attr_reader :last_response
0
+
0
+ self.service_type = :blog
0
+ self.host = 'api.defensio.com'
0
+ self.api_version = '1.1'
0
+ self.standard_headers = {
0
+ 'User-Agent' => 'Viking (Rails Plugin) v0.5',
0
+ 'Content-Type' => 'application/x-www-form-urlencoded'
0
+ }
0
+
0
+ # Create a new instance of the Akismet class
0
+ #
0
+ # :api_key
0
+ # Your Akismet API key
0
+ # :blog
0
+ # The blog associated with your api key
0
+ # :proxy_port
0
+ # :proxy_host
0
+ def initialize(options)
0
+ super
0
+ @verify_options = false
0
+ end
0
+
0
+ # Returns <tt>true</tt> if the API key has been verified, <tt>false</tt> otherwise
0
+ def verified?
0
+ (@verify_options ||= call_defensio('validate-key'))[:status] == 'success'
0
+ end
0
+
0
+ def check_article(options = {})
0
+ return false if @options[:api_key].nil? || @options[:blog].nil?
0
+ call_defensio 'announce-article', options
0
+ end
0
+
0
+ def check_comment(options = {})
0
+ return false if @options[:api_key].nil? || @options[:blog].nil?
0
+ if options[:article_date].respond_to?(:strftime)
0
+ options[:article_date] = options[:article_date].strftime("%Y/%m/%d")
0
+ end
0
+ call_defensio 'audit-comment', options
0
+ end
0
+
0
+ def mark_as_spam(options = {})
0
+ return false if @options[:api_key].nil? || @options[:blog].nil?
0
+ call_defensio 'report-false-negatives', options
0
+ end
0
+
0
+ def mark_as_ham(options = {})
0
+ return false if @options[:api_key].nil? || @options[:blog].nil?
0
+ call_defensio 'report-false-positives', options
0
+ end
0
+
0
+ def stats
0
+ return false if @options[:api_key].nil? || @options[:blog].nil?
0
+ call_defensio 'get-stats'
0
+ end
0
+
0
+ protected
0
+ def api_url(action)
0
+ URI.escape("/#{self.class.service_type}/#{self.class.api_version}/#{action}/#{@options[:api_key]}.yaml")
0
+ end
0
+
0
+ def call_defensio(action, params = {})
0
+ url = api_url(action)
0
+ data = params.inject({'owner-url' => @options[:blog] || @options[:owner_url]}) do |memo, (key, value)|
0
+ memo[key.to_s.dasherize] = value
0
+ memo
0
+ end.to_query
0
+ http = Net::HTTP.new(self.class.host, self.class.port, @options[:proxy_host], @options[:proxy_port])
0
+ resp = http.post(url, data, self.class.standard_headers)
0
+ log_request url, data, resp
0
+ data = YAML.load(resp.body)
0
+ (data.respond_to?(:key?) && data.key?('defensio-result')) ? data['defensio-result'].symbolize_keys : {:data => resp.body, :status => 'fail'}
0
+ end
0
+ end
0
+end
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
0
@@ -1 +1,170 @@
0
+require 'test/unit'
0
+require 'cgi'
0
+require 'rubygems'
0
+require 'active_support'
0
+require 'mocha'
0
+require 'test/spec'
0
+
0
+$LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
0
+
0
+unless Hash.public_instance_methods.any? { |m| m =~ /to_query/ }
0
+ class Object
0
+ def to_param #:nodoc:
0
+ to_s
0
+ end
0
+
0
+ def to_query(key) #:nodoc:
0
+ "#{CGI.escape(key.to_s)}=#{CGI.escape(to_param.to_s)}"
0
+ end
0
+ end
0
+
0
+ class Array
0
+ def to_query(key) #:nodoc:
0
+ collect { |value| value.to_query("#{key}[]") } * '&'
0
+ end
0
+ end
0
+
0
+ class Hash
0
+ def to_query(namespace = nil)
0
+ collect do |key, value|
0
+ value.to_query(key)
0
+ end.sort * '&'
0
+ end
0
+ end
0
+
0
+ class String
0
+ def dasherize
0
+ gsub(/_/, '-')
0
+ end
0
+ end
0
+end
0
+require 'viking'
0
+
0
+context "Viking Connection" do
0
+ specify "should load akismet engine" do
0
+ Viking.connect(:akismet, :api_key => 'foo', :blog => 'bar').class.should == Viking::Akismet
0
+ end
0
+
0
+ specify "should set default engine" do
0
+ begin
0
+ Viking.default_engine = :akismet
0
+ Viking.connect_options = { :api_key => 'foo', :blog => 'bar' }
0
+ Viking.default_instance.class.should == Viking::Akismet
0
+ Viking.default_instance.options.should == Viking.connect_options
0
+ ensure
0
+ Viking.default_engine = nil
0
+ Viking.connect_options = nil
0
+ Viking.default_instance = nil
0
+ end
0
+ end
0
+end
0
+
0
+context "Akismet" do
0
+ setup do
0
+ @viking = Viking.connect :akismet, :api_key => 'foo', :blog => 'bar'
0
+ end
0
+
0
+ specify "should verify api key" do
0
+ mock_akismet("/1.1/verify-key", {:key => :foo, :blog => :bar}).returns(stub(:body => 'valid'))
0
+ @viking.verified?.should == true # #verified? is called twice to make sure #verify_api_key is not called twice
0
+ @viking.verified?.should == true
0
+ end
0
+
0
+ specify "should show as unverified with api key" do
0
+ mock_akismet("/1.1/verify-key", {:key => :foo, :blog => :bar}).returns(stub(:body => 'invalid'))
0
+ @viking.verified?.should == false
0
+ @viking.verified?.should == false
0
+ end
0
+
0
+ specify "should check comment is valid" do
0
+ mock_akismet("/1.1/comment-check").returns(stub(:body => 'false'))
0
+ @viking.check_comment.should == {:message => 'false', :spam => false}
0
+ end
0
+
0
+ specify "should check comment is spam" do
0
+ mock_akismet("/1.1/comment-check").returns(stub(:body => 'blah'))
0
+ @viking.check_comment.should == {:message => 'blah', :spam => true}
0
+ end
0
+
0
+ specify "should mark comment as spam" do
0
+ mock_akismet("/1.1/submit-spam").returns(stub(:body => 'blah'))
0
+ @viking.mark_as_spam.should == {:message => 'blah'}
0
+ end
0
+
0
+ specify "should mark comment as ham" do
0
+ mock_akismet("/1.1/submit-ham").returns(stub(:body => 'blah'))
0
+ @viking.mark_as_ham.should == {:message => 'blah'}
0
+ end
0
+
0
+ protected
0
+ def mock_akismet(url, options = {})
0
+ Net::HTTP.any_instance.expects(:post).with(url, options.merge(:blog => :bar).to_query, Viking::Akismet.standard_headers)
0
+ end
0
+end
0
+
0
+context "Defensio" do
0
+ setup do
0
+ @viking = Viking.connect :defensio, :api_key => 'foo', :blog => 'bar'
0
+ end
0
+
0
+ specify "should build correct action url" do
0
+ @viking.send(:api_url, 'foo').should == '/blog/1.1/foo/foo.yaml'
0
+ end
0
+
0
+ specify "should verify api key" do
0
+ mock_defensio("validate-key", {}, {'status' => 'success'})
0
+ @viking.verified?.should == true # #verified? is called twice to make sure #verify_api_key is not called twice
0
+ @viking.verified?.should == true
0
+ end
0
+
0
+ specify "should show as unverified with api key" do
0
+ mock_defensio("validate-key", {}, {'status' => 'asdf'})
0
+ @viking.verified?.should == false
0
+ @viking.verified?.should == false
0
+ end
0
+
0
+ specify "should announce article" do
0
+ mock_defensio("announce-article", {}, {'message' => 'whatever'})
0
+ @viking.check_article.should == {:message => 'whatever'}
0
+ end
0
+
0
+ specify "should check comment is valid" do
0
+ mock_defensio("audit-comment", {}, {'spam' => false, 'spaminess' => 0.1})
0
+ @viking.check_comment.should == {:spaminess => 0.1, :spam => false}
0
+ end
0
+
0
+ specify "should mark comment as spam" do
0
+ mock_defensio("report-false-negatives", {:user_ip => '123'}, {'message' => 'blah'})
0
+ @viking.mark_as_spam(:user_ip => '123').should == {:message => 'blah'}
0
+ end
0
+
0
+ specify "should mark comment as ham" do
0
+ mock_defensio("report-false-positives", {}, {'message' => 'blah'})
0
+ @viking.mark_as_ham.should == {:message => 'blah'}
0
+ end
0
+
0
+ specify "should recover from bad defensio message" do
0
+ data = {'owner-url' => 'bar'}.to_query
0
+ response = {'nothing' => '1'}.to_yaml
0
+ Net::HTTP.any_instance.expects(:post).with(@viking.send(:api_url, 'announce-article'), data, Viking::Defensio.standard_headers).returns(stub(:body => response))
0
+ @viking.check_article.should == {:data => response, :status => 'fail'}
0
+ end
0
+
0
+ specify "should recover from bad yaml response" do
0
+ data = {'owner-url' => 'bar'}.to_query
0
+ response = 'nothing'
0
+ Net::HTTP.any_instance.expects(:post).with(@viking.send(:api_url, 'announce-article'), data, Viking::Defensio.standard_headers).returns(stub(:body => response))
0
+ @viking.check_article.should == {:data => response, :status => 'fail'}
0
+ end
0
+
0
+ protected
0
+ def mock_defensio(action, options = {}, response = {})
0
+ data = options.inject({'owner-url' => 'bar'}) do |memo, (key, value)|
0
+ memo[key.to_s.dasherize] = value
0
+ memo
0
+ end.to_query
0
+ response = {'defensio-result' => response.stringify_keys}.to_yaml
0
+ Net::HTTP.any_instance.expects(:post).with(@viking.send(:api_url, action), data, Viking::Defensio.standard_headers).returns(stub(:body => response))
0
+ end
0
+end

Comments

    No one has commented yet.