about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--app/lib/command_tag/commands/hello_world.rb2
-rw-r--r--app/lib/command_tag/commands/parent_status_tools.rb15
-rw-r--r--app/lib/command_tag/processor.rb60
3 files changed, 54 insertions, 23 deletions
diff --git a/app/lib/command_tag/commands/hello_world.rb b/app/lib/command_tag/commands/hello_world.rb
index 4cf17685e..581b21317 100644
--- a/app/lib/command_tag/commands/hello_world.rb
+++ b/app/lib/command_tag/commands/hello_world.rb
@@ -1,7 +1,7 @@
 # frozen_string_literal: true
 
 module CommandTag::Commands::HelloWorld
-  def handle_hello_world_at_start
+  def handle_hello_world_at_start(_)
     @text << "\nHello, world!"
   end
 end
diff --git a/app/lib/command_tag/commands/parent_status_tools.rb b/app/lib/command_tag/commands/parent_status_tools.rb
index df3cd06c6..ab917e8f5 100644
--- a/app/lib/command_tag/commands/parent_status_tools.rb
+++ b/app/lib/command_tag/commands/parent_status_tools.rb
@@ -1,8 +1,6 @@
 # frozen_string_literal: true
-
-# rubocop:disable Layout/ExtraSpacing
 module CommandTag::Commands::ParentStatusTools
-  def handle_publish_once_at_end
+  def handle_publish_once_at_end(_)
     return unless author_of_parent? && !@parent.published?
 
     PublishStatusService.new.call(@parent)
@@ -13,7 +11,7 @@ module CommandTag::Commands::ParentStatusTools
   alias handle_publish_toot_once_at_end                   handle_publish_once_at_end
   alias handle_publish_parent_once_at_end                 handle_publish_once_at_end
 
-  def handle_edit_once_before_save
+  def handle_edit_once_before_save(_)
     return unless author_of_parent?
 
     params = @parent.slice(*UpdateStatusService::ALLOWED_ATTRIBUTES).with_indifferent_access.compact
@@ -27,7 +25,7 @@ module CommandTag::Commands::ParentStatusTools
   alias handle_edit_toot_once_before_save                 handle_edit_once_before_save
   alias handle_edit_parent_once_before_save               handle_edit_once_before_save
 
-  def handle_mute_once_at_end
+  def handle_mute_once_at_end(_)
     return if author_of_parent?
 
     MuteStatusService.new.call(@account, @parent)
@@ -43,7 +41,7 @@ module CommandTag::Commands::ParentStatusTools
   alias handle_hide_toot_once_at_end                      handle_mute_once_at_end
   alias handle_hide_parent_once_at_end                    handle_mute_once_at_end
 
-  def handle_unmute_once_at_end
+  def handle_unmute_once_at_end(_)
     return if author_of_parent?
 
     @account.unmute_status!(@parent)
@@ -59,7 +57,7 @@ module CommandTag::Commands::ParentStatusTools
   alias handle_unhide_toot_once_at_end                    handle_unmute_once_at_end
   alias handle_unhide_parent_once_at_end                  handle_unmute_once_at_end
 
-  def handle_mute_thread_once_at_end
+  def handle_mute_thread_once_at_end(_)
     return if author_of_parent?
 
     MuteConversationService.new.call(@account, @conversation)
@@ -69,7 +67,7 @@ module CommandTag::Commands::ParentStatusTools
   alias handle_hide_thread_once_at_end                    handle_mute_thread_once_at_end
   alias handle_hide_conversation_once_at_end              handle_mute_thread_once_at_end
 
-  def handle_unmute_thread_once_at_end
+  def handle_unmute_thread_once_at_end(_)
     return if author_of_parent? || @conversation.blank?
 
     @account.unmute_conversation!(@conversation)
@@ -79,4 +77,3 @@ module CommandTag::Commands::ParentStatusTools
   alias handle_unhide_thread_once_at_end                  handle_unmute_thread_once_at_end
   alias handle_unhide_conversation_once_at_end            handle_unmute_thread_once_at_end
 end
-# rubocop:enable Layout/ExtraSpacing
diff --git a/app/lib/command_tag/processor.rb b/app/lib/command_tag/processor.rb
index 66a507f23..864da6c59 100644
--- a/app/lib/command_tag/processor.rb
+++ b/app/lib/command_tag/processor.rb
@@ -1,7 +1,18 @@
 # frozen_string_literal: true
 
+#                  .~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~.                  #
+###################              Cthulhu Code!              ###################
+#                  `~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`                  #
+# - Interprets and executes user input.  THIS CAN BE VERY DANGEROUS!          #
+# - Has a high complexity level and needs tests.                              #
+# - May destroy objects passed to it.                                         #
+# - Incurs a high performance penalty.                                        #
+#                                                                             #
+###############################################################################
+
 class CommandTag::Processor
   include Redisable
+  include ImgProxyHelper
   include CommandTag::Commands
 
   STATEMENT_RE = /^\s*#!\s*([^\n]+ (?:start|begin|do)$.*)\n\s*#!\s*(?:end|stop|done)\s*$|^\s*#!\s*(.*?)\s*$/im.freeze
@@ -15,6 +26,7 @@ class CommandTag::Processor
     @run_once     = Set[]
     @vars         = {}
     @text         = prepare_input(status.text)
+    @statements   = []
 
     return unless @account.present? && @account.local? && @status.present?
   end
@@ -22,7 +34,7 @@ class CommandTag::Processor
   def process!
     reset_status_caches
 
-    @statements = parse_statements
+    parse_statements
     @text = @text.gsub(STATEMENT_STRIP_RE, '').split("\n")
 
     %w(at_start once_at_start).each { |suffix| execute_statements(suffix) }
@@ -39,10 +51,14 @@ class CommandTag::Processor
       end
     elsif @status.destroyed?
       %w(after_destroy once_after_destroy).each { |suffix| execute_statements(suffix) }
-    elsif @status.update(text: process_inline_images(@text))
-      %w(after_save once_after_save).each { |suffix| execute_statements(suffix) }
     else
-      %w(after_save_fail once_after_save_fail).each { |suffix| execute_statements(suffix) }
+      @status.text = @text
+      process_inline_images!
+      if @status.save
+        %w(after_save once_after_save).each { |suffix| execute_statements(suffix) }
+      else
+        %w(after_save_fail once_after_save_fail).each { |suffix| execute_statements(suffix) }
+      end
     end
 
     %w(at_end once_at_end).each { |suffix| execute_statements(suffix) }
@@ -57,21 +73,39 @@ class CommandTag::Processor
   end
 
   def parse_statements
-    @text.scan(STATEMENT_RE).flatten.map do |statement|
+    @text.scan(STATEMENT_RE).flatten.each do |statement|
       next if statement.blank? || statement[0]&.strip.blank?
 
       statement = statement.scan(/^(.*) (?:start|begin|do)$(.*)|'([^']*)'|"([^"]*)"|(\S+)/im).flatten.compact
       statement[0] = statement[0].strip.tr(':.\- ', '_').gsub(/__+/, '_').downcase
-      statement
-    end.compact
+      add_statement_handlers_for(statement)
+    end
+  end
+
+  def potential_handlers_for(name)
+    ['_once', ''].each_with_index do |count_affix, index|
+      %w(at_start when_blank at_end).each do |when_affix|
+        yield ["handle_#{name}#{count_affix}_#{when_affix}", index.zero?]
+      end
+
+      %w(destroy save postprocess save_fail).each do |event_affix|
+        %w(before after).each do |when_affix|
+          yield ["handle_#{name}#{count_affix}_#{when_affix}_#{event_affix}", index.zero?]
+        end
+      end
+    end
+  end
+
+  def add_statement_handlers_for(statement_array)
+    potential_handlers_for(statement_array[0]) do |handler, once|
+      (@statements << [handler, statement_array[1..-1]]) if respond_to?(handler) && !(once && @run_once.include?(handler))
+      @run_once << handler if once
+    end
   end
 
-  def execute_statements(suffix)
-    @statements.each do |statement|
-      name = "handle_#{statement[0]}_#{suffix}"
-      is_run_once = suffix.start_with?('once_')
-      public_send(name, statement[1..-1]) if respond_to?(name) && !(is_run_once && @run_once.include?(name))
-      @run_once << name if is_run_once
+  def execute_statements(event)
+    @statements.select { |handler, _| handler.end_with?("_#{event}") }.each do |handler, arguments|
+      public_send(handler, arguments)
     end
   end