blob: 1e177a015219336095b0acabfb7a2fa0d0f01b78 (
plain) (
blame)
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
|
# frozen_string_literal: true
class CommandTag::Processor
include Redisable
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!
reset_status_caches
@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) }
reset_status_caches
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(':.\- ', '_').gsub(/__+/, '_').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 reset_status_caches
[@status, @parent].each do |status|
next unless @account.id == status&.account_id
Rails.cache.delete_matched("statuses/#{status.id}-*")
Rails.cache.delete("statuses/#{status.id}")
Rails.cache.delete(status)
redis.zremrangebyscore("spam_check:#{status.account.id}", status.id, status.id)
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
|