mass-client 1.0.22 → 1.0.24
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/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
|