wco_models 3.1.0.189 → 3.1.0.191
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/controllers/wco/api/tags_controller.rb +9 -0
- data/app/controllers/wco/api_controller.rb +0 -1
- data/app/models/wco/tag.rb +10 -5
- data/app/models/wco_email/email_filter.rb +67 -14
- data/app/models/wco_email/email_filter_action.rb +47 -0
- data/app/models/wco_email/email_filter_condition.rb +19 -4
- data/app/models/wco_email/message.rb +21 -1
- data/app/models/wco_email/message_stub.rb +19 -1
- data/app/models/wco_hosting/appliance_tmpl.rb +2 -0
- data/app/views/wco/api/tags/index.json.jbuilder +7 -0
- data/app/views/wco/profiles/_form.haml +1 -1
- data/config/routes.rb +2 -0
- data/lib/wco_models.rb +24 -2
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9bff74466afd78d598eeb38f3b23283337a17e0b5a8b92b0e26f845f0bb8911a
|
4
|
+
data.tar.gz: e4f9e670080defcc68b180349aff8fd16b5de911bfc2951a97032f57a5a3400e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2aa5e46bf8e08e735d816278ecc948d47e99cd70e7c85e8d17bf7a7f196310c6096f12a14fd9d03158f426025580cec2648995c4325ff21bfe0940193f35ce73
|
7
|
+
data.tar.gz: d59c6bd87089bbb5a3ac0092a365696cf0d0fde26c2eb2573f00a1b6bc304ba53b2ef96a45ffa8212ef43b17ac7a0c13fa8d9d4c0c464454ccc42c18f2bc2cc4
|
data/app/models/wco/tag.rb
CHANGED
@@ -30,16 +30,21 @@ class Wco::Tag
|
|
30
30
|
find_or_create_by({ slug: INBOX })
|
31
31
|
end
|
32
32
|
|
33
|
-
TRASH = 'trash'
|
34
|
-
def self.trash
|
35
|
-
find_or_create_by({ slug: TRASH })
|
36
|
-
end
|
37
|
-
|
38
33
|
SPAM = 'spam'
|
39
34
|
def self.spam
|
40
35
|
find_or_create_by({ slug: SPAM })
|
41
36
|
end
|
42
37
|
|
38
|
+
NOT_SPAM = 'not-spam'
|
39
|
+
def self.not_spam
|
40
|
+
find_or_create_by({ slug: NOT_SPAM })
|
41
|
+
end
|
42
|
+
|
43
|
+
TRASH = 'trash'
|
44
|
+
def self.trash
|
45
|
+
find_or_create_by({ slug: TRASH })
|
46
|
+
end
|
47
|
+
|
43
48
|
def to_s
|
44
49
|
slug
|
45
50
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
|
2
|
+
|
2
3
|
##
|
3
4
|
## 2023-03-04 _vp_ When I receive one.
|
4
5
|
##
|
@@ -10,9 +11,6 @@ class WcoEmail::EmailFilter
|
|
10
11
|
|
11
12
|
PAGE_PARAM_NAME = :filters_page
|
12
13
|
|
13
|
-
FIELD_OPTS = [ :subject, :from, :to, :to_and_cc, :body, ]
|
14
|
-
MATCHTYPE_OPTS = [ :regex, :exact_insensitive, ]
|
15
|
-
|
16
14
|
field :from_regex
|
17
15
|
field :from_exact
|
18
16
|
field :subject_regex
|
@@ -23,13 +21,33 @@ class WcoEmail::EmailFilter
|
|
23
21
|
field :skip_from_regex
|
24
22
|
field :skip_to_exact
|
25
23
|
|
26
|
-
has_many :
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
24
|
+
has_many :actions, class_name: '::WcoEmail::EmailFilterAction', inverse_of: :email_filter
|
25
|
+
accepts_nested_attributes_for :actions, allow_destroy: true
|
26
|
+
validate :validate_actions
|
27
|
+
def validate_actions
|
28
|
+
if actions.length == 0
|
29
|
+
errors.add(:actions, 'must be present')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
## 'and' - all conditions must match, for filter to match
|
34
|
+
has_many :conditions, class_name: '::WcoEmail::EmailFilterCondition', inverse_of: :email_filter
|
35
|
+
accepts_nested_attributes_for :conditions, allow_destroy: true
|
36
|
+
|
37
|
+
## 'and' - all conditions must match, for filter to match
|
38
|
+
has_many :skip_conditions, class_name: '::WcoEmail::EmailFilterCondition', inverse_of: :email_skip_filter
|
39
|
+
accepts_nested_attributes_for :skip_conditions, allow_destroy: true
|
40
|
+
validate :validate_conditions
|
41
|
+
def validate_conditions
|
42
|
+
if conditions.length + skip_conditions.length == 0
|
43
|
+
errors.add(:conditions, 'Either conditions or skip conditions must be present.')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
has_and_belongs_to_many :action_tmpls, class_name: '::Wco::OfficeActionTemplate'
|
48
|
+
has_and_belongs_to_many :leadsets, class_name: '::Wco::Leadset'
|
49
|
+
|
50
|
+
belongs_to :tag, class_name: '::Wco::Tag', inverse_of: :email_filters, optional: true
|
33
51
|
|
34
52
|
KIND_AUTORESPOND_TMPL = 'autorespond-template'
|
35
53
|
KIND_AUTORESPOND_EACT = 'autorespond-email-action'
|
@@ -46,10 +64,45 @@ class WcoEmail::EmailFilter
|
|
46
64
|
field :kind
|
47
65
|
|
48
66
|
|
49
|
-
belongs_to :email_template, class_name: 'WcoEmail::EmailTemplate', optional: true
|
50
|
-
belongs_to :email_action_template, class_name: 'WcoEmail::EmailActionTemplate', optional: true
|
67
|
+
belongs_to :email_template, class_name: '::WcoEmail::EmailTemplate', optional: true
|
68
|
+
belongs_to :email_action_template, class_name: '::WcoEmail::EmailActionTemplate', optional: true
|
69
|
+
|
70
|
+
## @TODO: change to has_and_belongs_to_many, test-driven.
|
71
|
+
has_many :conversations, class_name: '::WcoEmail::Conversation', inverse_of: :filter
|
72
|
+
|
73
|
+
def to_s
|
74
|
+
"EmailFilter: #{from_regex} #{from_exact} #{conditions.map { |c| c.to_s }.join }"
|
75
|
+
end
|
76
|
+
def to_s_full
|
77
|
+
# inn = ""
|
78
|
+
# inn = "#{inn}#{conditions.map { |c| c.to_s_full }.join }" if conditions.present?
|
79
|
+
# inn = "#{inn}#{skip_conditions.map { |c| c.to_s_full }.join }" if skip_conditions.present?
|
80
|
+
out =<<-AOL
|
81
|
+
<EmailFilter #{from_regex} #{from_exact}>
|
82
|
+
#{conditions.map { |c| c.to_s_full( indent: 2) }.join }
|
83
|
+
#{skip_conditions.map { |c| c.to_s_full( indent: 2) }.join }
|
84
|
+
#{actions.map { |c| c.to_s_full( indent: 2) }.join }
|
85
|
+
</EmailFilter>"
|
86
|
+
AOL
|
87
|
+
while out.match(/\n\n/) do
|
88
|
+
out = out.gsub(/\n\n/, "\n")
|
89
|
+
end
|
90
|
+
out
|
91
|
+
end
|
92
|
+
|
93
|
+
def to_xml
|
94
|
+
attrs = ''
|
95
|
+
children = ''
|
96
|
+
if from_regex || from_exact
|
97
|
+
attrs = "#{attrs} from=#{from_regex}#{from_exact}"
|
98
|
+
end
|
99
|
+
if conditions.present?
|
100
|
+
children = "#{children}#{conditions.map { |c| c.to_s }.join('') }"
|
101
|
+
end
|
102
|
+
return "<EF #{attrs}>#{children}</EF>\n"
|
103
|
+
end
|
51
104
|
|
52
|
-
has_many :conversations, class_name: 'WcoEmail::Conversation', inverse_of: :filter
|
53
105
|
|
54
|
-
end
|
55
106
|
|
107
|
+
end
|
108
|
+
::EF = WcoEmail::EmailFilter
|
@@ -0,0 +1,47 @@
|
|
1
|
+
|
2
|
+
class WcoEmail::EmailFilterAction
|
3
|
+
include Mongoid::Document
|
4
|
+
include Mongoid::Timestamps
|
5
|
+
store_in collection: 'email_filter_actions'
|
6
|
+
|
7
|
+
belongs_to :email_filter
|
8
|
+
|
9
|
+
KIND_EXE = 'exe'
|
10
|
+
KIND_REMOVE_TAG = ::WcoEmail::ACTION_REMOVE_TAG
|
11
|
+
KIND_ADD_TAG = ::WcoEmail::ACTION_ADD_TAG
|
12
|
+
KIND_AUTORESPOND = ::WcoEmail::ACTION_AUTORESPOND
|
13
|
+
KIND_SCHEDULE_EMAIL_ACTION = 'autorespond-email-action'
|
14
|
+
KIND_REMOVE_EMAIL_ACTION = 'remove-email-action'
|
15
|
+
field :kind
|
16
|
+
validates :kind, inclusion: ::WcoEmail::ACTIONS
|
17
|
+
|
18
|
+
field :value # the id of a tag, or email template, or email action
|
19
|
+
|
20
|
+
|
21
|
+
before_validation :check_value
|
22
|
+
def check_value
|
23
|
+
case kind
|
24
|
+
when KIND_AUTORESPOND
|
25
|
+
existing = WcoEmail::EmailTemplate.where({ id: value }).first
|
26
|
+
if !existing
|
27
|
+
errors.add( :base, 'missing EmailTemplate id when creating an EmailFilterAction' )
|
28
|
+
throw :abort
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
def to_s
|
35
|
+
"<EFA #{kind} #{value} />\n"
|
36
|
+
end
|
37
|
+
def to_s_full indent: 0
|
38
|
+
_value = value
|
39
|
+
if [ KIND_ADD_TAG, KIND_REMOVE_TAG ].include?( kind )
|
40
|
+
_value = Wco::Tag.find( value )
|
41
|
+
end
|
42
|
+
if [ KIND_AUTORESPOND ].include?( kind )
|
43
|
+
_value = WcoEmail::EmailTemplate.find( value )
|
44
|
+
end
|
45
|
+
"#{" " * indent }<EmailFilterAction #{kind} `#{_value}` />\n"
|
46
|
+
end
|
47
|
+
end
|
@@ -5,13 +5,28 @@ class WcoEmail::EmailFilterCondition
|
|
5
5
|
include Mongoid::Paranoia
|
6
6
|
store_in collection: 'office_email_filter_conditions'
|
7
7
|
|
8
|
-
belongs_to :email_filter, inverse_of: :
|
9
|
-
belongs_to :
|
8
|
+
belongs_to :email_filter, class_name: '::WcoEmail::EmailFilter', inverse_of: :conditions, optional: true
|
9
|
+
belongs_to :email_skip_filter, class_name: '::WcoEmail::EmailFilter', inverse_of: :skip_conditions, optional: true
|
10
10
|
|
11
|
+
## see WcoEmail::FIELD_*
|
11
12
|
field :field
|
12
|
-
field :
|
13
|
-
|
13
|
+
validates :field, presence: true
|
14
|
+
|
15
|
+
field :operator, type: String
|
16
|
+
validates :operator, presence: true, inclusion: ::WcoEmail::OPERATORS
|
14
17
|
|
18
|
+
field :value
|
19
|
+
validates :value, presence: true
|
15
20
|
|
21
|
+
def to_s
|
22
|
+
"<EFC #{field} #{operator} #{value} />"
|
23
|
+
end
|
24
|
+
def to_s_full indent: 0
|
25
|
+
_value = value
|
26
|
+
if [ OPERATOR_HAS_TAG, OPERATOR_NOT_HAS_TAG ].include?( operator )
|
27
|
+
_value = Wco::Tag.find( value )
|
28
|
+
end
|
29
|
+
"#{" " * indent }<EmailFilterCondition #{field} #{operator} `#{_value}` />\n"
|
30
|
+
end
|
16
31
|
end
|
17
32
|
|
@@ -124,7 +124,27 @@ class WcoEmail::Message
|
|
124
124
|
})
|
125
125
|
|
126
126
|
else
|
127
|
-
|
127
|
+
if filter.actions.present?
|
128
|
+
filter.actions.each do |act|
|
129
|
+
case act.kind
|
130
|
+
when ::WcoEmail::ACTION_REMOVE_TAG
|
131
|
+
this_tag = Wco::Tag.find( act.value )
|
132
|
+
conv.tags -= [ this_tag ]
|
133
|
+
when ::WcoEmail::ACTION_ADD_TAG
|
134
|
+
this_tag = Wco::Tag.find( act.value )
|
135
|
+
conv.tags += [ this_tag ]
|
136
|
+
when ::WcoEmail::ACTION_AUTORESPOND
|
137
|
+
this_template = WcoEmail::EmailTemplate.find( act.value )
|
138
|
+
WcoEmail::Context.create!({
|
139
|
+
email_template: this_template,
|
140
|
+
lead_id: lead.id,
|
141
|
+
send_at: Time.now,
|
142
|
+
})
|
143
|
+
end
|
144
|
+
end
|
145
|
+
else
|
146
|
+
raise "unknown filter kind: #{filter.kind}"
|
147
|
+
end
|
128
148
|
end
|
129
149
|
|
130
150
|
conv.save!
|
@@ -57,7 +57,7 @@ class WcoEmail::MessageStub
|
|
57
57
|
raw = @client.get_object( bucket: stub.bucket, key: stub.object_key ).body.read
|
58
58
|
raw = raw.encode('utf-8', invalid: :replace, undef: :replace, replace: '_' )
|
59
59
|
the_mail = Mail.new( raw )
|
60
|
-
puts! the_mail, 'the_mail'
|
60
|
+
# puts! the_mail, 'the_mail'
|
61
61
|
|
62
62
|
message_id = the_mail.header['message-id']&.decoded
|
63
63
|
message_id ||= "#{the_mail.date&.iso8601}::#{the_mail.from}"
|
@@ -199,6 +199,24 @@ class WcoEmail::MessageStub
|
|
199
199
|
reason = 'subject_exact'
|
200
200
|
end
|
201
201
|
|
202
|
+
filter.conditions.each do |cond|
|
203
|
+
case cond.field
|
204
|
+
when WcoEmail::FIELD_LEADSET
|
205
|
+
if cond.operator == WcoEmail::OPERATOR_NOT_HAS_TAG
|
206
|
+
this_tag = Wco::Tag.find cond.value
|
207
|
+
if leadset.tags.include?( this_tag )
|
208
|
+
;
|
209
|
+
else
|
210
|
+
reason = "condition leadset not-has-tag #{this_tag} NOT met"
|
211
|
+
end
|
212
|
+
end
|
213
|
+
when WcoEmail::FIELD_TO
|
214
|
+
if @message.to == cond.value
|
215
|
+
reason = "condition to = #{cond.value}"
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
202
220
|
if reason
|
203
221
|
puts! "Applying filter #{filter} to conv #{@message.conversation} for matching #{reason}" if DEBUG
|
204
222
|
|
data/config/routes.rb
CHANGED
data/lib/wco_models.rb
CHANGED
@@ -31,7 +31,30 @@ INACTIVE = 'inactive'
|
|
31
31
|
STATUSES = [ nil, ACTIVE, INACTIVE ]
|
32
32
|
|
33
33
|
module Wco; end
|
34
|
-
|
34
|
+
|
35
|
+
module WcoEmail
|
36
|
+
ACTION_ADD_TAG = 'add-tag'
|
37
|
+
ACTION_AUTORESPOND = 'autorespond-template'
|
38
|
+
ACTION_EXE = 'exe'
|
39
|
+
ACTION_SCHEDULE_EMAIL_ACTION = 'autorespond-email-action'
|
40
|
+
ACTION_REMOVE_EMAIL_ACTION = 'remove-email-action'
|
41
|
+
ACTION_REMOVE_TAG = 'remove-tag'
|
42
|
+
ACTIONS = [ 'add-tag', 'autorespond-email-action', 'autorespond-template', 'exe', 'remove-email-action', 'remove-tag' ]
|
43
|
+
|
44
|
+
FIELD_BODY = 'body'
|
45
|
+
FIELD_EXE = 'exe'
|
46
|
+
FIELD_FROM = 'from'
|
47
|
+
FIELD_LEADSET = 'leadset'
|
48
|
+
FIELD_SUBJECT = 'subject'
|
49
|
+
FIELD_TO = 'to'
|
50
|
+
|
51
|
+
OPERATOR_EQUALS = 'equals'
|
52
|
+
OPERATOR_HAS_TAG = 'has-tag'
|
53
|
+
OPERATOR_NOT_HAS_TAG = 'not-has-tag'
|
54
|
+
OPERATOR_TEXT_INPUT = 'text-input'
|
55
|
+
OPERATORS = [ 'equals', 'has-tag', 'not-has-tag', 'text-input' ]
|
56
|
+
end
|
57
|
+
|
35
58
|
module WcoHosting; end
|
36
59
|
|
37
60
|
class Wco::HTTParty
|
@@ -40,4 +63,3 @@ class Wco::HTTParty
|
|
40
63
|
end
|
41
64
|
|
42
65
|
ActiveSupport.escape_html_entities_in_json = true
|
43
|
-
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wco_models
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.1.0.
|
4
|
+
version: 3.1.0.191
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Victor Pudeyev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-01-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ahoy_matey
|
@@ -429,6 +429,7 @@ files:
|
|
429
429
|
- app/assets/stylesheets/wco/videos.scss
|
430
430
|
- app/controllers/wco/api/leads_controller.rb
|
431
431
|
- app/controllers/wco/api/obfuscated_redirects_controller.rb
|
432
|
+
- app/controllers/wco/api/tags_controller.rb
|
432
433
|
- app/controllers/wco/api_controller.rb
|
433
434
|
- app/controllers/wco/application_controller.rb
|
434
435
|
- app/controllers/wco/galleries_controller.rb
|
@@ -499,6 +500,7 @@ files:
|
|
499
500
|
- app/models/wco_email/email_action_template.rb
|
500
501
|
- app/models/wco_email/email_action_template_tie.rb
|
501
502
|
- app/models/wco_email/email_filter.rb
|
503
|
+
- app/models/wco_email/email_filter_action.rb
|
502
504
|
- app/models/wco_email/email_filter_condition.rb
|
503
505
|
- app/models/wco_email/email_template.rb
|
504
506
|
- app/models/wco_email/message.rb
|
@@ -525,6 +527,7 @@ files:
|
|
525
527
|
- app/views/wco/_search.haml
|
526
528
|
- app/views/wco/_select_all.haml
|
527
529
|
- app/views/wco/api/leads/index_hash.jbuilder
|
530
|
+
- app/views/wco/api/tags/index.json.jbuilder
|
528
531
|
- app/views/wco/application/_alerts_notices.haml
|
529
532
|
- app/views/wco/application/_auth_widget.haml
|
530
533
|
- app/views/wco/application/_debug.haml
|