From ca98de4af64c5726a2351f81afcc07a1e38e4520 Mon Sep 17 00:00:00 2001 From: "Robin H. Johnson" Date: Sun, 21 May 2017 00:34:49 -0700 Subject: Implement hidden messages to block out spam. Signed-off-by: Robin H. Johnson --- ag | 42 +++++++++++++++++++++++++++++++++-- lib/storage.rb | 70 ++++++++++++++++++++++++++++++++++++++++------------------ 2 files changed, 88 insertions(+), 24 deletions(-) diff --git a/ag b/ag index c220b9d..d54cabe 100755 --- a/ag +++ b/ag @@ -28,9 +28,11 @@ $options.jobs = false $options.progress = true $options.need_argument = true $options.argmode = nil +$options.comment = nil op = OptionParser.new do |opts| - opts.banner = "Usage: ag <<--index-full|--index-new|--delete-msg|--delete-index|--reindex|--rethread|--info> <--list listname>> <[--file|--msgid|--hash] > [options]" + actions = %w(hide-msg unhide-msg index-full index-new delete-msg delete-index reindex rethread info).map { |s| '--'+s }.join('|') + opts.banner = "Usage: ag <<#{actions}>> <--list listname>> <[--file|--msgid|--hash] > [options]" opts.on('--index-full', 'Read the full past archive from Maildir/cur. Does --delete-index by default. Needs --list and a Maildir') do abort 'Can only select one action' if $options.action != nil @@ -52,13 +54,25 @@ op = OptionParser.new do |opts| $options.action = :do_delete_msg end + opts.on('--hide-msg', 'Hides a message. Needs --list and one of --file, --msgid, or --hash') do + abort 'Can only select one action' if $options.action != nil + + $options.action = :do_hide_msg + end + + opts.on('--unhide-msg', 'Unhides a message. Needs --list and one of --file, --msgid, or --hash') do + abort 'Can only select one action' if $options.action != nil + + $options.action = :do_unhide_msg + end + opts.on('--create-index', 'Create index but do not populate. Needs --list') do abort 'Can only select one action' if $options.action != nil $options.action = :do_create_index $options.need_argument = false end - + opts.on('--rethread', 'Rethread messages. Needs --list') do abort 'Can only select one action' if $options.action != nil @@ -131,6 +145,10 @@ op = OptionParser.new do |opts| opts.on('--no-progress', 'Do not display the progress bar') do $options.progress = false end + + opts.on('--comment COMMENT', 'Comment string as why the message is being hidden/unhidden.') do |comment| + $options.comment = comment + end end op.parse! @@ -215,6 +233,26 @@ def do_delete_msg end end +def do_hide_msg + id = Ag::Utils.resolve_id + + begin + Ag::Storage.hide($options.name, id, $options.comment) + rescue => e + $stderr.puts "Cannot hide message: #{e}" + end +end + +def do_unhide_msg + id = Ag::Utils.resolve_id + + begin + Ag::Storage.unhide($options.name, id, $options.comment) + rescue => e + $stderr.puts "Cannot unhide message: #{e}" + end +end + def do_delete_index(ignore_missing: false, _raise: false) begin Ag::Storage.delete_index($options.name) diff --git a/lib/storage.rb b/lib/storage.rb index 6ba4026..a22450d 100644 --- a/lib/storage.rb +++ b/lib/storage.rb @@ -5,6 +5,10 @@ require 'pp' module Ag::Storage module_function + def index_names(list) + return 'ml-' + list + end + def index_status(indexname) $es.cluster.health(level: :indices)['indices'][indexname]['status'] || 'FAIL' end @@ -18,13 +22,13 @@ module Ag::Storage # throws Elasticsearch::Transport::Transport::Errors::NotFound # if the list does not exist def delete_index(list) - $es.indices.delete(index: 'ml-' + list) + $es.indices.delete(index: index_name(list)) end # Create an index for list # sleep in 5ms intervals until it is ready def create_index(list, sleeptime: 0.005) - indexname = 'ml-' + list + indexname = index_name(list) $es.indices.create( index: indexname, body: { @@ -94,7 +98,14 @@ module Ag::Storage }, to: { type: 'string' - } + }, + hidden: { + type: 'boolean', + }, + comment: { + type: 'string', + index: 'not_analyzed', + }, } } } @@ -124,7 +135,7 @@ module Ag::Storage return nil if value == nil result = $es.search( - index: 'ml-' + list, + index: index_name(list), body: { query: { filtered: { @@ -196,7 +207,7 @@ module Ag::Storage end $es.index( - index: 'ml-' + list, + index: index_name(list), type: 'message', id: identifier, body: { @@ -212,14 +223,14 @@ module Ag::Storage attachments: attachments, received: received, raw_parent: raw_parent, - raw_filename: filename + raw_filename: filename, } ) end def fix_threading(list, pass) result = $es.search( - index: 'ml-' + list, + index: index_name(list), size: 5000, body: { size: 5000, @@ -250,31 +261,46 @@ module Ag::Storage opts[:progress] = "Calculating Threading (Pass #{pass})" if $options.progress Parallel.each(result['hits']['hits'], opts) do |hit| msg = resolve_message_id(list, hit['_source']['raw_parent']) - - unless msg == nil - $es.update( - index: 'ml-' + list, - type: 'message', - id: hit['_id'], - body: { - doc: { - parent: msg - } - } - ) - end + update(list, hit['_id'], { doc: { parent: msg } }) unless msg.nil? end result['hits']['total'] end def delete(list, id) - $es.delete(index: 'ml-' + list, type: 'message', id: id) + $es.delete(index: index_name(list), type: 'message', id: id) + end + + def _hide_unhide(list, id, hide_status, comment) + doc = { hidden: hide_status } + doc[:comment] = comment if comment # Only modify it if it exists + update(list, id, { + doc: doc, + detect_noop: true, + }) + end + + def unhide(list, id, comment) + hide_unhide(list, id, true, comment) + end + + def unhide(list, id, comment) + _hide_unhide(list, id, false, comment) + end + + def update(list, id, doc_changes) + raise "Invalid update for #{list}/#{id} #{doc_changes.to_s}" unless doc_changes.is_a?(Hash) + $es.update( + index: index_name(list), + type: 'message', + id: id, + body: doc_changes, + ) end def get(list, id) result = $es.search( - index: 'ml-' + list, + index: index_name(list), size: 1, body: { query: { -- cgit v1.2.3-65-gdbad