wco_models 3.1.0.189 → 3.1.0.191

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6d7aa099d022824fbef4b0fae04c43b89a70ab7e232e70fce561f268c8733084
4
- data.tar.gz: 4b7b8bb274105b8ab5dd52c5705e5cab7e2f16a1d4e43d59434c62ddaa87fa0d
3
+ metadata.gz: 9bff74466afd78d598eeb38f3b23283337a17e0b5a8b92b0e26f845f0bb8911a
4
+ data.tar.gz: e4f9e670080defcc68b180349aff8fd16b5de911bfc2951a97032f57a5a3400e
5
5
  SHA512:
6
- metadata.gz: 856d7b8285233d1a98b6874c493e6b015da8c8723da597576fb28d0716f190a1a41ea673c18920cca10e12791cb1e08d7f3d4fcb0b3b352dd3562838c406ab5c
7
- data.tar.gz: 65badfb5507f336f56d25fe963a5eb8a743186d410cfa4910bdc8fd952c25fa9bcea54df61bfa63511dd63c94715b5846c311dcc4e19b3462be0ae1f8d603596
6
+ metadata.gz: 2aa5e46bf8e08e735d816278ecc948d47e99cd70e7c85e8d17bf7a7f196310c6096f12a14fd9d03158f426025580cec2648995c4325ff21bfe0940193f35ce73
7
+ data.tar.gz: d59c6bd87089bbb5a3ac0092a365696cf0d0fde26c2eb2573f00a1b6bc304ba53b2ef96a45ffa8212ef43b17ac7a0c13fa8d9d4c0c464454ccc42c18f2bc2cc4
@@ -0,0 +1,9 @@
1
+
2
+ class Wco::Api::TagsController < Wco::ApiController
3
+
4
+ def index
5
+ authorize! :index, Wco::Tag
6
+ @tags = Wco::Tag.all()
7
+ end
8
+
9
+ end
@@ -10,7 +10,6 @@ class Wco::ApiController < ActionController::Base
10
10
  private
11
11
 
12
12
  def decode_jwt
13
- byebug
14
13
  out = JWT.decode params[:jwt_token], nil, false
15
14
  email = out[0]['email']
16
15
  user = User.find_by({ email: email })
@@ -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 :email_filter_conditions
27
- has_many :email_filter_skip_conditions, class_name: 'WcoEmail::EmailFilterCondition'
28
-
29
- has_and_belongs_to_many :action_tmpls, class_name: 'Wco::OfficeActionTemplate'
30
- has_and_belongs_to_many :leadsets, class_name: 'Wco::Leadset'
31
-
32
- belongs_to :tag, class_name: 'Wco::Tag', inverse_of: :email_filters, optional: true
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: :email_filter_conditions
9
- belongs_to :email_filter_skip, inverse_of: :email_filter_skip_conditions
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 :matchtype
13
- field :value
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
- raise "unknown filter kind: #{filter.kind}"
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
 
@@ -30,6 +30,8 @@ class WcoHosting::ApplianceTmpl
30
30
  # file.close
31
31
  # end
32
32
 
33
+ field :docker_compose_erb, type: :string
34
+
33
35
  field :stdout, type: :string, default: ''
34
36
  field :stderr, type: :string, default: ''
35
37
 
@@ -0,0 +1,7 @@
1
+
2
+ json.tags do
3
+ json.array! @tags do |tag|
4
+ json.label tag.to_s
5
+ json.value tag.id.to_s
6
+ end
7
+ end
@@ -16,7 +16,7 @@
16
16
  %label schwab_refresh_token
17
17
  = f.text_field :schwab_refresh_token
18
18
  .field
19
- %label schwab_access_token
19
+ %label schwab_id_token
20
20
  = f.text_field :schwab_id_token
21
21
 
22
22
  .actions
data/config/routes.rb CHANGED
@@ -7,6 +7,8 @@ Wco::Engine.routes.draw do
7
7
 
8
8
  get 'obf', to: 'obfuscated_redirects#show' ## testing only.
9
9
  get 'obf/:id', to: 'obfuscared_redirects#show'
10
+
11
+ get 'tags', to: 'tags#index'
10
12
  end
11
13
 
12
14
  get 'application/tinymce', to: 'application#tinymce'
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
- module WcoEmail; end
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.189
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: 2024-11-30 00:00:00.000000000 Z
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