From 3366a957219b15f5ab6f6eabbf5466e1e12082de Mon Sep 17 00:00:00 2001 From: Fire Demon Date: Mon, 20 Jul 2020 03:58:14 -0500 Subject: [Feature] Add command tags; add #!edit and #!publish commands for mobile users --- app/lib/command_tag/processor.rb | 79 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 app/lib/command_tag/processor.rb (limited to 'app/lib/command_tag/processor.rb') diff --git a/app/lib/command_tag/processor.rb b/app/lib/command_tag/processor.rb new file mode 100644 index 000000000..b122b9e8d --- /dev/null +++ b/app/lib/command_tag/processor.rb @@ -0,0 +1,79 @@ +# frozen_string_literal: true + +class CommandTag::Processor + include CommandTag::Commands + + STATEMENT_RE = /^\s*#!\s*([^\n]+ (?:start|begin|do)$.*)\n\s*#!\s*(?:end|stop|done)\s*$|^\s*#!\s*(.*?)\s*$/im.freeze + STATEMENT_STRIP_RE = /^\s*#!\s*(?:[^\n]+ (?:start|begin|do)$.*)\n\s*#!\s*(?:end|stop|done)\s*$\n?|^\s*#!\s*(?:.*?)\s*$\n?/im.freeze + + def initialize(account, status) + @account = account + @status = status + @parent = status.thread + @run_once = Set[] + @vars = {} + @text = status.text.gsub("\r\n", "\n").gsub("\n\r", "\n").gsub("\r", "\n") + + return unless @account.present? && @account.local? && @status.present? + end + + def process! + @statements = parse_statements + @text = @text.gsub(STATEMENT_STRIP_RE, '').split("\n") + + %w(at_start once_at_start).each { |suffix| execute_statements(suffix) } + @text = @text.join("\n").rstrip + %w(before_save once_before_save).each { |suffix| execute_statements(suffix) } + + if @text.blank? + %w(when_blank once_when_blank).each { |suffix| execute_statements(suffix) } + + unless (@status.published? && !@status.edited.zero?) || @text.present? + %w(before_destroy once_before_destroy).each { |suffix| execute_statements(suffix) } + @status.destroy + %w(after_destroy once_after_destroy).each { |suffix| execute_statements(suffix) } + end + elsif @status.destroyed? + %w(after_destroy once_after_destroy).each { |suffix| execute_statements(suffix) } + elsif @status.update(text: @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) } + end + + %w(at_end once_at_end).each { |suffix| execute_statements(suffix) } + end + + private + + def parse_statements + @text.scan(STATEMENT_RE).flatten.map 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('- ', '_').downcase + statement + end.compact + 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 + end + end + + def author_of_status? + @account.id == @status.account_id + end + + def author_of_parent? + @account.id == @parent&.account_id + end + + def destroy_status! + @status.destroy unless @status.destroyed? + end +end -- cgit