Commit 045a4ac47f169d7e8f6204275daa5d303122ac60

Authored by Antonio Terceiro
1 parent 6aa80262

First version of the Spaminator™

(not tested yet)
plugins/anti_spam/lib/anti_spam_plugin/spaminator.rb 0 → 100644
@@ -0,0 +1,106 @@ @@ -0,0 +1,106 @@
  1 +require 'benchmark'
  2 +
  3 +class AntiSpamPlugin::Spaminator
  4 +
  5 + class << self
  6 + def run(environment)
  7 + instance = new(environment)
  8 + instance.run
  9 + end
  10 +
  11 + def benchmark(environment)
  12 + puts Benchmark.measure { run(environment) }
  13 + end
  14 + end
  15 +
  16 +
  17 + def initialize(environment)
  18 + @environment = environment
  19 + end
  20 +
  21 + def run
  22 + start_time = Time.now
  23 +
  24 + process_all_comments
  25 + process_all_people
  26 + process_people_without_network
  27 +
  28 + finish(start_time)
  29 + end
  30 +
  31 + protected
  32 +
  33 + def finish(start_time)
  34 + @environment.settings[:spaminator_last_run] = start_time
  35 + @environment.save!
  36 + end
  37 +
  38 + def conditions(table)
  39 + last_run = @environment.settings[:spaminator_last_run]
  40 + if last_run
  41 + ["profiles.environment_id = ? AND #{table}.created_at > ?", @environment.id, last_run]
  42 + else
  43 + [ "profiles.environment_id = ?", @environment.id]
  44 + end
  45 + end
  46 +
  47 + def process_all_comments
  48 + puts 'Processing comments ...'
  49 + i = 0
  50 + Comment.joins("JOIN articles ON (comments.source_id = articles.id AND comments.source_type = 'Article') JOIN profiles ON (profiles.id = articles.profile_id)").where(conditions(:comments)).find_each do |comment|
  51 + puts "Comment #{i += 1}"
  52 + process_comment(comment)
  53 + end
  54 + end
  55 +
  56 + def process_all_people
  57 + puts 'Processing people ...'
  58 + i = 0
  59 + Person.where(conditions(:profiles)).find_each do |person|
  60 + puts "Person #{i += 1}"
  61 + process_person(person)
  62 + end
  63 + end
  64 +
  65 + def process_comment(comment)
  66 + comment.check_for_spam
  67 +
  68 + # TODO several comments with the same content:
  69 + # → disable author
  70 + # → mark all of them as spam
  71 + end
  72 +
  73 + def process_person(person)
  74 + # person is author of more than 2 comments marked as spam
  75 + # → burn
  76 + #
  77 + number_of_spam_comments = Comment.spam.where(author_id => person.id).count
  78 + if number_of_spam_comments > 2
  79 + mark_as_spammer(person)
  80 + end
  81 + end
  82 +
  83 + def process_people_without_network
  84 + # people who signed up more than one month ago, have no friends and <= 1
  85 + # communities
  86 + #
  87 + # → burn
  88 + # → mark their comments as spam
  89 + #
  90 + Person.where(:environment_id => @environment.id).where(['created_at < ?', Time.now - 1.month]).find_each do |person|
  91 + number_of_friends = person.friends.count
  92 + number_of_communities = person.communities.count
  93 + if number_of_friends == 0 && number_of_communities <= 1
  94 + mark_as_spammer(person)
  95 + Comment.where(:author_id => person.id).find_each do |comment|
  96 + comment.spam!
  97 + end
  98 + end
  99 + end
  100 + end
  101 +
  102 + def mark_as_spammer(person)
  103 + person.disable
  104 + end
  105 +
  106 +end
plugins/anti_spam/test/unit/anti_spam_plugin/spaminator_test.rb 0 → 100644
@@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
  1 +require 'test_helper'
  2 +
  3 +class AntiSpamPluginSpaminatorTest < ActiveSupport::TestCase
  4 +
  5 + def setup
  6 + @environment = Environment.new
  7 + @environment.id = 99
  8 + @spaminator = AntiSpamPlugin::Spaminator.new(@environment)
  9 + @spaminator.stubs(:puts)
  10 + @now = Time.now
  11 + Time.stubs(:now).returns(@now)
  12 + end
  13 +
  14 + should 'search everything in the first run' do
  15 + assert_equal(['profiles.environment_id = ?',99], @spaminator.send(:conditions, nil))
  16 + end
  17 +
  18 + should 'search using recorded last date' do
  19 + @environment.settings[:spaminator_last_run] = @now
  20 + assert_equal(['profiles.environment_id = ? AND table.created_at > ?', 99, @now], @spaminator.send(:conditions, 'table'))
  21 + end
  22 +
  23 + should 'record time of last run in environment' do
  24 + @spaminator.expects(:process_all_comments)
  25 + @spaminator.expects(:process_all_people)
  26 + @environment.stubs(:save!)
  27 + @spaminator.run
  28 + assert_equal @now, @environment.settings[:spaminator_last_run]
  29 + end
  30 +
  31 + should 'find all comments' do
  32 + @spaminator.stubs(:process_comment)
  33 + @spaminator.send :process_all_comments
  34 + end
  35 +
  36 + should 'find all people' do
  37 + @spaminator.stubs(:process_person)
  38 + @spaminator.send :process_all_people
  39 + end
  40 +
  41 + should 'find all comments newer than a date' do
  42 + @environment.settings[:spaminator_last_run] = Time.now - 1.month
  43 + @spaminator.stubs(:process_comment)
  44 + @spaminator.send :process_all_comments
  45 + end
  46 +
  47 + should 'find all people newer than a date' do
  48 + @environment.settings[:spaminator_last_run] = Time.now - 1.month
  49 + @spaminator.stubs(:process_person)
  50 + @spaminator.send :process_all_people
  51 + end
  52 +
  53 +end