radiant-comments-extension 0.0.6 → 0.0.8

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.
Files changed (47) hide show
  1. data/.gitignore +1 -1
  2. data/CHANGELOG +6 -0
  3. data/Gemfile +4 -0
  4. data/README.rdoc +9 -0
  5. data/Rakefile +0 -16
  6. data/TODO +0 -1
  7. data/app/controllers/admin/comments_controller.rb +1 -5
  8. data/app/controllers/comments_controller.rb +46 -4
  9. data/app/models/akismet_spam_filter.rb +1 -1
  10. data/app/models/comment.rb +7 -1
  11. data/app/models/mollom_spam_filter.rb +17 -7
  12. data/app/models/spam_filter.rb +1 -0
  13. data/app/views/admin/comments/_comment.html.haml +26 -0
  14. data/app/views/admin/comments/_form.html.haml +37 -0
  15. data/app/views/admin/comments/edit.html.haml +4 -0
  16. data/app/views/admin/comments/index.html.haml +57 -0
  17. data/app/views/admin/pages/{_comments.rhtml → _comments.html.haml} +0 -0
  18. data/app/views/admin/pages/_edit_comments_enabled.html.haml +7 -0
  19. data/app/views/admin/pages/_index_head_view_comments.html.haml +1 -0
  20. data/app/views/admin/pages/_index_view_comments.html.haml +7 -0
  21. data/comments_extension.rb +11 -27
  22. data/config/locales/en.yml +26 -0
  23. data/config/locales/nl.yml +26 -0
  24. data/config/routes.rb +16 -0
  25. data/db/migrate/002_create_snippets.rb +4 -4
  26. data/lib/comment_page_extensions.rb +15 -2
  27. data/lib/comment_tags.rb +55 -0
  28. data/lib/radiant-comments-extension.rb +2 -0
  29. data/lib/radiant-comments-extension/version.rb +3 -0
  30. data/public/stylesheets/admin/comments.css +21 -29
  31. data/radiant-comments-extension.gemspec +8 -117
  32. data/spec/controllers/page_postback_spec.rb +2 -1
  33. data/spec/models/comment_spec.rb +7 -23
  34. data/spec/models/mollom_spam_filter_spec.rb +5 -0
  35. metadata +30 -32
  36. data/VERSION +0 -1
  37. data/app/views/admin/comments/_comment.rhtml +0 -34
  38. data/app/views/admin/comments/_form.rhtml +0 -36
  39. data/app/views/admin/comments/edit.rhtml +0 -5
  40. data/app/views/admin/comments/index.rhtml +0 -55
  41. data/app/views/admin/pages/_edit_comments_enabled.rhtml +0 -8
  42. data/app/views/admin/pages/_index_head_view_comments.rhtml +0 -1
  43. data/app/views/admin/pages/_index_view_comments.rhtml +0 -11
  44. data/app/views/comments/_comment.rhtml +0 -1
  45. data/app/views/comments/_form.rhtml +0 -23
  46. data/app/views/comments/_new.rhtml +0 -5
  47. data/lib/mollom.rb +0 -246
data/.gitignore CHANGED
@@ -1,3 +1,3 @@
1
1
  .DS_Store
2
2
  .svn
3
- pkg/*
3
+ *.gem
data/CHANGELOG CHANGED
@@ -1,5 +1,11 @@
1
1
  = Git
2
2
 
3
+ = 0.0.7
4
+
5
+ * Updated to use of the Mollom gem i.o. local copy [Benny Degezelle]
6
+ * Updated to use mollom to it's full potential (show CAPTCHA when unsure) [Benny Degezelle]
7
+ * Added r:comments:spam_message which only expands if a posted comment is thought to be spam [Benny Degezelle]
8
+
3
9
  = 0.0.6
4
10
 
5
11
  * Added spam_answer_tag for simple spam protection or CAPTCHA
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source :gemcutter
2
+
3
+ # Specify your gem's dependencies in comments-gem.gemspec
4
+ gemspec
data/README.rdoc CHANGED
@@ -15,6 +15,7 @@ If you want to contribute features or fixes please write your specs and code and
15
15
  * Requires will_paginate Rails plugin (http://github.com/mislav/will_paginate/tree/master)
16
16
  * Requires fastercsv 1.2.3 or greater.
17
17
  * Requires sanitize 1.0.8 or greater.
18
+ * Requires mollom 0.2.2 or greater.
18
19
 
19
20
  == Installation
20
21
 
@@ -24,6 +25,14 @@ To install Comments, run:
24
25
 
25
26
  This _WILL_ delete any snippets named 'comment', 'comments' and 'comment_form' if these exist.
26
27
 
28
+ If you are upgrading from a previous version with out the sanitizer run:
29
+
30
+ rake radiant:extensions:comments:initialize
31
+
32
+ or if you want to clean up your initializer for the sanitize gem run:
33
+
34
+ rake radiant:extensions:comments:forced_initialize
35
+
27
36
  == More Help
28
37
 
29
38
  See the included HELP docs here or read them in your Radiant interface with the Help extension installed.
data/Rakefile CHANGED
@@ -1,19 +1,3 @@
1
- begin
2
- require 'jeweler'
3
- Jeweler::Tasks.new do |gem|
4
- gem.name = "radiant-comments-extension"
5
- gem.summary = %Q{Comments Extension for Radiant CMS}
6
- gem.description = %Q{Adds blog-like comment functionality to Radiant.}
7
- gem.email = "jim@saturnflyer.com"
8
- gem.homepage = "http://github.com/saturnflyer/radiant-comments-extension"
9
- gem.authors = ['Jim Gay', 'Ryan Heneise', 'Sean Cribbs','John Muhl', 'Sven Schwyn', 'Gerrit Kaiser', 'Stephen Lombardo', 'Benny Degezelle', 'Frank Louwers', 'Michael Hale', 'Nathaniel Talbott', 'John Croisant', 'Jon Leighton', 'Witter Cheng', 'Keith Bingman']
10
- gem.add_development_dependency "radiant"
11
- # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
12
- end
13
- rescue LoadError
14
- puts "Jeweler (or a dependency) not available. This is only required if you plan to package dashboard as a gem."
15
- end
16
-
17
1
  # Determine where the RSpec plugin is by loading the boot
18
2
  unless defined? RADIANT_ROOT
19
3
  ENV["RAILS_ENV"] = "test"
data/TODO CHANGED
@@ -3,4 +3,3 @@
3
3
  * Write better specs.
4
4
  * Move tests to specs.
5
5
  * Add user notification message when a comment is posted.
6
- * captcha mollom implementation
@@ -114,11 +114,7 @@ class Admin::CommentsController < ApplicationController
114
114
  end
115
115
 
116
116
  def clear_cache
117
- if defined?(ResponseCache)
118
- ResponseCache.instance.clear
119
- else
120
- Radiant::Cache.clear
121
- end
117
+ Radiant::Cache.clear
122
118
  end
123
119
 
124
120
  def clear_single_page_cache(comment)
@@ -24,13 +24,42 @@ class CommentsController < ApplicationController
24
24
  end
25
25
  end
26
26
 
27
- flash[:selected_comment] = comment.id
28
- redirect_to "#{@page.url}comments#comment-#{comment.id}"
27
+ if comment.approved?
28
+ redirect_to "#{@page.url}comments#comment-#{comment.id}"
29
+ elsif Comment.spam_filter == MollomSpamFilter && MollomSpamFilter.mollom_response(comment).to_s == 'unsure'
30
+ set_up_page_with_captcha(comment)
31
+ render :text => @page.render and return
32
+ else
33
+ @page.posted_comment_is_spam = true
34
+ #comment.destroy
35
+ render :text => @page.render
36
+ end
29
37
  rescue ActiveRecord::RecordInvalid
38
+ if comment.errors.on(:spam_answer)
39
+ @page.posted_comment_is_spam = true
40
+ end
30
41
  @page.last_comment = comment
31
42
  render :text => @page.render
32
- # rescue Comments::MollomUnsure
33
- #flash, en render :text => @page.render
43
+ rescue SpamFilter::Spam
44
+ @page.posted_comment_is_spam = true
45
+ #comment.destroy
46
+ render :text => @page.render
47
+ end
48
+
49
+ def solve_captcha
50
+ comment = Comment.find_by_mollom_id(params[:comment_mollom_id])
51
+ answer = params[:captcha_answer]
52
+ mollom = Comment.spam_filter.mollom
53
+ if mollom.valid_captcha? :session_id => comment.mollom_id, :solution => answer
54
+ comment.approve!
55
+ redirect_to "#{@page.url}comments#comment-#{comment.id}"
56
+ else
57
+ set_up_page_with_captcha(comment)
58
+ render :text => @page.render
59
+ end
60
+ rescue Mollom::Error # when you don't provide 'correct' or 'incorrect' in mollom developer mode
61
+ set_up_page_with_captcha(comment)
62
+ render :text => @page.render
34
63
  end
35
64
 
36
65
  private
@@ -55,5 +84,18 @@ class CommentsController < ApplicationController
55
84
  end
56
85
  end
57
86
  end
87
+
88
+ def set_up_page_with_captcha(comment)
89
+ mollom = Comment.spam_filter.mollom
90
+ if comment.mollom_id.nil?
91
+ captcha = mollom.image_captcha
92
+ comment.update_attribute(:mollom_id, captcha['session_id'])
93
+ else
94
+ captcha = mollom.image_captcha(:session_id => comment.mollom_id)
95
+ end
96
+ @page.last_comment = comment
97
+ @page.captcha_url = captcha['url']
98
+ @page.comment_mollom_id = @page.captcha_url[/\/([a-z0-9]*).png/, 1]
99
+ end
58
100
 
59
101
  end
@@ -10,7 +10,7 @@ class AkismetSpamFilter < SpamFilter
10
10
 
11
11
  def approved?(comment)
12
12
  (akismet.valid? && ham?(comment)) || raise(SpamFilter::Spam)
13
- rescue
13
+ rescue StandardError, TimeoutError
14
14
  # Spam and anything raised by Net::HTTP, e.g. Errno, Timeout stuff
15
15
  false
16
16
  end
@@ -1,4 +1,5 @@
1
1
  require 'digest/md5'
2
+ require 'sanitize'
2
3
  class Comment < ActiveRecord::Base
3
4
  belongs_to :page, :counter_cache => true
4
5
 
@@ -35,8 +36,12 @@ class Comment < ActiveRecord::Base
35
36
  self.referrer = request.env['HTTP_REFERER']
36
37
  end
37
38
 
39
+ def is_ham?
40
+ spam_filter.valid?(self)
41
+ end
42
+
38
43
  def auto_approve?
39
- Radiant::Config['comments.auto_approve'] == "true" && spam_filter.approved?(self)
44
+ Radiant::Config['comments.auto_approve'] == "true" && is_ham?
40
45
  end
41
46
 
42
47
  def unapproved?
@@ -75,6 +80,7 @@ class Comment < ActiveRecord::Base
75
80
 
76
81
  def auto_approve
77
82
  self.approved_at = Time.now if auto_approve?
83
+ true
78
84
  end
79
85
 
80
86
  def apply_filter
@@ -8,9 +8,14 @@ class MollomSpamFilter < SpamFilter
8
8
  !Radiant::Config['comments.mollom_publickey'].blank?
9
9
  end
10
10
 
11
+ def valid?(comment)
12
+ approved?(comment)
13
+ rescue SpamFilter::Unsure
14
+ end
15
+
11
16
  def approved?(comment)
12
17
  (mollom.key_ok? && ham?(comment)) || raise(SpamFilter::Spam)
13
- rescue Mollom::Error, SpamFilter::Spam
18
+ rescue Mollom::Error, SpamFilter::Spam, TimeoutError
14
19
  false
15
20
  end
16
21
 
@@ -32,19 +37,24 @@ class MollomSpamFilter < SpamFilter
32
37
  end
33
38
  end
34
39
 
35
- private
36
- def ham?(comment)
37
- response = mollom.check_content(
40
+ def mollom_response(comment)
41
+ mollom.check_content(
38
42
  :author_name => comment.author, # author name
39
43
  :author_mail => comment.author_email, # author email
40
44
  :author_url => comment.author_url, # author url
41
- :post_body => comment.content # comment text
45
+ :post_body => comment.content, # comment text
46
+ :author_ip => comment.author_ip
42
47
  )
43
- comment.mollom_id = response.session_id
48
+ end
49
+
50
+ private
51
+
52
+ def ham?(comment)
53
+ response = mollom_response(comment)
44
54
  save_mollom_servers
45
55
  response.ham?
46
56
  end
47
-
57
+
48
58
  def save_mollom_servers
49
59
  Rails.cache.write('MOLLOM_SERVER_CACHE', mollom.server_list.to_yaml) if mollom.key_ok?
50
60
  rescue Mollom::Error #TODO: something with this error...
@@ -40,4 +40,5 @@ class SpamFilter
40
40
  end
41
41
 
42
42
  class Spam < ::StandardError; end
43
+ class Unsure < ::StandardError; end
43
44
  end
@@ -0,0 +1,26 @@
1
+ %tr{:id => dom_id(comment), :class => "comment comment-#{comment.ap_status}"}
2
+ %td.content{:title => comment.content.size >= 70 ? t('click_to_toggle') : "" }
3
+ %blockquote.short= escape_once(truncate(comment.content, :length => 70))
4
+ - if comment.content.size >= 70
5
+ %blockquote.expanded{:style => "display:none"}
6
+ = escape_once(comment.content)
7
+ %td.date-column
8
+ = comment.created_at.strftime("%b %e, %Y at %I:%M%p")
9
+ %td.author-column
10
+ = escape_once(comment.author)
11
+ - unless comment.author_email.blank?
12
+ = mail_to(comment.author_email, image_tag("admin/email.png"))
13
+ - unless comment.author_url.blank?
14
+ = link_to(image_tag("admin/link.png"), comment.author_url)
15
+ - unless @page
16
+ %td.page-column
17
+ = link_to truncate(comment.page.title, :length => 40), comment.page.url, :class => 'view-page'
18
+ = link_to image_tag("admin/page_white_edit.png"), edit_admin_page_path(comment.page), :title => t('edit_page')
19
+ %td.controls-column
20
+ - if comment.approved?
21
+ = link_to(image_tag('admin/error.png'), unapprove_admin_comment_path(comment), :method => :put, :title => t('unapprove_comment'))
22
+ - else
23
+ = link_to(image_tag('admin/accept.png'), approve_admin_comment_path(comment), :title => t('approve_comment'), :method => :put)
24
+
25
+ = link_to image_tag("admin/delete.png"), admin_comment_path(comment), :method => :delete, :confirm => t('are_you_sure_you_want_to_delete_this_comment'), :title => t('delete_comment')
26
+ = link_to image_tag("admin/comment_edit.png"), edit_admin_comment_path(comment), :title => t('edit_comment')
@@ -0,0 +1,37 @@
1
+ - if Comment.spam_filter == SimpleSpamFilter
2
+ %div{:style => "display:none"}
3
+ = f.hidden_field :spam_answer, :value => "hemidemisemiquaver"
4
+ = f.hidden_field :valid_spam_answer, :value => Digest::MD5.hexdigest("hemidemisemiquaver")
5
+
6
+ #comment_form_container.form-area
7
+ .set
8
+ %p.title
9
+ = f.label :author, t('author')
10
+ = f.text_field :author
11
+ %p
12
+ = f.label :author_url, t('url')
13
+ = f.text_field :author_url
14
+ %p
15
+ = f.label :author_email, t('email')
16
+ = f.text_field :author_email
17
+ %p
18
+ %label{:for => "comment_content"}= t('comment')
19
+ %br/
20
+ = f.text_area :content, :rows => 10, :cols => 72, :class => "textarea"
21
+ %p
22
+ %label{:for => "comment_filter_id"}= t('filter')
23
+ = f.select :filter_id, [['<none>', '']] + TextFilter.descendants.map { |s| s.filter_name }.sort
24
+ %p
25
+ Referred by:
26
+ = f.object.referrer
27
+ %p
28
+ Browser:
29
+ = f.object.user_agent
30
+ %p
31
+ Author's IP Address:
32
+ = f.object.author_ip
33
+
34
+ %p.buttons
35
+ = save_model_button(@comment)
36
+ = t('or')
37
+ = link_to t('cancel'), :back
@@ -0,0 +1,4 @@
1
+ %h1= "#{t('edit_comment_on')} #{escape_once(@comment.page.title)}"
2
+
3
+ - form_for [:admin, @comment] do |f|
4
+ = render :partial => "form", :locals => {:f => f}
@@ -0,0 +1,57 @@
1
+ - content_for :page_scripts do
2
+ :plain
3
+ document.observe('dom:loaded', function(){
4
+ Event.addBehavior({
5
+ 'tr.comment td.content': function(event){
6
+ $(this).observe('click', function(event){
7
+ if($(this).down('blockquote.expanded')){
8
+ $(this).down('blockquote.expanded').toggle();
9
+ $(this).down('blockquote.short').toggle();
10
+ }
11
+ event.stop();
12
+ });
13
+ }
14
+ });
15
+ });
16
+
17
+ - include_stylesheet 'admin/comments'
18
+
19
+ .outset
20
+ #filters
21
+ %ul.comment-nav
22
+ - if @page
23
+ %li
24
+ = "#{@page.comments.count.to_s} #{t("comment_states.#{params[:status]}")} " if params[:status]
25
+ = "#{pluralize(@page.comments.count, 'Comment')} on #{link_to @page.title, edit_admin_page_path(@page)}"
26
+ %li.all
27
+ = link_or_span_unless_current(t('comment_states.all'), :status => 'all', :page_id => params[:page_id])
28
+ %li.approved
29
+ = link_or_span_unless_current(t('comment_states.approved'), :status => "approved", :page_id => params[:page_id])
30
+ %li.unapproved
31
+ = link_or_span_unless_current(t('comment_states.unapproved'), :status => "unapproved", :page_id => params[:page_id])
32
+
33
+
34
+ #comments_table
35
+ %table#comments.index
36
+ %thead
37
+ %tr
38
+ %th= t('content')
39
+ %th= t('date_string')
40
+ %th= t('author')
41
+ - unless @page
42
+ %th= t('page')
43
+ %th= t('actions')
44
+ %tbody
45
+ = render(:partial => "comment", :collection => @comments) || %Q[<tr><td class="note" colspan="#{@page ? 4 : 5}">No comments</td></tr>]
46
+ %p
47
+ %small.notice
48
+ = Comment.spam_filter.message
49
+
50
+
51
+ #actions
52
+ = will_paginate @comments
53
+ %ul
54
+ %li
55
+ = link_to "#{image('table_save')} #{t('download_csv')}", :format => :csv
56
+ %li
57
+ = link_to "#{image('comments_delete')} #{t('delete_unapproved')}", destroy_unapproved_admin_comments_url, :class => 'delete-unapproved', :method => :delete, :confirm => 'Is it OK to delete ALL Unapproved Comments?'
@@ -0,0 +1,7 @@
1
+ %p{:style => "clear:left"}
2
+ %label{:for => "page_enable_comments"}
3
+ = check_box "page", "enable_comments"
4
+ = t('allow_comments_on_page')
5
+ - unless @page.new_record? or @page.comments_count < 1
6
+ %small
7
+ = link_to t('currently_x_view_comments', :count => @page.comments_count), admin_page_comments_path(:page_id => @page.id)
@@ -0,0 +1 @@
1
+ %th.comments= t('comments')
@@ -0,0 +1,7 @@
1
+ %td.comment_link
2
+ - if page.respond_to?('enable_comments')
3
+ %small
4
+ - if page.enable_comments
5
+ = link_to "#{page.comments_count} comments", admin_page_comments_path(:page_id => page.id)
6
+ - else
7
+ = link_to "Enable", admin_page_enable_comments_path(:page_id => page.id), :method => :put
@@ -1,28 +1,15 @@
1
+ require File.expand_path("../lib/radiant-comments-extension/version", __FILE__)
1
2
  class CommentsExtension < Radiant::Extension
2
- version "#{File.read(File.expand_path(File.dirname(__FILE__)) + '/VERSION')}"
3
+ version RadiantCommentsExtension::VERSION
3
4
  description "Adds blog-like comments and comment functionality to pages."
4
5
  url "http://github.com/saturnflyer/radiant-comments"
5
-
6
- define_routes do |map|
7
- map.namespace :admin do |admin|
8
- admin.connect 'comments/:status', :controller => 'comments', :status => 'unapproved', :conditions => { :method => :get }, :requirements => { :status => /all|unapproved|approved/ }
9
- admin.connect 'comments/:status.:format', :controller => 'comments', :status => /all|approved|unapproved/, :conditions => { :method => :get }
10
- admin.resources :comments, :member => { :remove => :get, :approve => :put, :unapprove => :put }, :collection => {:destroy_unapproved => :delete}
11
- admin.page_enable_comments '/pages/:page_id/comments/enable', :controller => 'comments', :action => 'enable', :conditions => {:method => :put}
12
- end
13
- map.with_options(:controller => 'admin/comments') do |comments|
14
- comments.connect 'admin/pages/:page_id/comments/:status', :status => /all|approved|unapproved/, :conditions => { :method => :get }
15
- comments.connect 'admin/pages/:page_id/comments/:status.:format', :status => /all|approved|unapproved/, :conditions => { :method => :get }
16
- comments.admin_page_comments 'admin/pages/:page_id/comments/:action'
17
- comments.admin_page_comment 'admin/pages/:page_id/comments/:id/:action'
18
- end
19
- # This needs to be last, otherwise it hoses the admin routes.
20
- map.resources :comments, :name_prefix => "page_", :path_prefix => "*url", :controller => "comments"
6
+
7
+ extension_config do |config|
8
+ config.gem 'sanitize'
9
+ config.gem 'mollom'
21
10
  end
22
11
 
23
12
  def activate
24
- require 'sanitize'
25
-
26
13
  Dir["#{File.dirname(__FILE__)}/app/models/*_filter.rb"].each do |file|
27
14
  require file
28
15
  end
@@ -37,14 +24,11 @@ class CommentsExtension < Radiant::Extension
37
24
  admin.page.index.add :sitemap_head, "index_head_view_comments"
38
25
  admin.page.index.add :node, "index_view_comments"
39
26
  end
40
-
41
- if self.respond_to? :tab
42
- tab "Content" do
43
- add_item('Comments', '/admin/comments')
44
- end
45
- else
46
- admin.tabs.add "Comments", "/admin/comments", :visibility => [:all]
47
- end
27
+
28
+ tab "Content" do
29
+ add_item("Comments", "/admin/comments")
30
+ end.
31
+
48
32
  require "fastercsv"
49
33
 
50
34
  ActiveRecord::Base.class_eval do