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 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