wabot 0.1.1 → 0.1.2
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/README.md +1 -1
- data/lib/wabot/bot.rb +62 -2
- data/lib/wabot/cli.rb +3 -5
- data/lib/wabot/user_store.rb +4 -14
- data/lib/wabot/version.rb +1 -1
- metadata +2 -16
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f07b179733062731ea76f1ffb30943949fe49d5d8343de859fd41b58c8f46494
|
|
4
|
+
data.tar.gz: 32b9957527498cda3b574358d424447b078fecf3f17c595b5a4195e301d09c1f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 624dfeb7730f1f1f316ae6b393ddd07ff968579b6c143c993872ba3ecb3542a3b6968e7c416bb44dd5fecea5cac741cb66f05e39537603e996d6131fcb1ec4f6
|
|
7
|
+
data.tar.gz: 9a92b158e50f703fcafa3c02b8c71c1b85142ca7bc9c4e939c27e405e9c43fbc7de6f1aec009a76aad996402f006b29c965c9aea9e529aba4f7581e93f9312bd
|
data/README.md
CHANGED
|
@@ -47,7 +47,7 @@ Notes:
|
|
|
47
47
|
- Selenium Manager will handle downloading a compatible chromedriver automatically
|
|
48
48
|
|
|
49
49
|
## Security
|
|
50
|
-
- Local
|
|
50
|
+
- Local users are username-only (no passwords) and stored in `storage/users.json`
|
|
51
51
|
- The current CLI login session is stored in `storage/session.json`
|
|
52
52
|
- Your WhatsApp Web cookies/tokens live inside `profiles/<username>`; keep this folder private
|
|
53
53
|
|
data/lib/wabot/bot.rb
CHANGED
|
@@ -58,6 +58,8 @@ module WaBot
|
|
|
58
58
|
encoded_text = URI.encode_www_form_component(message)
|
|
59
59
|
chat_url = "#{BASE_URL}/send?phone=#{digits_phone}&text=#{encoded_text}"
|
|
60
60
|
@driver.navigate.to(chat_url)
|
|
61
|
+
# Some dialogs (e.g., notifications prompts) can appear after navigation; try to close them.
|
|
62
|
+
dismiss_overlays
|
|
61
63
|
|
|
62
64
|
wait = Selenium::WebDriver::Wait.new(timeout: 60)
|
|
63
65
|
begin
|
|
@@ -67,7 +69,14 @@ module WaBot
|
|
|
67
69
|
# Always attempt to type the message explicitly to avoid relying on URL prefill
|
|
68
70
|
box = find_message_box
|
|
69
71
|
if box
|
|
70
|
-
|
|
72
|
+
begin
|
|
73
|
+
# Focus composer via JS to avoid click interception
|
|
74
|
+
@driver.execute_script("arguments[0].focus();", box)
|
|
75
|
+
rescue Selenium::WebDriver::Error::ElementClickInterceptedError
|
|
76
|
+
# If some overlay intercepted, try dismissing and continue
|
|
77
|
+
dismiss_overlays
|
|
78
|
+
@driver.execute_script("arguments[0].focus();", box)
|
|
79
|
+
end
|
|
71
80
|
sleep 0.15
|
|
72
81
|
# Select-all + delete to clear any previous text
|
|
73
82
|
modifier = (RUBY_PLATFORM =~ /darwin/i ? :command : :control)
|
|
@@ -83,7 +92,13 @@ module WaBot
|
|
|
83
92
|
begin
|
|
84
93
|
@driver.execute_script("arguments[0].click();", btn)
|
|
85
94
|
rescue
|
|
86
|
-
|
|
95
|
+
begin
|
|
96
|
+
btn.click
|
|
97
|
+
rescue Selenium::WebDriver::Error::ElementClickInterceptedError
|
|
98
|
+
# Dismiss overlays and retry JS click once
|
|
99
|
+
dismiss_overlays
|
|
100
|
+
@driver.execute_script("arguments[0].click();", btn)
|
|
101
|
+
end
|
|
87
102
|
end
|
|
88
103
|
else
|
|
89
104
|
# If no button, try Enter/Return inside the composer
|
|
@@ -209,5 +224,50 @@ module WaBot
|
|
|
209
224
|
false
|
|
210
225
|
end
|
|
211
226
|
end
|
|
227
|
+
|
|
228
|
+
def overlay_present?
|
|
229
|
+
begin
|
|
230
|
+
@driver.find_elements(css: "div[role='dialog']").any? { |el| el.displayed? }
|
|
231
|
+
rescue
|
|
232
|
+
false
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def dismiss_overlays
|
|
237
|
+
# Best-effort: press ESC, click common dismiss buttons, and wait briefly
|
|
238
|
+
begin
|
|
239
|
+
# Press ESC up to 2 times
|
|
240
|
+
body = @driver.find_element(tag_name: "body")
|
|
241
|
+
2.times { body.send_keys(:escape) }
|
|
242
|
+
rescue
|
|
243
|
+
end
|
|
244
|
+
# Try common close buttons
|
|
245
|
+
buttons_css = [
|
|
246
|
+
"div[role='dialog'] button[aria-label='Close']",
|
|
247
|
+
"div[role='dialog'] button[aria-label='close']",
|
|
248
|
+
"div[role='dialog'] button[title='Close']"
|
|
249
|
+
]
|
|
250
|
+
buttons_css.each do |css|
|
|
251
|
+
@driver.find_elements(css: css).each do |btn|
|
|
252
|
+
begin
|
|
253
|
+
@driver.execute_script("arguments[0].click();", btn)
|
|
254
|
+
rescue
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
# Try common text buttons
|
|
259
|
+
texts = ["Not now", "No thanks", "Cancel", "Close", "Got it", "OK"]
|
|
260
|
+
texts.each do |txt|
|
|
261
|
+
begin
|
|
262
|
+
el = @driver.find_element(xpath: "//div[@role='dialog']//button[normalize-space(text())='#{txt}']")
|
|
263
|
+
@driver.execute_script("arguments[0].click();", el)
|
|
264
|
+
rescue
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
# Small wait to allow overlay to disappear
|
|
268
|
+
Selenium::WebDriver::Wait.new(timeout: 3).until { !overlay_present? }
|
|
269
|
+
rescue
|
|
270
|
+
# ignore
|
|
271
|
+
end
|
|
212
272
|
end
|
|
213
273
|
end
|
data/lib/wabot/cli.rb
CHANGED
|
@@ -11,11 +11,10 @@ module WaBot
|
|
|
11
11
|
class CLI < Thor
|
|
12
12
|
desc "register", "Register a new local user"
|
|
13
13
|
method_option :username, aliases: "-u", type: :string, required: true, desc: "Username"
|
|
14
|
-
method_option :password, aliases: "-p", type: :string, required: true, desc: "Password"
|
|
15
14
|
def register
|
|
16
15
|
store = UserStore.new
|
|
17
16
|
begin
|
|
18
|
-
store.register(options[:username]
|
|
17
|
+
store.register(options[:username])
|
|
19
18
|
puts "User registered: #{options[:username]}".green
|
|
20
19
|
rescue => e
|
|
21
20
|
puts "Error: #{e.message}".red
|
|
@@ -25,11 +24,10 @@ module WaBot
|
|
|
25
24
|
|
|
26
25
|
desc "login", "Login as a local user"
|
|
27
26
|
method_option :username, aliases: "-u", type: :string, required: true
|
|
28
|
-
method_option :password, aliases: "-p", type: :string, required: true
|
|
29
27
|
def login
|
|
30
28
|
store = UserStore.new
|
|
31
|
-
unless store.authenticate(options[:username]
|
|
32
|
-
puts "
|
|
29
|
+
unless store.authenticate(options[:username])
|
|
30
|
+
puts "User not found. Please register first.".red
|
|
33
31
|
exit 1
|
|
34
32
|
end
|
|
35
33
|
session = SessionStore.new
|
data/lib/wabot/user_store.rb
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "json"
|
|
4
|
-
require "bcrypt"
|
|
5
4
|
require "fileutils"
|
|
6
5
|
|
|
7
6
|
module WaBot
|
|
@@ -13,29 +12,20 @@ module WaBot
|
|
|
13
12
|
initialize_file
|
|
14
13
|
end
|
|
15
14
|
|
|
16
|
-
def register(username
|
|
15
|
+
def register(username)
|
|
17
16
|
raise "Username is required" if username.to_s.strip.empty?
|
|
18
|
-
raise "Password is required" if password.to_s.strip.empty?
|
|
19
17
|
|
|
20
18
|
users = read_users
|
|
21
19
|
raise "User already exists" if users.any? { |u| u["username"] == username }
|
|
22
20
|
|
|
23
|
-
|
|
24
|
-
users << { "username" => username, "password_hash" => password_hash }
|
|
21
|
+
users << { "username" => username }
|
|
25
22
|
write_users(users)
|
|
26
23
|
true
|
|
27
24
|
end
|
|
28
25
|
|
|
29
|
-
def authenticate(username
|
|
26
|
+
def authenticate(username)
|
|
30
27
|
users = read_users
|
|
31
|
-
|
|
32
|
-
return false unless user
|
|
33
|
-
|
|
34
|
-
begin
|
|
35
|
-
BCrypt::Password.new(user["password_hash"]) == password
|
|
36
|
-
rescue
|
|
37
|
-
false
|
|
38
|
-
end
|
|
28
|
+
users.any? { |u| u["username"] == username }
|
|
39
29
|
end
|
|
40
30
|
|
|
41
31
|
def users
|
data/lib/wabot/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: wabot
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Vikas Kumar
|
|
@@ -37,20 +37,6 @@ dependencies:
|
|
|
37
37
|
- - "~>"
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
39
|
version: '1.3'
|
|
40
|
-
- !ruby/object:Gem::Dependency
|
|
41
|
-
name: bcrypt
|
|
42
|
-
requirement: !ruby/object:Gem::Requirement
|
|
43
|
-
requirements:
|
|
44
|
-
- - "~>"
|
|
45
|
-
- !ruby/object:Gem::Version
|
|
46
|
-
version: '3.1'
|
|
47
|
-
type: :runtime
|
|
48
|
-
prerelease: false
|
|
49
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
-
requirements:
|
|
51
|
-
- - "~>"
|
|
52
|
-
- !ruby/object:Gem::Version
|
|
53
|
-
version: '3.1'
|
|
54
40
|
- !ruby/object:Gem::Dependency
|
|
55
41
|
name: colorize
|
|
56
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -82,7 +68,7 @@ files:
|
|
|
82
68
|
- lib/wabot/session_store.rb
|
|
83
69
|
- lib/wabot/user_store.rb
|
|
84
70
|
- lib/wabot/version.rb
|
|
85
|
-
homepage: https://github.com/vikas-0/
|
|
71
|
+
homepage: https://github.com/vikas-0/wabot
|
|
86
72
|
licenses:
|
|
87
73
|
- MIT
|
|
88
74
|
metadata: {}
|