mass-client 1.0.22 → 1.0.24
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/base-line/profile.rb +153 -0
- data/lib/first-line/profile_rpa.rb +8 -109
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 960021fea3e8dc9a0735b20a24730083231b8109ec74dd738a3d8508ff5ced3a
|
4
|
+
data.tar.gz: 126df561fa20424d26c71d3b6b32000b7ae1ae72b6beda64bc37e9bfef56894b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 92bb76f6c2cd71c2b9d5cbcc84fce102c7c5ab2de8949e6dedf5a09d8f928e221563133049ff212d4d601ea317b714a77e0767016d9e671c3df365b6120fc06f
|
7
|
+
data.tar.gz: 402f6999e082f2bc4e90168915a165c2f336bd3547bbd360e909d07ddc879af3add9c3d1363a39198d7a5d4e443505d7adc1936840b93a58d2b6131d8144e149
|
data/lib/base-line/profile.rb
CHANGED
@@ -2,6 +2,159 @@ module Mass
|
|
2
2
|
class Profile < BlackStack::Base
|
3
3
|
attr_accessor :type
|
4
4
|
|
5
|
+
# DROPBOX LOCKFILE PARAMETERS
|
6
|
+
LOCKFILE_PATH = '/tmp/dropbox_upload.lock' # Path to your lockfile
|
7
|
+
LOCK_TIMEOUT = 5 # Maximum time in seconds to wait for the lock
|
8
|
+
|
9
|
+
# DROPBOX LOCKFILE FUNCTIONS
|
10
|
+
def acquire_lock
|
11
|
+
begin
|
12
|
+
Timeout.timeout(LOCK_TIMEOUT) do
|
13
|
+
# Wait until the lockfile can be created (i.e., it's not already taken)
|
14
|
+
while File.exist?(LOCKFILE_PATH)
|
15
|
+
sleep 0.1
|
16
|
+
end
|
17
|
+
# Create the lockfile
|
18
|
+
File.open(LOCKFILE_PATH, 'w') {}
|
19
|
+
end
|
20
|
+
rescue Timeout::Error
|
21
|
+
raise "Timeout while waiting for lockfile."
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def release_lock
|
26
|
+
File.delete(LOCKFILE_PATH) if File.exist?(LOCKFILE_PATH)
|
27
|
+
end
|
28
|
+
|
29
|
+
def upload_to_dropbox_with_lock(tmp_path, path)
|
30
|
+
acquire_lock
|
31
|
+
begin
|
32
|
+
# Upload the file to Dropbox
|
33
|
+
s = BlackStack::DropBox.dropbox_upload_file(tmp_path, path)
|
34
|
+
json = JSON.parse(s)
|
35
|
+
if json['is_downloadable'].nil? || !json['is_downloadable']
|
36
|
+
raise "Dropbox file upload failed. Dropbox response: #{s}"
|
37
|
+
end
|
38
|
+
rescue => e
|
39
|
+
raise "Error during upload: #{e.message}"
|
40
|
+
ensure
|
41
|
+
# Always release the lock, even if an error occurs
|
42
|
+
release_lock
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
#
|
48
|
+
#
|
49
|
+
|
50
|
+
# download image from Selenium using JavaScript and upload to Dropbox
|
51
|
+
# return the URL of the screenshot
|
52
|
+
#
|
53
|
+
# Parameters:
|
54
|
+
# - url: Internet address of the image to download from the website and upload to dropbox.
|
55
|
+
# - dropbox_folder: Dropbox folder name to store the image.
|
56
|
+
#
|
57
|
+
def download_image_0(url, dropbox_folder = nil)
|
58
|
+
raise "Either dropbox_folder parameter or self.desc['id_account'] are required." if dropbox_folder.nil? && self.desc['id_account'].nil?
|
59
|
+
dropbox_folder = self.desc['id_account'] if dropbox_folder.nil?
|
60
|
+
|
61
|
+
# Parameters
|
62
|
+
id = SecureRandom.uuid
|
63
|
+
|
64
|
+
# JavaScript to get base64 image data
|
65
|
+
js0 = "
|
66
|
+
function getImageBase64(imageSrc) {
|
67
|
+
return new Promise(async (resolve, reject) => {
|
68
|
+
try {
|
69
|
+
const response = await fetch(imageSrc);
|
70
|
+
const blob = await response.blob();
|
71
|
+
const reader = new FileReader();
|
72
|
+
reader.onloadend = function() {
|
73
|
+
resolve(reader.result);
|
74
|
+
};
|
75
|
+
reader.onerror = function(error) {
|
76
|
+
reject(error);
|
77
|
+
};
|
78
|
+
reader.readAsDataURL(blob);
|
79
|
+
} catch (error) {
|
80
|
+
reject(error);
|
81
|
+
}
|
82
|
+
});
|
83
|
+
}
|
84
|
+
return getImageBase64('#{url}');
|
85
|
+
"
|
86
|
+
|
87
|
+
# Execute JavaScript and get base64 image data
|
88
|
+
base64_image = driver.execute_script(js0)
|
89
|
+
raise "Failed to retrieve image data from URL: #{url}" if base64_image.nil?
|
90
|
+
|
91
|
+
# Extract MIME type and base64 data
|
92
|
+
mime_type_match = base64_image.match(/^data:image\/([a-zA-Z0-9.+-]+);base64,/)
|
93
|
+
if mime_type_match
|
94
|
+
mime_subtype = mime_type_match[1] # e.g., 'png', 'jpeg', 'gif'
|
95
|
+
# Map common MIME subtypes to file extensions
|
96
|
+
extension = case mime_subtype
|
97
|
+
when 'jpeg' then 'jpg'
|
98
|
+
else mime_subtype
|
99
|
+
end
|
100
|
+
# Remove the data URL prefix
|
101
|
+
image_data = base64_image.sub(/^data:image\/[a-zA-Z0-9.+-]+;base64,/, '')
|
102
|
+
else
|
103
|
+
raise "Unsupported or invalid image data format."
|
104
|
+
end
|
105
|
+
|
106
|
+
# Update filename and paths
|
107
|
+
filename = "#{id}.#{extension}"
|
108
|
+
tmp_paths = if Mass.download_path.is_a?(String)
|
109
|
+
["#{Mass.download_path}/#{filename}"]
|
110
|
+
elsif Mass.download_path.is_a?(Array)
|
111
|
+
Mass.download_path.map { |s| "#{s}/#{filename}" }
|
112
|
+
else
|
113
|
+
raise "Invalid Mass.download_path configuration."
|
114
|
+
end
|
115
|
+
|
116
|
+
# Save the image to the first available path
|
117
|
+
tmp_path = tmp_paths.find { |path| File.writable?(File.dirname(path)) }
|
118
|
+
raise "No writable path found in #{tmp_paths.join(', ')}." if tmp_path.nil?
|
119
|
+
|
120
|
+
File.open(tmp_path, 'wb') do |file|
|
121
|
+
file.write(Base64.decode64(image_data))
|
122
|
+
end
|
123
|
+
|
124
|
+
# Proceed with Dropbox operations
|
125
|
+
year = Time.now.year.to_s.rjust(4, '0')
|
126
|
+
month = Time.now.month.to_s.rjust(2, '0')
|
127
|
+
folder = "/massprospecting.rpa/#{dropbox_folder}.#{year}.#{month}"
|
128
|
+
path = "#{folder}/#{filename}"
|
129
|
+
BlackStack::DropBox.dropbox_create_folder(folder)
|
130
|
+
|
131
|
+
# Upload the file to Dropbox
|
132
|
+
upload_to_dropbox_with_lock(tmp_path, path)
|
133
|
+
|
134
|
+
# Delete the local file
|
135
|
+
File.delete(tmp_path)
|
136
|
+
|
137
|
+
# Return the URL of the file in Dropbox
|
138
|
+
#
|
139
|
+
# Add a timeout to wait the file is present in the cloud.
|
140
|
+
# Reference: https://github.com/MassProspecting/docs/issues/320
|
141
|
+
self.wait_for_dropbox_url(path).gsub('&dl=1', '&dl=0')
|
142
|
+
end
|
143
|
+
|
144
|
+
# download image from Selenium using JavaScript and upload to Dropbox
|
145
|
+
# return the URL of the screenshot
|
146
|
+
#
|
147
|
+
# Parameters:
|
148
|
+
# - img: Selenium image element to download from the website and upload to dropbox.
|
149
|
+
# - dropbox_folder: Dropbox folder name to store the image.
|
150
|
+
#
|
151
|
+
def download_image(img, dropbox_folder=nil)
|
152
|
+
download_image_0(img.attribute('src'), dropbox_folder)
|
153
|
+
end # def download_image
|
154
|
+
|
155
|
+
#
|
156
|
+
#
|
157
|
+
#
|
5
158
|
def self.object_name
|
6
159
|
'profile'
|
7
160
|
end
|
@@ -1,8 +1,10 @@
|
|
1
1
|
module Mass
|
2
2
|
class ProfileRPA < Mass::Profile
|
3
|
+
|
3
4
|
@@buffer_driver = nil
|
4
5
|
attr_accessor :headless
|
5
6
|
|
7
|
+
# SELENIUM FUNCTIONS
|
6
8
|
def self.buffer_driver
|
7
9
|
@@buffer_driver
|
8
10
|
end
|
@@ -218,14 +220,14 @@ module Mass
|
|
218
220
|
#
|
219
221
|
# @return [String] The URL of the file in Dropbox, with the `&dl=1` parameter
|
220
222
|
# replaced by `&dl=0`.
|
221
|
-
# @
|
223
|
+
# @return nil If the file is not available within the specified
|
222
224
|
# maximum wait time, raises an error with a timeout message.
|
223
225
|
#
|
224
226
|
# @example
|
225
227
|
# wait_for_dropbox_url('/path/to/file', max_wait: 60, interval: 3)
|
226
228
|
# # => "https://www.dropbox.com/s/yourfile?dl=0"
|
227
229
|
#
|
228
|
-
def wait_for_dropbox_url(path, max_wait:
|
230
|
+
def wait_for_dropbox_url(path, max_wait: 5, interval: 2)
|
229
231
|
start_time = Time.now
|
230
232
|
|
231
233
|
loop do
|
@@ -235,7 +237,8 @@ module Mass
|
|
235
237
|
rescue => e
|
236
238
|
# Check if the timeout has been exceeded
|
237
239
|
if Time.now - start_time > max_wait
|
238
|
-
raise "Timeout exceeded while waiting for Dropbox file (#{path}): #{e.message}"
|
240
|
+
#raise "Timeout exceeded while waiting for Dropbox file (#{path}): #{e.message}"
|
241
|
+
return nil
|
239
242
|
end
|
240
243
|
|
241
244
|
# Wait for a short interval before retrying
|
@@ -244,110 +247,6 @@ module Mass
|
|
244
247
|
end
|
245
248
|
end
|
246
249
|
|
247
|
-
# download image from Selenium using JavaScript and upload to Dropbox
|
248
|
-
# return the URL of the screenshot
|
249
|
-
#
|
250
|
-
# Parameters:
|
251
|
-
# - url: Internet address of the image to download from the website and upload to dropbox.
|
252
|
-
# - dropbox_folder: Dropbox folder name to store the image.
|
253
|
-
#
|
254
|
-
def download_image_0(url, dropbox_folder = nil)
|
255
|
-
raise "Either dropbox_folder parameter or self.desc['id_account'] are required." if dropbox_folder.nil? && self.desc['id_account'].nil?
|
256
|
-
dropbox_folder = self.desc['id_account'] if dropbox_folder.nil?
|
257
|
-
|
258
|
-
# Parameters
|
259
|
-
id = SecureRandom.uuid
|
260
|
-
|
261
|
-
# JavaScript to get base64 image data
|
262
|
-
js0 = "
|
263
|
-
function getImageBase64(imageSrc) {
|
264
|
-
return new Promise(async (resolve, reject) => {
|
265
|
-
try {
|
266
|
-
const response = await fetch(imageSrc);
|
267
|
-
const blob = await response.blob();
|
268
|
-
const reader = new FileReader();
|
269
|
-
reader.onloadend = function() {
|
270
|
-
resolve(reader.result);
|
271
|
-
};
|
272
|
-
reader.onerror = function(error) {
|
273
|
-
reject(error);
|
274
|
-
};
|
275
|
-
reader.readAsDataURL(blob);
|
276
|
-
} catch (error) {
|
277
|
-
reject(error);
|
278
|
-
}
|
279
|
-
});
|
280
|
-
}
|
281
|
-
return getImageBase64('#{url}');
|
282
|
-
"
|
283
|
-
|
284
|
-
# Execute JavaScript and get base64 image data
|
285
|
-
base64_image = driver.execute_script(js0)
|
286
|
-
raise "Failed to retrieve image data from URL: #{url}" if base64_image.nil?
|
287
|
-
|
288
|
-
# Extract MIME type and base64 data
|
289
|
-
mime_type_match = base64_image.match(/^data:image\/([a-zA-Z0-9.+-]+);base64,/)
|
290
|
-
if mime_type_match
|
291
|
-
mime_subtype = mime_type_match[1] # e.g., 'png', 'jpeg', 'gif'
|
292
|
-
# Map common MIME subtypes to file extensions
|
293
|
-
extension = case mime_subtype
|
294
|
-
when 'jpeg' then 'jpg'
|
295
|
-
else mime_subtype
|
296
|
-
end
|
297
|
-
# Remove the data URL prefix
|
298
|
-
image_data = base64_image.sub(/^data:image\/[a-zA-Z0-9.+-]+;base64,/, '')
|
299
|
-
else
|
300
|
-
raise "Unsupported or invalid image data format."
|
301
|
-
end
|
302
|
-
|
303
|
-
# Update filename and paths
|
304
|
-
filename = "#{id}.#{extension}"
|
305
|
-
tmp_paths = if Mass.download_path.is_a?(String)
|
306
|
-
["#{Mass.download_path}/#{filename}"]
|
307
|
-
elsif Mass.download_path.is_a?(Array)
|
308
|
-
Mass.download_path.map { |s| "#{s}/#{filename}" }
|
309
|
-
else
|
310
|
-
raise "Invalid Mass.download_path configuration."
|
311
|
-
end
|
312
|
-
|
313
|
-
# Save the image to the first available path
|
314
|
-
tmp_path = tmp_paths.find { |path| File.writable?(File.dirname(path)) }
|
315
|
-
raise "No writable path found in #{tmp_paths.join(', ')}." if tmp_path.nil?
|
316
|
-
|
317
|
-
File.open(tmp_path, 'wb') do |file|
|
318
|
-
file.write(Base64.decode64(image_data))
|
319
|
-
end
|
320
|
-
|
321
|
-
# Proceed with Dropbox operations
|
322
|
-
year = Time.now.year.to_s.rjust(4, '0')
|
323
|
-
month = Time.now.month.to_s.rjust(2, '0')
|
324
|
-
folder = "/massprospecting.rpa/#{dropbox_folder}.#{year}.#{month}"
|
325
|
-
path = "#{folder}/#{filename}"
|
326
|
-
BlackStack::DropBox.dropbox_create_folder(folder)
|
327
|
-
|
328
|
-
# Upload the file to Dropbox
|
329
|
-
BlackStack::DropBox.dropbox_upload_file(tmp_path, path)
|
330
|
-
# Delete the local file
|
331
|
-
File.delete(tmp_path)
|
332
|
-
|
333
|
-
# Return the URL of the file in Dropbox
|
334
|
-
#
|
335
|
-
# Add a timeout to wait the file is present in the cloud.
|
336
|
-
# Reference: https://github.com/MassProspecting/docs/issues/320
|
337
|
-
self.wait_for_dropbox_url(path).gsub('&dl=1', '&dl=0')
|
338
|
-
end
|
339
|
-
|
340
|
-
# download image from Selenium using JavaScript and upload to Dropbox
|
341
|
-
# return the URL of the screenshot
|
342
|
-
#
|
343
|
-
# Parameters:
|
344
|
-
# - img: Selenium image element to download from the website and upload to dropbox.
|
345
|
-
# - dropbox_folder: Dropbox folder name to store the image.
|
346
|
-
#
|
347
|
-
def download_image(img, dropbox_folder=nil)
|
348
|
-
download_image_0(img.attribute('src'), dropbox_folder)
|
349
|
-
end # def download_image
|
350
|
-
|
351
250
|
# take screenshot and upload it to dropbox
|
352
251
|
# return the URL of the screenshot
|
353
252
|
def screenshot(dropbox_folder=nil)
|
@@ -365,7 +264,7 @@ module Mass
|
|
365
264
|
folder = "/massprospecting.rpa/#{dropbox_folder}.#{year}.#{month}"
|
366
265
|
path = "#{folder}/#{filename}"
|
367
266
|
BlackStack::DropBox.dropbox_create_folder(folder)
|
368
|
-
|
267
|
+
upload_to_dropbox_with_lock(tmp_path, path)
|
369
268
|
File.delete(tmp_path)
|
370
269
|
BlackStack::DropBox.get_file_url(path).gsub('&dl=1', '&dl=0')
|
371
270
|
end # def screenshot
|
@@ -387,7 +286,7 @@ module Mass
|
|
387
286
|
folder = "/massprospecting.bots/#{dropbox_folder}.#{year}.#{month}"
|
388
287
|
path = "#{folder}/#{filename}"
|
389
288
|
BlackStack::DropBox.dropbox_create_folder(folder)
|
390
|
-
|
289
|
+
upload_to_dropbox_with_lock(tmp_path, path)
|
391
290
|
File.delete(tmp_path)
|
392
291
|
BlackStack::DropBox.get_file_url(path).gsub('&dl=1', '&dl=0')
|
393
292
|
end # def snapshot
|