ferrumwizard 0.1.0 → 0.1.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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/ferrumwizard.rb +148 -30
- metadata +2 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: eb46fd03834d035f319b5654848eb8db05c4d8d870b59f261657fedc42b60222
|
|
4
|
+
data.tar.gz: a0e9d66110acbf0439494087795620675b10743eb767891e28cd9d0db55b4475
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f7f3129f81ae7a79646f3ce13299a174265f7d42c1be53ef88dffe9461fddc42793c28b97ba55703d5ccfe62ef5aa5a9dd3a80665d3b3a897550de0d83325946
|
|
7
|
+
data.tar.gz: c7c5bac0cde40acc8d91a07e55890043bc16ae08d8533b4f0cf24719419cf62d5ee012b059dfd5d15befcd619140632cd4194dbb3294e09c1038f022ebccd524
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data.tar.gz.sig
CHANGED
|
Binary file
|
data/lib/ferrumwizard.rb
CHANGED
|
@@ -8,96 +8,214 @@ require 'ferrum'
|
|
|
8
8
|
|
|
9
9
|
class FerrumWizard
|
|
10
10
|
|
|
11
|
-
attr_reader :browser, :links
|
|
11
|
+
attr_reader :browser, :links, :radio, :buttons, :js_methods
|
|
12
12
|
|
|
13
13
|
def initialize(url, headless: true, debug: false)
|
|
14
14
|
|
|
15
15
|
@url, @debug = url, debug
|
|
16
16
|
@browser = Ferrum::Browser.new headless: headless
|
|
17
|
-
|
|
17
|
+
sleep 2
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def inspect()
|
|
21
|
+
"#<FerrumWizard>"
|
|
18
22
|
end
|
|
19
23
|
|
|
20
|
-
def login(username, password)
|
|
24
|
+
def login(usernamex=nil, passwordx=nil, username: usernamex, password: passwordx)
|
|
25
|
+
|
|
26
|
+
puts 'username: ' + username.inspect if @debug
|
|
21
27
|
|
|
22
28
|
b = @browser
|
|
23
29
|
b.goto(@url)
|
|
24
|
-
|
|
30
|
+
@browser.network.wait_for_idle
|
|
31
|
+
sleep 3
|
|
25
32
|
|
|
26
33
|
# search for the username input box
|
|
27
34
|
e_username = b.at_xpath('//input[@type="email"]')
|
|
28
|
-
|
|
35
|
+
puts 'e_username: ' + e_username.inspect if @debug
|
|
36
|
+
sleep 1
|
|
29
37
|
# search for the password input box
|
|
30
38
|
e_password = b.at_xpath('//input[@type="password"]')
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
sleep 1
|
|
40
|
+
|
|
41
|
+
if username and e_username then
|
|
42
|
+
puts 'entering the username' if @debug
|
|
43
|
+
e_username.focus.type(username)
|
|
44
|
+
sleep 1
|
|
37
45
|
end
|
|
38
46
|
|
|
47
|
+
e_password.focus.type(password, :Enter) if e_password
|
|
48
|
+
@browser.network.wait_for_idle
|
|
49
|
+
|
|
39
50
|
sleep 4
|
|
40
|
-
|
|
41
|
-
|
|
51
|
+
|
|
52
|
+
scan_page()
|
|
42
53
|
|
|
43
|
-
end
|
|
54
|
+
end
|
|
44
55
|
|
|
45
56
|
def quit
|
|
46
57
|
@browser.quit
|
|
47
58
|
end
|
|
59
|
+
|
|
60
|
+
def scan_page()
|
|
61
|
+
|
|
62
|
+
@doc = Rexle.new @browser.body
|
|
63
|
+
fetch_links()
|
|
64
|
+
scan_form_elements()
|
|
65
|
+
scan_js_links()
|
|
66
|
+
self
|
|
67
|
+
end
|
|
48
68
|
|
|
49
69
|
def to_rb()
|
|
50
70
|
end
|
|
51
71
|
|
|
52
72
|
private
|
|
53
73
|
|
|
74
|
+
def fetch_buttons()
|
|
75
|
+
|
|
76
|
+
a2 = @browser.xpath('//input[@type="button"]')
|
|
77
|
+
@buttons = a2.flat_map do |x|
|
|
78
|
+
|
|
79
|
+
a = x.value.split(/\W+/).map {|label| [label, x]}
|
|
80
|
+
a << [x.value, x]
|
|
81
|
+
a + a.map {|x, obj| [x.downcase, obj]}
|
|
82
|
+
|
|
83
|
+
end.to_h
|
|
84
|
+
|
|
85
|
+
names = @buttons.keys.map(&:downcase).uniq.select {|x| x =~ /^\w+$/}
|
|
86
|
+
buttons = @buttons
|
|
87
|
+
|
|
88
|
+
names.each do |name|
|
|
89
|
+
|
|
90
|
+
define_singleton_method name.to_sym do
|
|
91
|
+
buttons[name].click
|
|
92
|
+
@browser.network.wait_for_idle
|
|
93
|
+
sleep = 1
|
|
94
|
+
self
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
end
|
|
100
|
+
|
|
54
101
|
def fetch_links()
|
|
102
|
+
|
|
103
|
+
all_links = @doc.root.xpath('//a')
|
|
55
104
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
105
|
+
all_links.each do |x|
|
|
106
|
+
|
|
107
|
+
if x.plaintext.empty? then
|
|
108
|
+
x.text = x.attributes[:href].sub(/\.\w+$/,'')[/([^\/]+)$/].split(/[_]|(?=[A-Z])/).join(' ')
|
|
109
|
+
else
|
|
110
|
+
x.text = x.plaintext.gsub('&','&')
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
end
|
|
114
|
+
|
|
60
115
|
valid_links = all_links.reject do |x|
|
|
61
116
|
|
|
62
117
|
puts 'x: ' + x.inspect if @debug
|
|
63
|
-
|
|
64
|
-
r = (x.attributes[:target] == '_blank') | s.empty?
|
|
118
|
+
r = (x.attributes[:target] == '_blank')
|
|
65
119
|
|
|
66
120
|
puts 'r: ' + r.inspect if @debug
|
|
67
121
|
r
|
|
68
122
|
|
|
69
|
-
end
|
|
123
|
+
end
|
|
124
|
+
indices = valid_links.map {|x| all_links.index x}
|
|
70
125
|
|
|
71
|
-
active_links =
|
|
72
|
-
valid_active_links =
|
|
126
|
+
active_links = @browser.xpath('//a')
|
|
127
|
+
valid_active_links = indices.map {|n| active_links[n]}
|
|
73
128
|
|
|
74
129
|
|
|
75
|
-
@links = valid_active_links.flat_map do |x|
|
|
76
|
-
|
|
130
|
+
@links = valid_active_links.flat_map.with_index do |x, i|
|
|
131
|
+
|
|
132
|
+
a = valid_links[i].text.split(/\W+/).map {|label| [label, x]}
|
|
133
|
+
a << [valid_links[i].text, x]
|
|
134
|
+
|
|
135
|
+
puts 'a: ' + a.inspect if @debug
|
|
77
136
|
a + a.map {|x, obj| [x.downcase, obj]}
|
|
78
137
|
end.to_h
|
|
79
138
|
|
|
80
|
-
names = @links.keys.map(&:downcase).uniq.select {|x| x =~
|
|
139
|
+
names = @links.keys.map(&:downcase).uniq.select {|x| x =~ /^[\w ]+$/}
|
|
81
140
|
links = @links
|
|
82
141
|
|
|
83
142
|
names.each do |name|
|
|
84
143
|
|
|
85
|
-
define_singleton_method name.to_sym do
|
|
144
|
+
define_singleton_method name.gsub(/ +/,'_').to_sym do
|
|
86
145
|
links[name].click
|
|
87
|
-
sleep
|
|
146
|
+
sleep 1
|
|
147
|
+
scan_page()
|
|
88
148
|
self
|
|
89
149
|
end
|
|
90
150
|
|
|
91
151
|
end
|
|
92
152
|
|
|
93
|
-
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def scan_form_elements()
|
|
156
|
+
|
|
157
|
+
# find radio buttons
|
|
158
|
+
|
|
159
|
+
#a = doc.root.xpath('//input[@type="radio"]')
|
|
160
|
+
a = @browser.xpath('//input[@type="radio"]')
|
|
161
|
+
#h = a.group_by {|x| x.attributes[:name]}
|
|
162
|
+
h = a.group_by {|x| x.attribute('name')}
|
|
163
|
+
@radio = h.values
|
|
164
|
+
define_singleton_method(:on) { @radio[0][0].click; self }
|
|
165
|
+
define_singleton_method(:off) { @radio[0][1].click; self }
|
|
166
|
+
|
|
167
|
+
fetch_buttons()
|
|
168
|
+
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def scan_js_links()
|
|
172
|
+
|
|
173
|
+
@js_methods = {}
|
|
174
|
+
b = @browser
|
|
175
|
+
|
|
176
|
+
b.xpath('//a').select {|x| x.attribute('href') =~ /^javascript/}.each do |e|
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
s = e.attribute('href')[/(?<=^javascript:)[^\(]+/]
|
|
180
|
+
puts 's: ' + s.inspect
|
|
181
|
+
a = s.split(/\W+|(?=[A-Z])/).map {|label| [label, s]}
|
|
182
|
+
a << [s, s]
|
|
183
|
+
a << [s.split(/\W+|(?=[A-Z])/).join('_'), s]
|
|
184
|
+
a << [s.split(/\W+|(?=[A-Z])/).join('_').downcase, s]
|
|
185
|
+
#@js_methods[s] = a
|
|
186
|
+
|
|
187
|
+
a.concat a.map {|x, name| [x.downcase, name] }
|
|
188
|
+
|
|
189
|
+
puts 'a: ' + a.inspect
|
|
190
|
+
|
|
191
|
+
a.uniq.select {|x, _| x =~ /^[a-z0-9_]+$/}.each do |x, name|
|
|
192
|
+
|
|
193
|
+
if @debug then
|
|
194
|
+
puts 'x: ' + x.inspect
|
|
195
|
+
puts 'name: ' + name.inspect
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
define_singleton_method(x.to_sym) do |*args|
|
|
199
|
+
#args = raw_args.map {|x| x[/^[0-9]+$/] ? x.to_i : x}
|
|
200
|
+
js_method = "%s(%s)" % [name, args.map(&:inspect).join(', ')]
|
|
201
|
+
puts 'js_method: ' + js_method.inspect if @debug
|
|
202
|
+
@browser.evaluate(js_method)
|
|
203
|
+
@browser.network.wait_for_idle
|
|
204
|
+
sleep 4
|
|
205
|
+
self.scan_page()
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
end
|
|
211
|
+
end
|
|
94
212
|
|
|
95
213
|
def method_missing(method_name, *args)
|
|
96
214
|
|
|
215
|
+
puts 'method_missing: ' + method_name.inspect if @debug
|
|
97
216
|
node = @browser.at_css '.' + method_name.to_s
|
|
98
217
|
node.text if node
|
|
99
218
|
|
|
100
219
|
end
|
|
101
220
|
|
|
102
221
|
end
|
|
103
|
-
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ferrumwizard
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- James Robertson
|
|
@@ -35,7 +35,7 @@ cert_chain:
|
|
|
35
35
|
7e24hNRMt3t/JE9ogEO4JzFUH2vq2zzR5X9JQqEclWfwHi4cf8bZFJ7spjZQPjSZ
|
|
36
36
|
Ok3rs0A+kW4ixAj1rDYuoyG/
|
|
37
37
|
-----END CERTIFICATE-----
|
|
38
|
-
date: 2020-
|
|
38
|
+
date: 2020-08-01 00:00:00.000000000 Z
|
|
39
39
|
dependencies:
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
41
|
name: rexle
|
metadata.gz.sig
CHANGED
|
Binary file
|