mass-client 1.0.1
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 +7 -0
- data/lib/base-line/channel.rb +7 -0
- data/lib/base-line/company.rb +7 -0
- data/lib/base-line/connectioncheck.rb +14 -0
- data/lib/base-line/data_type.rb +8 -0
- data/lib/base-line/enrichment.rb +51 -0
- data/lib/base-line/enrichment_type.rb +60 -0
- data/lib/base-line/event.rb +15 -0
- data/lib/base-line/headcount.rb +7 -0
- data/lib/base-line/inboxcheck.rb +14 -0
- data/lib/base-line/industry.rb +7 -0
- data/lib/base-line/job.rb +60 -0
- data/lib/base-line/lead.rb +7 -0
- data/lib/base-line/location.rb +7 -0
- data/lib/base-line/outreach.rb +42 -0
- data/lib/base-line/outreach_type.rb +76 -0
- data/lib/base-line/profile.rb +108 -0
- data/lib/base-line/profile_type.rb +10 -0
- data/lib/base-line/request.rb +40 -0
- data/lib/base-line/revenue.rb +7 -0
- data/lib/base-line/rule.rb +7 -0
- data/lib/base-line/source.rb +187 -0
- data/lib/base-line/source_type.rb +24 -0
- data/lib/base-line/tag.rb +7 -0
- data/lib/first-line/profile_api.rb +7 -0
- data/lib/first-line/profile_mta.rb +147 -0
- data/lib/first-line/profile_rpa.rb +375 -0
- data/lib/mass-client.rb +53 -0
- metadata +209 -0
@@ -0,0 +1,375 @@
|
|
1
|
+
module Mass
|
2
|
+
class ProfileRPA < Mass::Profile
|
3
|
+
@@buffer_driver = nil
|
4
|
+
attr_accessor :headless
|
5
|
+
|
6
|
+
def self.buffer_driver
|
7
|
+
@@buffer_driver
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.buffer_driver=(o)
|
11
|
+
@@buffer_driver = o
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(desc)
|
15
|
+
super(desc)
|
16
|
+
headless = true
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.domain
|
20
|
+
raise "Method domain of ProfileRPA must be implemented on each child class."
|
21
|
+
end
|
22
|
+
|
23
|
+
# resolving the redirection from facebook_2 to facebook, or linkedin_2 to
|
24
|
+
# more infromation here: https://github.com/VyMECO/mass.public/issues/93
|
25
|
+
#
|
26
|
+
# Parameters:
|
27
|
+
# - lead_descriptor: hash descriptor of a lead
|
28
|
+
# - field_1: field for storing the URL type 1 that must be realized.
|
29
|
+
# - field_2: field for storing the URL type 2 that redirets to the URL type .
|
30
|
+
# - logger: object to write log. Optional. Default: nil.
|
31
|
+
#
|
32
|
+
def resolve_dual_url(lead_descriptor,
|
33
|
+
field_1:,
|
34
|
+
field_2:,
|
35
|
+
logger: nil
|
36
|
+
)
|
37
|
+
l = logger || BlackStack::DummyLogger.new(nil)
|
38
|
+
k = lead_descriptor
|
39
|
+
|
40
|
+
l.logs "Resolving dual-url redirection #{k[field_2].to_s.blue}... "
|
41
|
+
if !k[field_2].nil? && k[field_1].nil?
|
42
|
+
h_filters = {}
|
43
|
+
h_filters[field_2.to_s] = k[field_2]
|
44
|
+
lead = Mass::Lead.page(
|
45
|
+
page: 1,
|
46
|
+
limit: 1,
|
47
|
+
filters: h_filters
|
48
|
+
).first
|
49
|
+
if lead
|
50
|
+
l.logf 'done'.green + " (field_2 already registered in the database.)"
|
51
|
+
else
|
52
|
+
driver.get(k[field_2])
|
53
|
+
sleep(5)
|
54
|
+
k[field_1] = driver.current_url
|
55
|
+
#ret.select { |k2| k2['lead'][field_2] == }
|
56
|
+
l.logf 'done'.green + " (#{k[field_1].to_s.blue})"
|
57
|
+
end
|
58
|
+
else
|
59
|
+
if k[field_2].nil?
|
60
|
+
l.logf 'skip'.yellow + " (no field_2)"
|
61
|
+
else
|
62
|
+
l.logf 'skip'.yellow + " (no dual-url redirection needed)"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end # def resolve_dual_url
|
66
|
+
|
67
|
+
# for internal use only. users should call `send_request` instead.
|
68
|
+
def close_popups(logger:nil)
|
69
|
+
raise "Method close_popups of ProfileRPA must be implemented on each child class."
|
70
|
+
end # def close_popups
|
71
|
+
|
72
|
+
# start the adspower server for headless mode, if it is not already started and if headless is activated.
|
73
|
+
def self.start_headless_server(headless: true, logger:nil)
|
74
|
+
l = logger || BlackStack::DummyLogger.new(nil)
|
75
|
+
# check if the rpa.rb process is running manually
|
76
|
+
l.logs "Starting AdsPower headless server?... "
|
77
|
+
unless headless
|
78
|
+
l.logf "no".yellow + " (headless is disabled in the command line)"
|
79
|
+
else
|
80
|
+
l.logf "yes".green + " (headless is enabled)"
|
81
|
+
|
82
|
+
# creating an AdsPower client
|
83
|
+
l.logs "Creating AdsPower client... "
|
84
|
+
c = AdsPowerClient.new(key: ADSPOWER_API_KEY)
|
85
|
+
l.logf 'done'.green
|
86
|
+
|
87
|
+
# starting adspower server
|
88
|
+
l.logs "Is headless server already running?... "
|
89
|
+
if c.online?
|
90
|
+
l.logf "yes".green
|
91
|
+
else
|
92
|
+
l.logf "no".yellow
|
93
|
+
|
94
|
+
l.logs "Starting AdsPower server... "
|
95
|
+
c.server_start
|
96
|
+
l.logf 'done'.green
|
97
|
+
end
|
98
|
+
end # if parser.value('manual')
|
99
|
+
end
|
100
|
+
|
101
|
+
# stop the adspower server for headless mode, if it is not already stopped and if headless is activated.
|
102
|
+
def self.clear_driver
|
103
|
+
self.class.buffer_driver = nil
|
104
|
+
end
|
105
|
+
|
106
|
+
# close all tabs except one
|
107
|
+
# do this only if there are more than one tab
|
108
|
+
# do this in order to avoid the browser show up if it is not necesasry.
|
109
|
+
def one_tab
|
110
|
+
handles = self.class.buffer_driver.window_handles
|
111
|
+
if handles.size > 1
|
112
|
+
chosen = handles.pop
|
113
|
+
handles.each { |handle|
|
114
|
+
self.class.buffer_driver.switch_to.window(handle)
|
115
|
+
self.class.buffer_driver.close # don't use quit, because you don't want to kill the chromedriver
|
116
|
+
}
|
117
|
+
self.class.buffer_driver.switch_to.window(chosen)
|
118
|
+
end
|
119
|
+
end # def one_tab
|
120
|
+
=begin
|
121
|
+
# scroll down n times
|
122
|
+
def scroll_down(n)
|
123
|
+
driver = self.driver
|
124
|
+
i = 0
|
125
|
+
while (i<n)
|
126
|
+
i += 1
|
127
|
+
step = self.desc['scrolling_step'] + rand(self.desc['scrolling_step_random'].to_i)
|
128
|
+
|
129
|
+
# scroll down to the 3th post
|
130
|
+
#
|
131
|
+
driver.execute_script("window.scrollBy(0, #{i*1000});");
|
132
|
+
|
133
|
+
# add delay to wait for the AJAX
|
134
|
+
#
|
135
|
+
sleep(10+rand(5))
|
136
|
+
end
|
137
|
+
end # def scroll_down
|
138
|
+
=end
|
139
|
+
# Allow or Block a site to perform multiple downloads.
|
140
|
+
# Parameters:
|
141
|
+
# - status: :allow or :block
|
142
|
+
# - domain: the domain of the site to allow or block.
|
143
|
+
# - secure: true or false
|
144
|
+
# - www: true or false
|
145
|
+
#
|
146
|
+
# Reference:
|
147
|
+
# - https://github.com/VyMECO/mass/issues/43
|
148
|
+
# - https://stackoverflow.com/questions/66659465/python-manually-config-chrome-settings-by-selenium-remotedriver
|
149
|
+
#
|
150
|
+
def automatic_downloads(
|
151
|
+
status:,
|
152
|
+
domain:,
|
153
|
+
secure:true,
|
154
|
+
www:true
|
155
|
+
)
|
156
|
+
err = []
|
157
|
+
err << "The status must be :allow or :block." if ![:allow, :block].include?(status)
|
158
|
+
err << "#{domain.to_s} is not a valid domain" if !domain.to_s.valid_domain?
|
159
|
+
raise err.join("\n") if err.size > 0
|
160
|
+
|
161
|
+
site_url = secure ? "https://" : "http://"
|
162
|
+
site_url += www ? "www." : ""
|
163
|
+
site_url += domain.to_s
|
164
|
+
site_url += secure ? ":443" : ""
|
165
|
+
|
166
|
+
url = "chrome://settings/content/siteDetails?site=#{CGI.escape(site_url)}"
|
167
|
+
self.driver.get(url)
|
168
|
+
temp = self.driver.execute_script("return document.querySelector('settings-ui').shadowRoot.querySelector('settings-main#main').shadowRoot.querySelector('settings-basic-page')")
|
169
|
+
rules = self.driver.execute_script("return arguments[0].shadowRoot.querySelector('settings-privacy-page').shadowRoot.querySelector('settings-animated-pages#pages settings-subpage site-details').shadowRoot.querySelector('div.list-frame:not(div>div.list-frame)')", temp)
|
170
|
+
automaticDownloads = self.driver.execute_script("return arguments[0].querySelector('site-details-permission[label=\"Automatic downloads\"]').shadowRoot.querySelector('#permission')", rules)
|
171
|
+
|
172
|
+
self.driver.execute_script("arguments[0].scrollIntoView()", automaticDownloads)
|
173
|
+
automaticDownloads.click()
|
174
|
+
automaticDownloads.find_element(:id => status.to_s).click()
|
175
|
+
end # def automatic_downloads
|
176
|
+
|
177
|
+
# download image from Selenium using JavaScript and upload to Dropbox
|
178
|
+
# return the URL of the screenshot
|
179
|
+
#
|
180
|
+
# Parameters:
|
181
|
+
# - url: Internet address of the image to download from the website and upload to dropbox.
|
182
|
+
# - dropbox_folder: Dropbox folder name to store the image.
|
183
|
+
#
|
184
|
+
def download_image_0(url, dropbox_folder=nil)
|
185
|
+
raise "Either dropbox_folder parameter or self.desc['id_account'] are required." if dropbox_folder.nil? && self.desc['id_account'].nil?
|
186
|
+
dropbox_folder = self.desc['id_account'] if dropbox_folder.nil?
|
187
|
+
# parameters
|
188
|
+
id = SecureRandom.uuid
|
189
|
+
filename = "#{id}.png"
|
190
|
+
tmp_path = ["#{Mass.download_path}/#{filename}"] if Mass.download_path.is_a?(String)
|
191
|
+
tmp_paths = Mass.download_path.map { |s| "#{s}/#{filename}" } if Mass.download_path.is_a?(Array)
|
192
|
+
|
193
|
+
# excute JavaScript function downloadImage with the parameter src
|
194
|
+
|
195
|
+
# this function is to download images from the same browser, using the proxy of the browser.
|
196
|
+
# never download images from the server, because sites can track the IP.
|
197
|
+
js0 = "
|
198
|
+
async function downloadImage(imageSrc, filename) {
|
199
|
+
const image = await fetch(imageSrc)
|
200
|
+
const imageBlog = await image.blob()
|
201
|
+
const imageURL = URL.createObjectURL(imageBlog)
|
202
|
+
|
203
|
+
const link = document.createElement('a')
|
204
|
+
link.href = imageURL
|
205
|
+
link.download = filename
|
206
|
+
document.body.appendChild(link)
|
207
|
+
link.click()
|
208
|
+
document.body.removeChild(link)
|
209
|
+
}
|
210
|
+
downloadImage('#{url}', '#{filename}')
|
211
|
+
"
|
212
|
+
driver.execute_script(js0)
|
213
|
+
|
214
|
+
# code
|
215
|
+
year = Time.now.year.to_s.rjust(4,'0')
|
216
|
+
month = Time.now.month.to_s.rjust(2,'0')
|
217
|
+
folder = "/massprospecting.rpa/#{dropbox_folder}.#{year}.#{month}"
|
218
|
+
path = "#{folder}/#{filename}"
|
219
|
+
BlackStack::DropBox.dropbox_create_folder(folder)
|
220
|
+
|
221
|
+
# find the tmp_path that exists
|
222
|
+
tmp_path = nil
|
223
|
+
tmp_paths.each { |s|
|
224
|
+
if File.exist?(s)
|
225
|
+
tmp_path = s
|
226
|
+
break
|
227
|
+
end
|
228
|
+
}
|
229
|
+
raise "The file #{filename} was not downloaded." if tmp_path.nil?
|
230
|
+
|
231
|
+
# upload the file to dropbox
|
232
|
+
BlackStack::DropBox.dropbox_upload_file(tmp_path, path)
|
233
|
+
# delete the file
|
234
|
+
File.delete(tmp_path)
|
235
|
+
# return the URL of the file in dropbox
|
236
|
+
BlackStack::DropBox.get_file_url(path).gsub('&dl=1', '&dl=0')
|
237
|
+
end # def download_image_0
|
238
|
+
|
239
|
+
# download image from Selenium using JavaScript and upload to Dropbox
|
240
|
+
# return the URL of the screenshot
|
241
|
+
#
|
242
|
+
# Parameters:
|
243
|
+
# - img: Selenium image element to download from the website and upload to dropbox.
|
244
|
+
# - dropbox_folder: Dropbox folder name to store the image.
|
245
|
+
#
|
246
|
+
def download_image(img, dropbox_folder=nil)
|
247
|
+
download_image_0(img.attribute('src'), dropbox_folder)
|
248
|
+
end # def download_image
|
249
|
+
|
250
|
+
# take screenshot and upload it to dropbox
|
251
|
+
# return the URL of the screenshot
|
252
|
+
def screenshot(dropbox_folder=nil)
|
253
|
+
raise "Either dropbox_folder parameter or self.desc['id_account'] are required." if dropbox_folder.nil? && self.desc['id_account'].nil?
|
254
|
+
dropbox_folder = self.desc['id_account'] if dropbox_folder.nil?
|
255
|
+
# parameters
|
256
|
+
id = SecureRandom.uuid
|
257
|
+
filename = "#{id}.png"
|
258
|
+
tmp_path = "/tmp/#{filename}"
|
259
|
+
# take screenshot using selenium driver and save it into the /tmp folder
|
260
|
+
self.driver.save_screenshot(tmp_path)
|
261
|
+
# code
|
262
|
+
year = Time.now.year.to_s.rjust(4,'0')
|
263
|
+
month = Time.now.month.to_s.rjust(2,'0')
|
264
|
+
folder = "/massprospecting.rpa/#{dropbox_folder}.#{year}.#{month}"
|
265
|
+
path = "#{folder}/#{filename}"
|
266
|
+
BlackStack::DropBox.dropbox_create_folder(folder)
|
267
|
+
BlackStack::DropBox.dropbox_upload_file(tmp_path, path)
|
268
|
+
File.delete(tmp_path)
|
269
|
+
BlackStack::DropBox.get_file_url(path).gsub('&dl=1', '&dl=0')
|
270
|
+
end # def screenshot
|
271
|
+
|
272
|
+
# create a file in the cloud with the HTML of the current page
|
273
|
+
# return the URL of the file
|
274
|
+
def snapshot(dropbox_folder=nil)
|
275
|
+
raise "Either dropbox_folder parameter or self.desc['id_account'] are required." if dropbox_folder.nil? && self.desc['id_account'].nil?
|
276
|
+
dropbox_folder = self.desc['id_account'] if dropbox_folder.nil?
|
277
|
+
# parameters
|
278
|
+
id = SecureRandom.uuid
|
279
|
+
filename = "#{id}.html"
|
280
|
+
tmp_path = "/tmp/#{filename}"
|
281
|
+
# take screenshot using selenium driver and save it into the /tmp folder
|
282
|
+
File.write(tmp_path, self.driver.page_source)
|
283
|
+
# code
|
284
|
+
year = Time.now.year.to_s.rjust(4,'0')
|
285
|
+
month = Time.now.month.to_s.rjust(2,'0')
|
286
|
+
folder = "/massprospecting.bots/#{dropbox_folder}.#{year}.#{month}"
|
287
|
+
path = "#{folder}/#{filename}"
|
288
|
+
BlackStack::DropBox.dropbox_create_folder(folder)
|
289
|
+
BlackStack::DropBox.dropbox_upload_file(tmp_path, path)
|
290
|
+
File.delete(tmp_path)
|
291
|
+
BlackStack::DropBox.get_file_url(path).gsub('&dl=1', '&dl=0')
|
292
|
+
end # def snapshot
|
293
|
+
|
294
|
+
# return a selnium driver for this profile
|
295
|
+
def driver()
|
296
|
+
class_name = self.class.name.gsub('Mass::', '')
|
297
|
+
allow_intercept_js = self.type.desc['allow_intercept_js']
|
298
|
+
|
299
|
+
#l = BlackStack::DummyLogger.new(nil) if l.nil?
|
300
|
+
|
301
|
+
c = AdsPowerClient.new(key: ADSPOWER_API_KEY)
|
302
|
+
|
303
|
+
self.class.buffer_driver = nil if !c.check(self.desc['ads_power_id'])
|
304
|
+
sleep(1)
|
305
|
+
|
306
|
+
if self.class.buffer_driver.nil?
|
307
|
+
self.class.buffer_driver = c.driver(self.desc['ads_power_id'], headless)
|
308
|
+
self.class.buffer_driver.manage.window.resize_to(self.desc['browser_width'], self.desc['browser_height'])
|
309
|
+
self.one_tab
|
310
|
+
|
311
|
+
#if self.desc['allow_browser_to_download_multiple_files']
|
312
|
+
# self.automatic_downloads(status: :allow, domain: self.domain, secure: true, www: true)
|
313
|
+
#else
|
314
|
+
# self.automatic_downloads(status: :block, domain: self.domain, secure: true, www: true)
|
315
|
+
#end
|
316
|
+
|
317
|
+
# Get source code of intercept.js library
|
318
|
+
#l.logs "Getting source code of intercept.js library... "
|
319
|
+
uri = URI.parse('https://raw.githubusercontent.com/leandrosardi/intercept/main/lib/intercept.js')
|
320
|
+
js1 = Net::HTTP.get(uri)
|
321
|
+
#l.logf "done".green
|
322
|
+
|
323
|
+
|
324
|
+
# call ls command to get array of files in the folder
|
325
|
+
# iterate all the *.js files inside the folder $RUBYLIB/extensions/mass.subaccount/js
|
326
|
+
js2 = ''
|
327
|
+
filenames = `ls #{CODE_PATH}/extensions/mass.subaccount/js/*.js`.split("\n")
|
328
|
+
filenames.each { |filename|
|
329
|
+
# Get the source code of the scraper
|
330
|
+
js2 += `cat #{filename}`
|
331
|
+
js2 += "\n\n"
|
332
|
+
}
|
333
|
+
|
334
|
+
#l.logf "done".green + " (#{filename.blue})"
|
335
|
+
|
336
|
+
# Initializing the interceptor
|
337
|
+
js3 = ""
|
338
|
+
=begin
|
339
|
+
js3 = "
|
340
|
+
$$.init({
|
341
|
+
parse: function(xhr) {
|
342
|
+
#{class_name}.scrape(xhr);
|
343
|
+
}
|
344
|
+
});
|
345
|
+
"
|
346
|
+
=end
|
347
|
+
# Execute the scraper
|
348
|
+
# Inject the library into the page
|
349
|
+
#
|
350
|
+
# Selenium: How to Inject/execute a Javascript in to a Page before loading/executing any other scripts of the page?
|
351
|
+
#
|
352
|
+
# Reference:
|
353
|
+
# - https://stackoverflow.com/questions/31354352/selenium-how-to-inject-execute-a-javascript-in-to-a-page-before-loading-executi
|
354
|
+
#
|
355
|
+
# Documentation:
|
356
|
+
# - https://www.selenium.dev/documentation/webdriver/bidirectional/chrome_devtools/cdp_endpoint/
|
357
|
+
#l.logs "Injecting the library into the page... "
|
358
|
+
|
359
|
+
# setup a profile_type to work or not with intercept.js
|
360
|
+
# References:
|
361
|
+
# - https://github.com/VyMECO/mass.public/issues/6
|
362
|
+
# - https://github.com/VyMECO/mass.public/issues/13
|
363
|
+
#
|
364
|
+
if allow_intercept_js
|
365
|
+
self.class.buffer_driver.execute_cdp("Page.addScriptToEvaluateOnNewDocument", source: js1+js2+js3)
|
366
|
+
end
|
367
|
+
#l.logf "done".green
|
368
|
+
end
|
369
|
+
|
370
|
+
# return
|
371
|
+
return self.class.buffer_driver
|
372
|
+
end # def driver
|
373
|
+
|
374
|
+
end # class ProfileRPA
|
375
|
+
end # module Mass
|
data/lib/mass-client.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'net/http'
|
3
|
+
require 'json'
|
4
|
+
require 'blackstack-core'
|
5
|
+
require 'simple_cloud_logging'
|
6
|
+
require 'simple_command_line_parser'
|
7
|
+
require 'colorize'
|
8
|
+
|
9
|
+
# base classes
|
10
|
+
require 'lib/base-line/channel'
|
11
|
+
|
12
|
+
require 'lib/base-line/profile_type'
|
13
|
+
require 'lib/base-line/source_type'
|
14
|
+
require 'lib/base-line/enrichment_type'
|
15
|
+
require 'lib/base-line/outreach_type'
|
16
|
+
require 'lib/base-line/data_type'
|
17
|
+
|
18
|
+
require 'lib/base-line/headcount'
|
19
|
+
require 'lib/base-line/industry'
|
20
|
+
require 'lib/base-line/location'
|
21
|
+
require 'lib/base-line/revenue'
|
22
|
+
require 'lib/base-line/tag'
|
23
|
+
require 'lib/base-line/profile'
|
24
|
+
|
25
|
+
require 'lib/base-line/source'
|
26
|
+
require 'lib/base-line/job'
|
27
|
+
require 'lib/base-line/event'
|
28
|
+
|
29
|
+
require 'lib/base-line/outreach'
|
30
|
+
require 'lib/base-line/enrichment'
|
31
|
+
|
32
|
+
require 'lib/base-line/company'
|
33
|
+
#require 'lib/base-line/company_data'
|
34
|
+
#require 'lib/base-line/company_industry'
|
35
|
+
#require 'lib/base-line/company_naics'
|
36
|
+
#require 'lib/base-line/company_sic'
|
37
|
+
#require 'lib/base-line/company_tag'
|
38
|
+
|
39
|
+
require 'lib/base-line/lead'
|
40
|
+
#require 'lib/base-line/lead_data'
|
41
|
+
#require 'lib/base-line/lead_tag'
|
42
|
+
|
43
|
+
require 'lib/base-line/inboxcheck'
|
44
|
+
require 'lib/base-line/connectioncheck'
|
45
|
+
require 'lib/base-line/rule'
|
46
|
+
require 'lib/base-line/request'
|
47
|
+
|
48
|
+
# first line of children
|
49
|
+
require 'lib/first-line/profile_api'
|
50
|
+
require 'lib/first-line/profile_mta'
|
51
|
+
require 'lib/first-line/profile_rpa'
|
52
|
+
|
53
|
+
|
metadata
ADDED
@@ -0,0 +1,209 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mass-client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Leandro Daniel Sardi
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-07-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: uri
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.11.2
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.11.2
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.11.2
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.11.2
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: net-http
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 0.2.0
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 0.2.0
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: 0.2.0
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 0.2.0
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: json
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: 2.6.3
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 2.6.3
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 2.6.3
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 2.6.3
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: blackstack-core
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - "~>"
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: 1.2.19
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.2.19
|
83
|
+
type: :runtime
|
84
|
+
prerelease: false
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.2.19
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: 1.2.19
|
93
|
+
- !ruby/object:Gem::Dependency
|
94
|
+
name: colorize
|
95
|
+
requirement: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - "~>"
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: 0.8.1
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 0.8.1
|
103
|
+
type: :runtime
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 0.8.1
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: 0.8.1
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: simple_cloud_logging
|
115
|
+
requirement: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - "~>"
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: 1.2.6
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: 1.2.6
|
123
|
+
type: :runtime
|
124
|
+
prerelease: false
|
125
|
+
version_requirements: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - "~>"
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: 1.2.6
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: 1.2.6
|
133
|
+
- !ruby/object:Gem::Dependency
|
134
|
+
name: simple_command_line_parser
|
135
|
+
requirement: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - "~>"
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: 1.1.2
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: 1.1.2
|
143
|
+
type: :runtime
|
144
|
+
prerelease: false
|
145
|
+
version_requirements: !ruby/object:Gem::Requirement
|
146
|
+
requirements:
|
147
|
+
- - "~>"
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: 1.1.2
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: 1.1.2
|
153
|
+
description: Ruby library for Mass API.
|
154
|
+
email: leandro@massprospecting.com
|
155
|
+
executables: []
|
156
|
+
extensions: []
|
157
|
+
extra_rdoc_files: []
|
158
|
+
files:
|
159
|
+
- lib/base-line/channel.rb
|
160
|
+
- lib/base-line/company.rb
|
161
|
+
- lib/base-line/connectioncheck.rb
|
162
|
+
- lib/base-line/data_type.rb
|
163
|
+
- lib/base-line/enrichment.rb
|
164
|
+
- lib/base-line/enrichment_type.rb
|
165
|
+
- lib/base-line/event.rb
|
166
|
+
- lib/base-line/headcount.rb
|
167
|
+
- lib/base-line/inboxcheck.rb
|
168
|
+
- lib/base-line/industry.rb
|
169
|
+
- lib/base-line/job.rb
|
170
|
+
- lib/base-line/lead.rb
|
171
|
+
- lib/base-line/location.rb
|
172
|
+
- lib/base-line/outreach.rb
|
173
|
+
- lib/base-line/outreach_type.rb
|
174
|
+
- lib/base-line/profile.rb
|
175
|
+
- lib/base-line/profile_type.rb
|
176
|
+
- lib/base-line/request.rb
|
177
|
+
- lib/base-line/revenue.rb
|
178
|
+
- lib/base-line/rule.rb
|
179
|
+
- lib/base-line/source.rb
|
180
|
+
- lib/base-line/source_type.rb
|
181
|
+
- lib/base-line/tag.rb
|
182
|
+
- lib/first-line/profile_api.rb
|
183
|
+
- lib/first-line/profile_mta.rb
|
184
|
+
- lib/first-line/profile_rpa.rb
|
185
|
+
- lib/mass-client.rb
|
186
|
+
homepage: https://github.com/massprospecting/mass-client
|
187
|
+
licenses:
|
188
|
+
- MIT
|
189
|
+
metadata: {}
|
190
|
+
post_install_message:
|
191
|
+
rdoc_options: []
|
192
|
+
require_paths:
|
193
|
+
- lib
|
194
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
195
|
+
requirements:
|
196
|
+
- - ">="
|
197
|
+
- !ruby/object:Gem::Version
|
198
|
+
version: '0'
|
199
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
200
|
+
requirements:
|
201
|
+
- - ">="
|
202
|
+
- !ruby/object:Gem::Version
|
203
|
+
version: '0'
|
204
|
+
requirements: []
|
205
|
+
rubygems_version: 3.3.7
|
206
|
+
signing_key:
|
207
|
+
specification_version: 4
|
208
|
+
summary: Ruby library for Mass API.
|
209
|
+
test_files: []
|