ref: master
plugins/spaminator/lib/spaminator_plugin/spaminator.rb
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 170 171 172 173 174 175 176 177 178 179 |
# encoding: utf-8 class SpaminatorPlugin::Spaminator class << self def run(environment) instance = new(environment) instance.run end def benchmark(environment) puts Benchmark.measure { run(environment) } end def initialize_logger(environment) logdir = Rails.root.join('log', SpaminatorPlugin.name.underscore) FileUtils.mkdir_p(logdir) if !File.exist?(logdir) logpath = File.join(logdir, "#{environment.name.to_slug}_#{ENV['RAILS_ENV']}_#{Time.now.strftime('%F_%T')}.log") @logger = Logger.new(logpath) end def log(message) @logger << "[#{Time.now.strftime('%F %T %z')}] #{message}\n" end end def initialize(environment) @environment = environment @settings = Noosfero::Plugin::Settings.new(@environment, SpaminatorPlugin) @report = SpaminatorPlugin::Report.new({:environment => environment, :total_people => Person.count, :total_comments => Comment.count}, :without_protection => true) self.class.initialize_logger(environment) end def run self.class.log("Starting Spaminator scan") start_time = Time.now process_all_comments process_all_people finish(start_time) end protected def finish(start_time) finish_report @settings.last_run = start_time @settings.save! self.class.log("Finishing Spaminator scan successfully") end # TODO considering run everything always def on_environment [ "profiles.environment_id = ?", @environment.id] end def comments_to_process Comment.joins("JOIN articles ON (comments.source_id = articles.id AND comments.source_type = 'Article') JOIN profiles ON (profiles.id = articles.profile_id)").without_spam.where(on_environment) end def people_to_process Person.visible.non_abusers.where(on_environment) end def process_all_comments self.class.log("Starting to process all comments") comments = comments_to_process total = comments.count pbar = ProgressBar.create(title: "☢ Comments", total: total, format: '%t: |%B| %E') if Rails.env.development? comments.each do |comment| begin process_comment(comment) rescue register_fail(:comments, comment) end pbar.increment if Rails.env.development? end @report.processed_comments = total pbar.finish if Rails.env.development? self.class.log("All comments processed") end def process_all_people self.class.log("Starting to process all people") people = people_to_process total = people.count pbar = ProgressBar.create(title: "☢ People", total: total, format: '%t: |%B| %E') if Rails.env.development? people.find_each do |person| process_person_by_comments(person) process_person_by_no_network(person) pbar.increment if Rails.env.development? end @report.processed_people = total pbar.finish if Rails.env.development? self.class.log("All people processed") end def process_comment(comment) self.class.log("Processing Comment[#{comment.id.to_s}]") comment = Comment.find(comment.id) comment.check_for_spam @report.spams_by_content += 1 if comment.spam # TODO several comments with the same content: # → disable author # → mark all of them as spam # TODO check comments that contains URL's end def process_person_by_comments(person) # person is author of more than 2 comments marked as spam # → mark as spammer # self.class.log("Processing Person[#{person.id.to_s}] by comments") begin number_of_spam_comments = Comment.spam.where(:author_id => person.id).count if number_of_spam_comments > 2 mark_as_spammer(person) @report.spammers_by_comments += 1 end rescue register_fail(:people, person) end end def process_person_by_no_network(person) # person who signed up more than one month ago, have no friends and <= 1 # communities # # → disable the profile # ? mark their comments as spam # self.class.log("Processing Person[#{person.id.to_s}] by network") if person.created_at < (Time.now - 1.month) && person.friends.count == 0 && person.communities.count <= 1 begin disable_person(person) @report.spammers_by_no_network += 1 rescue register_fail(:people, person) end Comment.where(:author_id => person.id).find_each do |comment| begin comment.spam! @report.spams_by_no_network += 1 rescue register_fail(:comments, comment) end end end end def disable_person(person) if person.disable Delayed::Job.enqueue(SpaminatorPlugin::Mailer::Job.new(person, :inactive_person_notification)) end end def mark_as_spammer(person) AbuseComplaint.create!(:reported => person).finish end def finish_report puts @report.details @report.save! end def register_fail(kind, failed) self.class.log("Failed #{kind.to_s.camelize}[#{failed.id.to_s}]") @report[:failed][kind.to_sym] << failed.id end end |