Class: Mass::Profile
- Inherits:
-
BlackStack::Base
- Object
- BlackStack::Base
- Mass::Profile
- Defined in:
- lib/base-line/profile.rb
Direct Known Subclasses
Constant Summary collapse
- LOCKFILE_PATH =
DROPBOX LOCKFILE PARAMETERS
'/tmp/dropbox_upload.lock'
- LOCK_TIMEOUT =
Path to your lockfile
60
Instance Attribute Summary collapse
-
#type ⇒ Object
Returns the value of attribute type.
Class Method Summary collapse
Instance Method Summary collapse
-
#acquire_lock ⇒ Object
DROPBOX LOCKFILE FUNCTIONS.
-
#child_class_instance ⇒ Object
crate an instance of the profile type using the class defined in the ‘desc` attribute.
-
#class_name_from_profile_type ⇒ Object
convert the profile_type into the ruby class to create an instance.
-
#connectioncheck(limit: 100, logger: nil) ⇒ Object
Scrape the inbox of the profile.
-
#create_s3_folder(folder_name) ⇒ Object
Function to create a folder in S3.
-
#download_image(img, dropbox_folder = nil) ⇒ Object
download image from Selenium using JavaScript and upload to Dropbox return the URL of the screenshot.
-
#download_image_0(url, dropbox_folder = nil) ⇒ Object
download image from Selenium using JavaScript and upload to Dropbox return the URL of the screenshot.
-
#inboxcheck(limit: 100, only_unread: true, logger: nil) ⇒ Object
Scrape the inbox of the profile.
-
#initialize(h) ⇒ Profile
constructor
A new instance of Profile.
- #release_lock ⇒ Object
-
#running? ⇒ Boolean
return true of the profile is running if its profile type is rpa-access, then it will return true if the browser is running.
-
#upload_file_to_s3(file_path, s3_key) ⇒ Object
Function to upload a file to Amazon S3 and get its public URL.
Constructor Details
#initialize(h) ⇒ Profile
Returns a new instance of Profile.
168 169 170 171 |
# File 'lib/base-line/profile.rb', line 168 def initialize(h) super(h) self.type = Mass::ProfileType.new(h['profile_type_desc']).child_class_instance end |
Instance Attribute Details
#type ⇒ Object
Returns the value of attribute type.
3 4 5 |
# File 'lib/base-line/profile.rb', line 3 def type @type end |
Class Method Details
.object_name ⇒ Object
164 165 166 |
# File 'lib/base-line/profile.rb', line 164 def self.object_name 'profile' end |
Instance Method Details
#acquire_lock ⇒ Object
DROPBOX LOCKFILE FUNCTIONS
10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# File 'lib/base-line/profile.rb', line 10 def acquire_lock begin Timeout.timeout(LOCK_TIMEOUT) do # Wait until the lockfile can be created (i.e., it's not already taken) while File.exist?(LOCKFILE_PATH) sleep 0.1 end # Create the lockfile File.open(LOCKFILE_PATH, 'w') {} end rescue Timeout::Error raise "Timeout while waiting for lockfile." end end |
#child_class_instance ⇒ Object
crate an instance of the profile type using the class defined in the ‘desc` attribute. override the base method
182 183 184 185 186 187 188 |
# File 'lib/base-line/profile.rb', line 182 def child_class_instance profile_type = self.desc['profile_type'] key = self.class_name_from_profile_type raise "Source code of profile type #{profile_type} not found. Create a class #{key} in the folder `/lib` of your mass-sdk." unless Kernel.const_defined?(key) ret = Kernel.const_get(key).new(self.desc) return ret end |
#class_name_from_profile_type ⇒ Object
convert the profile_type into the ruby class to create an instance. example: Apollo –> Mass::ApolloAPI
175 176 177 178 |
# File 'lib/base-line/profile.rb', line 175 def class_name_from_profile_type profile_type = self.desc['profile_type'] "Mass::#{profile_type}" end |
#connectioncheck(limit: 100, logger: nil) ⇒ Object
Scrape the inbox of the profile. Return a an array of hash descriptors of outreach records.
Parameters:
-
limit: the maximum number of connections to scrape. Default: 100.
-
logger: a logger object to log the process. Default: nil.
Example of a hash descritor into the returned array: “‘
# a scraped message is always a :performed message
'status' => :performed,
# what is the outreach type?
# e.g.: :LinkedIn_ConnectionRequest
# decide this in the child class.
'outreach_type' => nil,
# hash descriptor of the profile who is scraping the inbox
'profile' => self.desc,
# hash descriptor of the lead who is the conversation partner
'lead' => nil,
# if the message has been sent by the profile, it is :outgoing.
# if the message has been sent by the lead, it is :incoming.
'direction' => :accepted,
“‘
261 262 263 |
# File 'lib/base-line/profile.rb', line 261 def connectioncheck(limit: 100, logger:nil) [] end |
#create_s3_folder(folder_name) ⇒ Object
Function to create a folder in S3
44 45 46 47 48 49 50 |
# File 'lib/base-line/profile.rb', line 44 def create_s3_folder(folder_name) Mass.s3.put_object( bucket: Mass.s3_bucket, key: "#{folder_name}/" ) return true end |
#download_image(img, dropbox_folder = nil) ⇒ Object
download image from Selenium using JavaScript and upload to Dropbox return the URL of the screenshot
Parameters:
-
img: Selenium image element to download from the website and upload to dropbox.
-
dropbox_folder: Dropbox folder name to store the image.
157 158 159 |
# File 'lib/base-line/profile.rb', line 157 def download_image(img, dropbox_folder=nil) download_image_0(img.attribute('src'), dropbox_folder) end |
#download_image_0(url, dropbox_folder = nil) ⇒ Object
download image from Selenium using JavaScript and upload to Dropbox return the URL of the screenshot
Parameters:
-
url: Internet address of the image to download from the website and upload to dropbox.
-
dropbox_folder: Dropbox folder name to store the image.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/base-line/profile.rb', line 63 def download_image_0(url, dropbox_folder = nil) raise "Either dropbox_folder parameter or self.desc['id_account'] are required." if dropbox_folder.nil? && self.desc['id_account'].nil? dropbox_folder = self.desc['id_account'] if dropbox_folder.nil? # Parameters id = SecureRandom.uuid # JavaScript to get base64 image data js0 = " function getImageBase64(imageSrc) { return new Promise(async (resolve, reject) => { try { const response = await fetch(imageSrc); const blob = await response.blob(); const reader = new FileReader(); reader.onloadend = function() { resolve(reader.result); }; reader.onerror = function(error) { reject(error); }; reader.readAsDataURL(blob); } catch (error) { reject(error); } }); } return getImageBase64('#{url}'); " # Execute JavaScript and get base64 image data base64_image = driver.execute_script(js0) raise "Failed to retrieve image data from URL: #{url}" if base64_image.nil? # Extract MIME type and base64 data mime_type_match = base64_image.match(/^data:image\/([a-zA-Z0-9.+-]+);base64,/) if mime_type_match mime_subtype = mime_type_match[1] # e.g., 'png', 'jpeg', 'gif' # Map common MIME subtypes to file extensions extension = case mime_subtype when 'jpeg' then 'jpg' else mime_subtype end # Remove the data URL prefix image_data = base64_image.sub(/^data:image\/[a-zA-Z0-9.+-]+;base64,/, '') else raise "Unsupported or invalid image data format." end # Update filename and paths filename = "#{id}.#{extension}" tmp_paths = if Mass.download_path.is_a?(String) ["#{Mass.download_path}/#{filename}"] elsif Mass.download_path.is_a?(Array) Mass.download_path.map { |s| "#{s}/#{filename}" } else raise "Invalid Mass.download_path configuration." end # Save the image to the first available path tmp_path = tmp_paths.find { |path| File.writable?(File.dirname(path)) } raise "No writable path found in #{tmp_paths.join(', ')}." if tmp_path.nil? File.open(tmp_path, 'wb') do |file| file.write(Base64.decode64(image_data)) end # Proceed with Dropbox operations year = Time.now.year.to_s.rjust(4, '0') month = Time.now.month.to_s.rjust(2, '0') folder = dropbox_folder #"/massprospecting.rpa/#{dropbox_folder}.#{year}.#{month}" path = "#{folder}/#{filename}" create_s3_folder(folder) # Upload the file to Dropbox ret = upload_file_to_s3(tmp_path, path) # Delete the local file File.delete(tmp_path) # Return the URL of the file in Dropbox # # Add a timeout to wait the file is present in the cloud. # Reference: https://github.com/MassProspecting/docs/issues/320 ret end |
#inboxcheck(limit: 100, only_unread: true, logger: nil) ⇒ Object
Scrape the inbox of the profile. Return a an array of hash descriptors of outreach records.
Parameters:
-
limit: the maximum number of messages to scrape. Default: 100.
-
only_unread: if true, then only the unread messages will be scraped. Default: true.
-
logger: a logger object to log the process. Default: nil.
Example of a hash descritor into the returned array: “‘
# a scraped message is always a :performed message
'status' => :performed,
# what is the outreach type?
# e.g.: :LinkedIn_DirectMessage
# decide this in the child class.
'outreach_type' => nil,
# hash descriptor of the profile who is scraping the inbox
'profile' => self.desc,
# hash descriptor of the lead who is the conversation partner
'lead' => nil,
# if the message has been sent by the profile, it is :outgoing.
# if the message has been sent by the lead, it is :incoming.
'direction' => nil,
# the content of the message
'subject' => nil,
'body' => nil,
“‘
231 232 233 |
# File 'lib/base-line/profile.rb', line 231 def inboxcheck(limit: 100, only_unread:true, logger:nil) [] end |
#release_lock ⇒ Object
25 26 27 |
# File 'lib/base-line/profile.rb', line 25 def release_lock File.delete(LOCKFILE_PATH) if File.exist?(LOCKFILE_PATH) end |
#running? ⇒ Boolean
return true of the profile is running if its profile type is rpa-access, then it will return true if the browser is running. else, it will return always true.
193 194 195 196 197 198 199 |
# File 'lib/base-line/profile.rb', line 193 def running? if self.type.desc['access'].to_sym == :rpa c = AdsPowerClient.new(key: ADSPOWER_API_KEY) return c.check(self.desc['ads_power_id']) end return true end |
#upload_file_to_s3(file_path, s3_key) ⇒ Object
Function to upload a file to Amazon S3 and get its public URL
30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/base-line/profile.rb', line 30 def upload_file_to_s3(file_path, s3_key) # Upload the file Mass.s3.put_object( bucket: Mass.s3_bucket, key: s3_key, body: File.open(file_path) ) # Generate the public URL public_url = "https://#{Mass.s3_bucket}.s3.amazonaws.com/#{s3_key}" # return return public_url end |