wco_models 3.1.0.52 → 3.1.0.54
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/stylesheets/wco/utils.scss +4 -0
- data/app/models/wco/gallery.rb +7 -12
- data/app/models/wco/lead.rb +6 -0
- data/app/models/wco/photo.rb +1 -5
- data/app/models/wco_email/context.rb +3 -1
- data/app/models/wco_email/email_template.rb +16 -3
- data/app/models/wco_email/message.rb +1 -1
- data/app/models/wco_email/message_stub.rb +184 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 41ed3d61aaea366b6925edbffd7cc4cf955bfffaf21a46f029ab1e3d463e7e17
|
4
|
+
data.tar.gz: efcfd16d8db203ab26fcbe58ea9b82cb08a4d32023c986de52a9a9f61d5eb740
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2be84afa6c6de2b06ba0257553f100523fe052fabddc365292ae9cbe450070e95bb34e2a152eb026751f582e1167ea03b3253566448e42b4e69d2e485a2a6674
|
7
|
+
data.tar.gz: 1a627331788250f7664b617dba05db34a74991aab270bc1604a2c3906860828a1940f8db049fc41ec7c335eaa15d38156bb3e8136bef46471450e62167fd7302
|
data/app/models/wco/gallery.rb
CHANGED
@@ -7,23 +7,24 @@ class Wco::Gallery
|
|
7
7
|
include Wco::Utils
|
8
8
|
store_in collection: 'galleries'
|
9
9
|
|
10
|
-
PER_PAGE = 6
|
11
10
|
|
12
11
|
field :name
|
13
12
|
validates :name, :uniqueness => true
|
14
13
|
index({ :name => -1 }) ## 2023-09-23 removed uniqueness
|
15
14
|
|
15
|
+
field :slug
|
16
|
+
index({ :slug => -1 }, { :unique => true })
|
17
|
+
validates :slug, presence: true, uniqueness: true
|
18
|
+
before_validation :set_slug, :on => :create
|
19
|
+
|
16
20
|
field :subhead
|
17
21
|
field :descr, :as => :description
|
18
22
|
|
19
23
|
field :is_public, type: Boolean, default: false
|
20
24
|
# has_and_belongs_to_many :shared_profiles, :class_name => 'Wco::Profile', :inverse_of => :shared_galleries
|
21
25
|
|
22
|
-
field :is_trash, type: Boolean, default: false
|
23
|
-
field :is_done, type: Boolean, default: false
|
24
|
-
|
25
26
|
def published
|
26
|
-
where({ :is_public => true
|
27
|
+
where({ :is_public => true }).order_by({ :created_at => :desc })
|
27
28
|
end
|
28
29
|
|
29
30
|
field :x, :type => Float
|
@@ -31,15 +32,9 @@ class Wco::Gallery
|
|
31
32
|
field :z, :type => Float
|
32
33
|
|
33
34
|
field :lang, :default => 'en'
|
34
|
-
# field :username
|
35
|
-
# field :lead_id, type: :integer
|
36
35
|
|
37
|
-
field :slug
|
38
|
-
index({ :slug => -1 }, { :unique => true })
|
39
|
-
validates :slug, presence: true, uniqueness: true
|
40
|
-
before_validation :set_slug, :on => :create
|
41
36
|
|
42
|
-
def self.list conditions = {
|
37
|
+
def self.list conditions = {}
|
43
38
|
out = self.unscoped.where( conditions ).order_by( :created_at => :desc )
|
44
39
|
[['', nil]] + out.map { |item| [ "#{item.created_at.strftime('%Y%m%d')} #{item.name}", item.id ] }
|
45
40
|
end
|
data/app/models/wco/lead.rb
CHANGED
@@ -14,6 +14,12 @@ class Wco::Lead
|
|
14
14
|
field :address
|
15
15
|
|
16
16
|
belongs_to :leadset, class_name: 'Wco::Leadset'
|
17
|
+
before_validation :set_leadset, on: :create
|
18
|
+
def set_leadset
|
19
|
+
domain = email.split('@')[1]
|
20
|
+
self.leadset ||= Wco::Leadset.find_or_create_by({ company_url: domain })
|
21
|
+
end
|
22
|
+
|
17
23
|
has_one :photo, class_name: 'Wco::Photo'
|
18
24
|
|
19
25
|
has_many :email_messages, class_name: '::WcoEmail::Message', inverse_of: :lead
|
data/app/models/wco/photo.rb
CHANGED
@@ -51,14 +51,10 @@ class Wco::Photo
|
|
51
51
|
s3_region: ::S3_CREDENTIALS[:region]
|
52
52
|
validates_attachment_content_type :photo, :content_type => ["image/webp", "image/jpg", "image/jpeg", "image/png", "image/gif", 'application/octet-stream' ]
|
53
53
|
|
54
|
-
def self.n_per_manager_gallery
|
55
|
-
25
|
56
|
-
end
|
57
|
-
|
58
54
|
def export_fields
|
59
55
|
%w|
|
60
56
|
gallery_id
|
61
|
-
name descr weight
|
57
|
+
name descr weight
|
62
58
|
|
63
59
|
photo_file_name photo_content_type photo_file_size photo_updated_at photo_fingerprint
|
64
60
|
|
|
@@ -1,4 +1,6 @@
|
|
1
1
|
|
2
|
+
DEFAULT_FROM_EMAIL = 'victor@wasya.co'
|
3
|
+
|
2
4
|
class WcoEmail::EmailTemplate
|
3
5
|
include Mongoid::Document
|
4
6
|
include Mongoid::Timestamps
|
@@ -86,9 +88,20 @@ class WcoEmail::EmailTemplate
|
|
86
88
|
'Wasya Co Mailer <no-reply@wco.com.de>',
|
87
89
|
'Wasya Co Mailer <wasyacomailer@gmail.com>',
|
88
90
|
];
|
91
|
+
FROM_EMAILS_2 = [
|
92
|
+
|
93
|
+
[ 'Victor Pudeyev <piousbox@gmail.com>', 'piousbox@gmail.com' ],
|
94
|
+
[ 'Victor Pudeyev <victor@piousbox.com>', 'victor@piousbox.com' ],
|
95
|
+
[ 'Victor Pudeyev <no-reply@piousbox.com>', 'no-reply@piousbox.com' ],
|
96
|
+
|
97
|
+
[ 'WasyaCo Consulting <no-reply@wasya.co>', 'no-reply@wasya.co' ],
|
98
|
+
[ 'Victor Pudeyev <victor@wasya.co>', 'victor@wasya.co' ],
|
99
|
+
|
100
|
+
];
|
89
101
|
field :from_email
|
90
|
-
def self.
|
91
|
-
[ [nil, nil] ] + FROM_EMAILS.map { |i| [i, i] }
|
102
|
+
def self.from_emails_list
|
103
|
+
# [ [nil, nil] ] + FROM_EMAILS.map { |i| [i, i] }
|
104
|
+
FROM_EMAILS_2
|
92
105
|
end
|
93
106
|
|
94
107
|
SIGNATURE = <<~AOL
|
@@ -118,7 +131,7 @@ class WcoEmail::EmailTemplate
|
|
118
131
|
def self.blank; self.blank_template; end
|
119
132
|
|
120
133
|
def self.list
|
121
|
-
all.map { |p| [ p.
|
134
|
+
all.map { |p| [ p.slug, p.id ] }
|
122
135
|
end
|
123
136
|
|
124
137
|
end
|
@@ -1,4 +1,10 @@
|
|
1
1
|
|
2
|
+
=begin
|
3
|
+
|
4
|
+
key = '01070861907736276273039d9ee-c69a3509-5c85-481d-822e-ba65c204e1ba-000000@eu-central-1.amazonses.com'
|
5
|
+
|
6
|
+
=end
|
7
|
+
|
2
8
|
##
|
3
9
|
## Only object_key, no validations.
|
4
10
|
## 2023-12-28 _vp_ Continue.
|
@@ -13,9 +19,9 @@ class WcoEmail::MessageStub
|
|
13
19
|
STATUS_PENDING = 'status_pending'
|
14
20
|
STATUS_PROCESSED = 'status_processed'
|
15
21
|
STATUS_FAILED = 'status_failed'
|
16
|
-
STATUSES = [ STATUS_PENDING, STATUS_PROCESSED ]
|
22
|
+
STATUSES = [ STATUS_PENDING, STATUS_PROCESSED, STATUS_FAILED ]
|
17
23
|
field :status, default: STATUS_PENDING
|
18
|
-
scope :pending, ->{ where( status:
|
24
|
+
scope :pending, ->{ where( status: STATUS_PENDING ) }
|
19
25
|
|
20
26
|
field :bucket # 'ish-ses', 'ish-ses-2024'
|
21
27
|
|
@@ -31,8 +37,180 @@ class WcoEmail::MessageStub
|
|
31
37
|
{}
|
32
38
|
AOL
|
33
39
|
|
34
|
-
|
35
|
-
|
40
|
+
def do_process
|
41
|
+
@client ||= Aws::S3::Client.new({
|
42
|
+
region: ::S3_CREDENTIALS[:region_ses],
|
43
|
+
access_key_id: ::S3_CREDENTIALS[:access_key_id_ses],
|
44
|
+
secret_access_key: ::S3_CREDENTIALS[:secret_access_key_ses],
|
45
|
+
})
|
46
|
+
stub = self
|
47
|
+
|
48
|
+
raw = @client.get_object( bucket: stub.bucket, key: stub.object_key ).body.read
|
49
|
+
the_mail = Mail.new( raw )
|
50
|
+
|
51
|
+
message_id = the_mail.header['message-id']&.decoded
|
52
|
+
message_id ||= "#{the_mail.date&.iso8601}::#{the_mail.from}"
|
53
|
+
# puts! message_id, 'message_id'
|
54
|
+
|
55
|
+
in_reply_to_id = the_mail.header['in-reply-to']&.to_s
|
56
|
+
puts! in_reply_to_id, 'in_reply_to_id'
|
57
|
+
|
58
|
+
the_mail.to = [ 'NO-RECIPIENT' ] if !the_mail.to
|
59
|
+
subject = WcoEmail::Message.strip_emoji( the_mail.subject || '(wco-no-subject)' )
|
60
|
+
puts! subject, 'subject'
|
61
|
+
|
62
|
+
## Conversation
|
63
|
+
if in_reply_to_id
|
64
|
+
in_reply_to_msg = WcoEmail::Message.where({ message_id: in_reply_to_id }).first
|
65
|
+
if !in_reply_to_msg
|
66
|
+
conv = WcoEmail::Conversation.find_or_create_by({
|
67
|
+
subject: subject,
|
68
|
+
})
|
69
|
+
in_reply_to_msg = WcoEmail::Message.find_or_create_by({
|
70
|
+
message_id: in_reply_to_id,
|
71
|
+
conversation: conv,
|
72
|
+
})
|
73
|
+
end
|
74
|
+
conv = in_reply_to_msg.conversation
|
75
|
+
else
|
76
|
+
conv = WcoEmail::Conversation.find_or_create_by({
|
77
|
+
subject: subject,
|
78
|
+
})
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
## Leadset, Lead
|
83
|
+
from = the_mail.from ? the_mail.from[0] : "nobody@unknown-doma.in"
|
84
|
+
domain = from.split('@')[1]
|
85
|
+
leadset = Wco::Leadset.where( company_url: domain ).first
|
86
|
+
leadset ||= Wco::Leadset.create( company_url: domain, email: from )
|
87
|
+
lead = Wco::Lead.find_or_create_by( email: from, leadset: leadset )
|
88
|
+
|
89
|
+
|
90
|
+
message = WcoEmail::Message.unscoped.where( message_id: message_id ).first
|
91
|
+
if message
|
92
|
+
message.message_id = "#{Time.now.strftime('%Y%m%d')}-trash-#{message.message_id}"
|
93
|
+
message.object_key = "#{Time.now.strftime('%Y%m%d')}-trash-#{message.object_key}"
|
94
|
+
message.save!( validate: false )
|
95
|
+
message.delete
|
96
|
+
end
|
97
|
+
@message = WcoEmail::Message.create!({
|
98
|
+
stub: stub,
|
99
|
+
conversation: conv,
|
100
|
+
lead: lead,
|
101
|
+
|
102
|
+
message_id: message_id,
|
103
|
+
in_reply_to_id: in_reply_to_id,
|
104
|
+
object_key: stub.object_key,
|
105
|
+
|
106
|
+
subject: subject,
|
107
|
+
date: the_mail.date,
|
108
|
+
|
109
|
+
from: from,
|
110
|
+
froms: the_mail.from,
|
111
|
+
|
112
|
+
to: the_mail.to ? the_mail.to[0] : nil,
|
113
|
+
tos: the_mail.to,
|
114
|
+
|
115
|
+
cc: the_mail.cc ? the_mail.cc[0] : nil,
|
116
|
+
ccs: the_mail.cc,
|
117
|
+
})
|
118
|
+
|
119
|
+
## Parts
|
120
|
+
the_mail.parts.each do |part|
|
121
|
+
@message.churn_subpart( part )
|
122
|
+
end
|
123
|
+
@message.save
|
124
|
+
|
125
|
+
if the_mail.parts.length == 0
|
126
|
+
body = the_mail.body.decoded.encode('UTF-8', invalid: :replace, undef: :replace, replace: '?')
|
127
|
+
if the_mail.content_type&.include?('text/html')
|
128
|
+
@message.part_html = body
|
129
|
+
elsif the_mail.content_type&.include?('text/plain')
|
130
|
+
@message.part_txt = body
|
131
|
+
elsif the_mail.content_type.blank?
|
132
|
+
@message.part_txt = body
|
133
|
+
else
|
134
|
+
@message.logs.push "mail body of unknown type: #{the_mail.content_type}"
|
135
|
+
end
|
136
|
+
@message.save
|
137
|
+
end
|
138
|
+
|
139
|
+
## Attachments
|
140
|
+
the_mail.attachments.each do |att|
|
141
|
+
@message.save_attachment( att )
|
142
|
+
end
|
143
|
+
|
144
|
+
if !@message.save
|
145
|
+
puts! @message.errors.full_messages.join(", "), "Could not save @message"
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
conv.leads.push lead
|
150
|
+
conv.save
|
151
|
+
# lead.conversations.push conv
|
152
|
+
# lead.save
|
153
|
+
|
154
|
+
the_mail.cc&.each do |cc|
|
155
|
+
domain = cc.split('@')[1] rescue 'unknown.domain'
|
156
|
+
leadset = Wco::Leadset.find_or_create_by( company_url: domain )
|
157
|
+
Wco::Lead.find_or_create_by( email: cc, leadset: leadset )
|
158
|
+
end
|
159
|
+
|
160
|
+
conv.update_attributes({
|
161
|
+
status: WcoEmail::Conversation::STATUS_UNREAD,
|
162
|
+
latest_at: the_mail.date || Time.now.to_datetime,
|
163
|
+
from_emails: ( conv.from_emails + the_mail.from ).uniq,
|
164
|
+
preview: @message.preview_str,
|
165
|
+
})
|
166
|
+
|
167
|
+
##
|
168
|
+
## Tags
|
169
|
+
##
|
170
|
+
inbox_tag = Wco::Tag.inbox
|
171
|
+
conv.tags.push inbox_tag
|
172
|
+
conv.tags.push stub.tags
|
173
|
+
conv.save
|
174
|
+
# inbox_tag.conversations.push conv
|
175
|
+
# inbox_tag.save
|
176
|
+
|
177
|
+
|
178
|
+
## Actions & Filters
|
179
|
+
email_filters = WcoEmail::EmailFilter.active
|
180
|
+
email_filters.each do |filter|
|
181
|
+
if ( filter.from_regex.blank? || @message.from.match( filter.from_regex ) ) &&
|
182
|
+
( filter.from_exact.blank? || @message.from.downcase.include?( filter.from_exact&.downcase ) ) &&
|
183
|
+
( filter.body_exact.blank? || @message.part_html&.include?( filter.body_exact ) ) &&
|
184
|
+
( filter.subject_regex.blank? || @message.subject.match( filter.subject_regex ) ) &&
|
185
|
+
( filter.subject_exact.blank? || @message.subject.downcase.include?( filter.subject_exact&.downcase ) )
|
186
|
+
|
187
|
+
# || MiaTagger.analyze( @message.part_html, :is_spammy_recruite ).score > .5
|
188
|
+
|
189
|
+
puts! "applying filter #{filter} to conv #{conv}" if DEBUG
|
190
|
+
|
191
|
+
@message.apply_filter( filter )
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
stub.update_attributes({ status: WcoEmail::MessageStub::STATUS_PROCESSED })
|
196
|
+
|
197
|
+
## Notification
|
198
|
+
config = JSON.parse(stub.config)
|
199
|
+
if config['skip_notification']
|
200
|
+
;
|
201
|
+
else
|
202
|
+
conv = WcoEmail::Conversation.find( conv.id )
|
203
|
+
if conv.tags.include? inbox_tag
|
204
|
+
out = WcoEmail::ApplicationMailer.forwarder_notify( @message.id.to_s )
|
205
|
+
Rails.env.production? ? out.deliver_later : out.deliver_now
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
puts 'ok'
|
210
|
+
end
|
211
|
+
|
212
|
+
## This only saves a local message from mbox to s3.
|
213
|
+
def save_mbox_to_m3 message
|
36
214
|
the_mail = Mail.new(message)
|
37
215
|
key = the_mail.message_id || "no-key-#{Time.now.to_i}.#{rand(1000)}"
|
38
216
|
|
@@ -82,7 +260,7 @@ class WcoEmail::MessageStub
|
|
82
260
|
|
83
261
|
if message
|
84
262
|
if skip < @count
|
85
|
-
|
263
|
+
save_mbox_to_m3 message
|
86
264
|
print "#{@count}."
|
87
265
|
else
|
88
266
|
print "s-#{@count}."
|
@@ -98,7 +276,7 @@ class WcoEmail::MessageStub
|
|
98
276
|
|
99
277
|
if message
|
100
278
|
if skip < @count
|
101
|
-
|
279
|
+
save_mbox_to_m3 message
|
102
280
|
print "#{@count}."
|
103
281
|
else
|
104
282
|
print "s-#{@count}."
|
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.54
|
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-01-
|
11
|
+
date: 2024-01-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk-s3
|