phantomblaster 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.rspec +2 -0
- data/.rubocop.yml +4 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +69 -0
- data/Rakefile +6 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/exe/phantomblaster +6 -0
- data/lib/phantomblaster.rb +33 -0
- data/lib/phantomblaster/cli.rb +115 -0
- data/lib/phantomblaster/client.rb +48 -0
- data/lib/phantomblaster/errors.rb +5 -0
- data/lib/phantomblaster/generators/script.rb +22 -0
- data/lib/phantomblaster/generators/script/script.js +55 -0
- data/lib/phantomblaster/models/script.rb +44 -0
- data/lib/phantomblaster/models/user.rb +17 -0
- data/lib/phantomblaster/version.rb +3 -0
- data/phantomblaster.gemspec +31 -0
- metadata +165 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: bc45e1660a2476296084bf99de734f35449a2f8ae4716af296f2b8083d622813
|
4
|
+
data.tar.gz: 77a1e7f85c01d4a4b43f7f359d84fc796afce7cd678b2d59085e6626265d6439
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b567452bed265587c9398a4adfa6b4d0930ba4977e791984078f844cf9f705417b10bc453ecadb9de17aa71432bfbf05ee81adeddc210c519db138724ddec8a9
|
7
|
+
data.tar.gz: 4b0103920b45f9cf73ccc446cd1d872bff0d141673316981c155745f38651a7f560acc54b08db6eeea13854c7bbebd63abcf169d949df0f3fe1ef43317f9c9a7
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2018 Jason Adkison
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# Phantomblaster
|
2
|
+
|
3
|
+
A ruby gem for interacting with the [Phantombuster](https://phantombuster.com) service.
|
4
|
+
|
5
|
+
Currently includes a CLI tool to make it easier to develop and work with agent scripts. In the future, it will provide an easy way to interact with agents from within any ruby program.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'phantomblaster'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install phantomblaster
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
```
|
26
|
+
phantomblaster account # Displays information about the account
|
27
|
+
phantomblaster agents # Lists all remote agents
|
28
|
+
phantomblaster download FILENAME # Downloads an agent script
|
29
|
+
phantomblaster generate FILENAME # Generates an agent script
|
30
|
+
phantomblaster help [COMMAND] # Describe available commands or one specific command
|
31
|
+
phantomblaster pull # Fetches all agent scripts
|
32
|
+
phantomblaster push # Pushes all agent scripts
|
33
|
+
phantomblaster scripts # Lists all remote scripts
|
34
|
+
phantomblaster upload FILENAME # Uploads an agent script
|
35
|
+
```
|
36
|
+
|
37
|
+
## Configuration
|
38
|
+
|
39
|
+
There are currently 2 options available.
|
40
|
+
|
41
|
+
You can configure options by creating an initializer:
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
Phantomblaster.configure do |config|
|
45
|
+
config.api_key = 'XXXXXXXXX'
|
46
|
+
config.scripts_dir = '/path/to/scripts'
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
Or set the following environment variables:
|
51
|
+
|
52
|
+
* PHANTOMBUSTER_API_KEY
|
53
|
+
* PHANTOMBUSTER_SCRIPTS_DIR
|
54
|
+
|
55
|
+
The scripts directory must be an absolute path.
|
56
|
+
|
57
|
+
## Development
|
58
|
+
|
59
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
60
|
+
|
61
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
62
|
+
|
63
|
+
## Contributing
|
64
|
+
|
65
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/jasonadkison/phantomblaster.
|
66
|
+
|
67
|
+
## License
|
68
|
+
|
69
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'pry'
|
5
|
+
require 'phantomblaster'
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require 'irb'
|
15
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/exe/phantomblaster
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'phantomblaster/version'
|
2
|
+
require 'phantomblaster/errors'
|
3
|
+
require 'phantomblaster/client'
|
4
|
+
require 'phantomblaster/models/user'
|
5
|
+
require 'phantomblaster/models/script'
|
6
|
+
|
7
|
+
# A module for containing phantombuster functionalities.
|
8
|
+
module Phantomblaster
|
9
|
+
class << self
|
10
|
+
attr_accessor :configuration
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.configure
|
14
|
+
self.configuration ||= Configuration.new
|
15
|
+
yield(configuration)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Class that holds the config state for the gem.
|
19
|
+
# Define each config option with a getter/setter.
|
20
|
+
class Configuration
|
21
|
+
attr_accessor :api_key, :scripts_dir
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
@api_key = ''
|
25
|
+
@scripts_dir = ''
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
Phantomblaster.configure do |config|
|
31
|
+
config.api_key = ENV['PHANTOMBUSTER_API_KEY']
|
32
|
+
config.scripts_dir = ENV['PHANTOMBUSTER_SCRIPTS_DIR'] || File.join(File.dirname(__FILE__), '../scripts')
|
33
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'terminal-table'
|
3
|
+
require 'pathname'
|
4
|
+
require 'phantomblaster/generators/script'
|
5
|
+
|
6
|
+
module Phantomblaster
|
7
|
+
class CLI < Thor
|
8
|
+
package_name 'phantomblaster'
|
9
|
+
|
10
|
+
desc 'account', 'Displays information about the account'
|
11
|
+
def account
|
12
|
+
title = 'Phantombuster Account'
|
13
|
+
headings = ['Email', 'API Key']
|
14
|
+
rows = [[current_user.email, Phantomblaster.configuration.api_key]]
|
15
|
+
table = Terminal::Table.new title: title, headings: headings, rows: rows
|
16
|
+
say table
|
17
|
+
end
|
18
|
+
|
19
|
+
desc 'agents', 'Lists all remote agents'
|
20
|
+
def agents
|
21
|
+
title = 'Phantombuster Agents'
|
22
|
+
headings = ['Agent Name', 'Agent ID', 'Script ID', 'Last Status']
|
23
|
+
rows = []
|
24
|
+
current_agents.each do |agent|
|
25
|
+
rows << [agent['name'], agent['id'], agent['scriptId'], agent['lastEndStatus']]
|
26
|
+
end
|
27
|
+
table = Terminal::Table.new title: title, headings: headings, rows: rows
|
28
|
+
say table
|
29
|
+
end
|
30
|
+
|
31
|
+
desc 'scripts', 'Lists all remote scripts'
|
32
|
+
def scripts
|
33
|
+
title = 'Phantombuster Scripts'
|
34
|
+
headings = ['Script Name', 'Script ID', 'Script Source', 'Script Last Saved At']
|
35
|
+
rows = []
|
36
|
+
current_scripts.each do |script|
|
37
|
+
rows << [script.name, script.id, script.source, script.last_saved_at]
|
38
|
+
end
|
39
|
+
table = Terminal::Table.new title: title, headings: headings, rows: rows
|
40
|
+
say table
|
41
|
+
end
|
42
|
+
|
43
|
+
desc 'generate FILENAME', 'Generates an agent script'
|
44
|
+
def generate(name)
|
45
|
+
Phantomblaster::Generators::Script.start([name])
|
46
|
+
end
|
47
|
+
|
48
|
+
desc 'upload FILENAME', 'Uploads an agent script'
|
49
|
+
def upload(name)
|
50
|
+
return unless yes?("Upload #{name} to Phantombuster?")
|
51
|
+
|
52
|
+
res = Phantomblaster::Models::Script.upload(name)
|
53
|
+
say res
|
54
|
+
end
|
55
|
+
|
56
|
+
desc 'download FILENAME', 'Downloads an agent script'
|
57
|
+
def download(name, force = false)
|
58
|
+
script = Phantomblaster::Models::Script.find_by_name(name)
|
59
|
+
folder_pathname = Pathname.new(Phantomblaster.configuration.scripts_dir)
|
60
|
+
file_pathname = Pathname.new(name)
|
61
|
+
full_pathname = folder_pathname.join(file_pathname)
|
62
|
+
|
63
|
+
unless folder_pathname.directory?
|
64
|
+
return unless yes?("Directory #{folder_pathname.realdirpath} does not exist. Create it?")
|
65
|
+
|
66
|
+
folder_pathname.mkpath
|
67
|
+
end
|
68
|
+
|
69
|
+
if !force && full_pathname.exist?
|
70
|
+
return unless yes?("File #{full_pathname.realpath} already exists. Overwrite?")
|
71
|
+
end
|
72
|
+
|
73
|
+
full_pathname.open('w') { |f| f << script.text }
|
74
|
+
say "Wrote #{full_pathname.realpath}"
|
75
|
+
end
|
76
|
+
|
77
|
+
desc 'pull', 'Fetches all agent scripts'
|
78
|
+
def pull
|
79
|
+
return unless yes?("This will pull from Phantombuster and overwrite any existing scripts. " \
|
80
|
+
"Are you sure you want to continue?")
|
81
|
+
|
82
|
+
current_scripts.each do |script|
|
83
|
+
download(script.name, true)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
desc 'push', 'Pushes all agent scripts'
|
88
|
+
def push
|
89
|
+
return unless yes?("This will push all local scripts to Phantombuster and overwrite any " \
|
90
|
+
"existing scripts. Are you sure you want to continue?")
|
91
|
+
|
92
|
+
folder_pathname = Pathname.new(Phantomblaster.configuration.scripts_dir)
|
93
|
+
raise 'Scripts directory does not exist' unless folder_pathname.directory?
|
94
|
+
|
95
|
+
Pathname.glob("#{folder_pathname.realdirpath}/**/*.js").each do |pn|
|
96
|
+
_dir, file = pn.split
|
97
|
+
upload(file)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
def current_user
|
104
|
+
@current_user ||= Phantomblaster::Models::User.find
|
105
|
+
end
|
106
|
+
|
107
|
+
def current_agents
|
108
|
+
@current_agents ||= current_user.agents
|
109
|
+
end
|
110
|
+
|
111
|
+
def current_scripts
|
112
|
+
@current_scripts ||= Phantomblaster::Models::Script.all
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'net/http'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Phantomblaster
|
6
|
+
class Client
|
7
|
+
API_URL = 'https://phantombuster.com/api/v1'.freeze
|
8
|
+
|
9
|
+
def self.build_request(path, args = {}, &_block)
|
10
|
+
uri = URI("#{API_URL}#{path}")
|
11
|
+
new_query = URI.decode_www_form(uri.query || '')
|
12
|
+
args.to_a.each { |arg| new_query << arg }
|
13
|
+
new_query << ['key', Phantomblaster.configuration.api_key]
|
14
|
+
uri.query = URI.encode_www_form(new_query)
|
15
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
16
|
+
http.use_ssl = true
|
17
|
+
yield [http, uri]
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.get(path, args = {})
|
21
|
+
response = build_request(path, args) do |http, uri|
|
22
|
+
http.request(Net::HTTP::Get.new(uri))
|
23
|
+
end
|
24
|
+
|
25
|
+
unless response.is_a?(Net::HTTPSuccess)
|
26
|
+
raise APIError, "Unexpected response: #{response.read_body}"
|
27
|
+
end
|
28
|
+
|
29
|
+
JSON.parse(response.read_body)['data']
|
30
|
+
rescue JSON::ParserError => _e
|
31
|
+
raise APIError, "Could not parse response: #{response.read_body}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.post(path, args = {})
|
35
|
+
response = build_request(path, args) do |http, uri|
|
36
|
+
http.request(Net::HTTP::Post.new(uri))
|
37
|
+
end
|
38
|
+
|
39
|
+
unless response.is_a?(Net::HTTPSuccess)
|
40
|
+
raise APIError, "Unexpected response: #{response.read_body}"
|
41
|
+
end
|
42
|
+
|
43
|
+
JSON.parse(response.read_body)
|
44
|
+
rescue JSON::ParserError => _e
|
45
|
+
raise APIError, "Could not parse response: #{response.read_body}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'thor/group'
|
2
|
+
|
3
|
+
module Phantomblaster
|
4
|
+
module Generators
|
5
|
+
class Script < Thor::Group
|
6
|
+
include Thor::Actions
|
7
|
+
argument :filename, type: :string
|
8
|
+
|
9
|
+
def self.source_root
|
10
|
+
File.dirname(__FILE__) + '/script'
|
11
|
+
end
|
12
|
+
|
13
|
+
def create_scripts_dir
|
14
|
+
empty_directory(Phantomblaster.configuration.scripts_dir)
|
15
|
+
end
|
16
|
+
|
17
|
+
def copy_script
|
18
|
+
template('script.js', "#{Phantomblaster.configuration.scripts_dir}/#{filename}")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
// Phantombuster configuration {
|
2
|
+
|
3
|
+
"phantombuster command: nodejs"
|
4
|
+
"phantombuster package: 5"
|
5
|
+
"phantombuster flags: save-folder"
|
6
|
+
|
7
|
+
const Buster = require("phantombuster")
|
8
|
+
const buster = new Buster()
|
9
|
+
|
10
|
+
const Nick = require("nickjs")
|
11
|
+
const nick = new Nick()
|
12
|
+
|
13
|
+
// }
|
14
|
+
|
15
|
+
/*
|
16
|
+
This demo script returns two things:
|
17
|
+
1) JSON of all the Hacker News homepage links
|
18
|
+
2) Screenshot of the Hacker News homepage
|
19
|
+
|
20
|
+
Edit it as you wish, have a look at our documentation on https://hub.phantombuster.com/ and do get in touch.
|
21
|
+
|
22
|
+
Most importantly, click LAUNCH to get a taste of Phantombuster's power!! :)
|
23
|
+
*/
|
24
|
+
|
25
|
+
nick.newTab().then(async (tab) => {
|
26
|
+
|
27
|
+
await tab.open("news.ycombinator.com")
|
28
|
+
await tab.untilVisible("#hnmain") // Make sure we have loaded the right page
|
29
|
+
await tab.inject("../injectables/jquery-3.0.0.min.js") // We're going to use jQuery to scrape
|
30
|
+
|
31
|
+
// Evaluate a function in the current page DOM context. Execution is sandboxed: page has no access to the Nick context
|
32
|
+
// In other words: Open the browser inspector to execute this function in the console
|
33
|
+
const hackerNewsLinks = await tab.evaluate((arg, callback) => {
|
34
|
+
const data = []
|
35
|
+
$(".athing").each((index, element) => {
|
36
|
+
data.push({
|
37
|
+
title: $(element).find(".storylink").text(),
|
38
|
+
url: $(element).find(".storylink").attr("href")
|
39
|
+
})
|
40
|
+
})
|
41
|
+
callback(null, data)
|
42
|
+
})
|
43
|
+
|
44
|
+
await buster.setResultObject(hackerNewsLinks) // Send the result back to Phantombuster
|
45
|
+
await tab.screenshot("screenshot.png") // Why not take a screenshot while we're at it?
|
46
|
+
|
47
|
+
})
|
48
|
+
.then(() => {
|
49
|
+
console.log("Job done!")
|
50
|
+
nick.exit()
|
51
|
+
})
|
52
|
+
.catch((err) => {
|
53
|
+
console.log(`Something went wrong: ${err}`)
|
54
|
+
nick.exit(1)
|
55
|
+
})
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Phantomblaster
|
2
|
+
module Models
|
3
|
+
class Script
|
4
|
+
def self.find(id)
|
5
|
+
data = Phantomblaster::Client.get("/script/by-id/json/#{id}", withoutText: false)
|
6
|
+
new(data)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.find_by_name(name)
|
10
|
+
data = Phantomblaster::Client.get("/script/by-name/json/#{name}", withoutText: false)
|
11
|
+
new(data)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.all
|
15
|
+
data = Phantomblaster::Client.get('/scripts')
|
16
|
+
data.map { |params| new(params) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.upload(name)
|
20
|
+
pathname = Pathname.new("#{Phantomblaster.configuration.scripts_dir}/#{name}")
|
21
|
+
raise MissingFileError, "#{pathname.realdirpath} not found" unless pathname.file?
|
22
|
+
|
23
|
+
text = pathname.open(&:read)
|
24
|
+
Phantomblaster::Client.post("/script/#{name}", text: text,
|
25
|
+
insertOnly: false,
|
26
|
+
source: :phantomblaster)
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_reader :id, :name, :source, :last_saved_at
|
30
|
+
|
31
|
+
def initialize(params)
|
32
|
+
@id = params['id']
|
33
|
+
@name = params['name']
|
34
|
+
@source = params['source']
|
35
|
+
@last_saved_at = params['lastSaveDate']
|
36
|
+
@text = params['text'].to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
def text
|
40
|
+
@text ||= self.class.find(id).instance_variable_get(:@text)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Phantomblaster
|
2
|
+
module Models
|
3
|
+
class User
|
4
|
+
def self.find
|
5
|
+
data = Phantomblaster::Client.get('/user')
|
6
|
+
new(data)
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :email, :agents
|
10
|
+
|
11
|
+
def initialize(params)
|
12
|
+
@email = params['email']
|
13
|
+
@agents = params['agents']
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'phantomblaster/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'phantomblaster'
|
7
|
+
spec.version = Phantomblaster::VERSION
|
8
|
+
spec.authors = ['Jason Adkison']
|
9
|
+
spec.email = ['jadkison@gmail.com']
|
10
|
+
spec.summary = 'A gem for interacting with Phantombuster agents.'
|
11
|
+
spec.description = 'A gem for interacting with Phantombuster agents. Allows you to easily ' \
|
12
|
+
'manage, sync and consume agents from within your Ruby/Rails based ' \
|
13
|
+
'applications.'
|
14
|
+
spec.homepage = 'https://github.com/jasonadkison/phantomblaster'
|
15
|
+
spec.license = 'MIT'
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
+
f.match(%r{^(test|spec|features)/})
|
18
|
+
end
|
19
|
+
spec.bindir = 'exe'
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = ['lib']
|
22
|
+
|
23
|
+
spec.add_development_dependency 'bundler', '~> 1.15'
|
24
|
+
spec.add_development_dependency 'pry', '~> 0.11.3'
|
25
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
26
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
27
|
+
spec.add_development_dependency 'rubocop', '~> 0.59.1'
|
28
|
+
|
29
|
+
spec.add_runtime_dependency 'terminal-table', '~> 1.8.0'
|
30
|
+
spec.add_runtime_dependency 'thor', '~> 0.20.0'
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: phantomblaster
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jason Adkison
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-09-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.15'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.15'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pry
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.11.3
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.11.3
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.59.1
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.59.1
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: terminal-table
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.8.0
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 1.8.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: thor
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.20.0
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.20.0
|
111
|
+
description: A gem for interacting with Phantombuster agents. Allows you to easily
|
112
|
+
manage, sync and consume agents from within your Ruby/Rails based applications.
|
113
|
+
email:
|
114
|
+
- jadkison@gmail.com
|
115
|
+
executables:
|
116
|
+
- phantomblaster
|
117
|
+
extensions: []
|
118
|
+
extra_rdoc_files: []
|
119
|
+
files:
|
120
|
+
- ".gitignore"
|
121
|
+
- ".rspec"
|
122
|
+
- ".rubocop.yml"
|
123
|
+
- ".travis.yml"
|
124
|
+
- Gemfile
|
125
|
+
- LICENSE.txt
|
126
|
+
- README.md
|
127
|
+
- Rakefile
|
128
|
+
- bin/console
|
129
|
+
- bin/setup
|
130
|
+
- exe/phantomblaster
|
131
|
+
- lib/phantomblaster.rb
|
132
|
+
- lib/phantomblaster/cli.rb
|
133
|
+
- lib/phantomblaster/client.rb
|
134
|
+
- lib/phantomblaster/errors.rb
|
135
|
+
- lib/phantomblaster/generators/script.rb
|
136
|
+
- lib/phantomblaster/generators/script/script.js
|
137
|
+
- lib/phantomblaster/models/script.rb
|
138
|
+
- lib/phantomblaster/models/user.rb
|
139
|
+
- lib/phantomblaster/version.rb
|
140
|
+
- phantomblaster.gemspec
|
141
|
+
homepage: https://github.com/jasonadkison/phantomblaster
|
142
|
+
licenses:
|
143
|
+
- MIT
|
144
|
+
metadata: {}
|
145
|
+
post_install_message:
|
146
|
+
rdoc_options: []
|
147
|
+
require_paths:
|
148
|
+
- lib
|
149
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - ">="
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '0'
|
154
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - ">="
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '0'
|
159
|
+
requirements: []
|
160
|
+
rubyforge_project:
|
161
|
+
rubygems_version: 2.7.7
|
162
|
+
signing_key:
|
163
|
+
specification_version: 4
|
164
|
+
summary: A gem for interacting with Phantombuster agents.
|
165
|
+
test_files: []
|