chromate-rb 0.0.1.pre → 0.0.3.pre

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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +2 -0
  3. data/CHANGELOG.md +72 -3
  4. data/README.md +33 -6
  5. data/Rakefile +48 -16
  6. data/docker_root/Gemfile +4 -0
  7. data/docker_root/Gemfile.lock +28 -0
  8. data/docker_root/TestInDocker.gif +0 -0
  9. data/docker_root/app.rb +87 -0
  10. data/dockerfiles/Dockerfile +21 -7
  11. data/dockerfiles/README.md +49 -0
  12. data/docs/BOT_BROWSER.md +74 -0
  13. data/docs/README.md +74 -0
  14. data/docs/browser.md +124 -102
  15. data/docs/client.md +126 -0
  16. data/docs/element.md +365 -0
  17. data/docs/elements/checkbox.md +69 -0
  18. data/docs/elements/radio.md +57 -0
  19. data/lib/bot_browser/downloader.rb +64 -0
  20. data/lib/bot_browser/installer.rb +99 -0
  21. data/lib/bot_browser.rb +43 -0
  22. data/lib/chromate/actions/dom.rb +35 -27
  23. data/lib/chromate/actions/navigate.rb +7 -5
  24. data/lib/chromate/actions/screenshot.rb +71 -14
  25. data/lib/chromate/actions/stealth.rb +62 -0
  26. data/lib/chromate/binary.rb +83 -0
  27. data/lib/chromate/browser.rb +120 -24
  28. data/lib/chromate/c_logger.rb +8 -0
  29. data/lib/chromate/client.rb +65 -26
  30. data/lib/chromate/configuration.rb +31 -14
  31. data/lib/chromate/element.rb +119 -16
  32. data/lib/chromate/elements/checkbox.rb +40 -0
  33. data/lib/chromate/elements/option.rb +43 -0
  34. data/lib/chromate/elements/radio.rb +37 -0
  35. data/lib/chromate/elements/select.rb +50 -6
  36. data/lib/chromate/elements/tags.rb +29 -0
  37. data/lib/chromate/exceptions.rb +2 -0
  38. data/lib/chromate/files/agents.json +11 -0
  39. data/lib/chromate/files/stealth.js +199 -0
  40. data/lib/chromate/hardwares/keyboard_controller.rb +45 -0
  41. data/lib/chromate/hardwares/keyboards/virtual_controller.rb +65 -0
  42. data/lib/chromate/hardwares/mouse_controller.rb +55 -11
  43. data/lib/chromate/hardwares/mouses/linux_controller.rb +124 -21
  44. data/lib/chromate/hardwares/mouses/mac_os_controller.rb +6 -6
  45. data/lib/chromate/hardwares/mouses/virtual_controller.rb +95 -7
  46. data/lib/chromate/hardwares/mouses/x11.rb +36 -0
  47. data/lib/chromate/hardwares.rb +19 -3
  48. data/lib/chromate/helpers.rb +22 -15
  49. data/lib/chromate/user_agent.rb +41 -15
  50. data/lib/chromate/version.rb +1 -1
  51. data/lib/chromate.rb +2 -0
  52. data/logo.png +0 -0
  53. data/results/bot.png +0 -0
  54. data/results/brotector.png +0 -0
  55. data/results/cloudflare.png +0 -0
  56. data/results/headers.png +0 -0
  57. data/results/pixelscan.png +0 -0
  58. metadata +45 -2
@@ -85,7 +85,7 @@ module Chromate
85
85
  system_point = CGEventGetLocation(event)
86
86
  CFRelease(event)
87
87
 
88
- # Convertir les coordonnées système en coordonnées navigateur
88
+ # Convert the system coordinates to browser coordinates
89
89
  browser_x = system_point[:x] / @scale_factor
90
90
  browser_y = (@display_height - system_point[:y]) / @scale_factor
91
91
 
@@ -94,7 +94,7 @@ module Chromate
94
94
  y: browser_y
95
95
  }
96
96
 
97
- # Retourner un nouveau CGPoint avec les coordonnées système
97
+ # Return the browser coordinates
98
98
  CGPoint.new.tap do |p|
99
99
  p[:x] = system_point[:x]
100
100
  p[:y] = system_point[:y]
@@ -102,7 +102,7 @@ module Chromate
102
102
  end
103
103
 
104
104
  def convert_coordinates(browser_x, browser_y)
105
- # Convertir les coordonnées du navigateur en coordonnées système
105
+ # Convert the browser coordinates to system coordinates
106
106
  system_x = browser_x * @scale_factor
107
107
  system_y = @display_height - (browser_y * @scale_factor)
108
108
 
@@ -113,12 +113,12 @@ module Chromate
113
113
  end
114
114
 
115
115
  def determine_scale_factor
116
- # Obtenir le facteur d'échelle en comparant les dimensions logiques et physiques
117
- # Par défaut, utiliser 2.0 pour les écrans Retina
116
+ # Determine the scale factor for the display
117
+ # By default, the scale factor is 2.0 for Retina displays
118
118
 
119
119
  `system_profiler SPDisplaysDataType | grep -i "retina"`.empty? ? 1.0 : 2.0
120
120
  rescue StandardError
121
- 2.0 # Par défaut pour les écrans Retina modernes
121
+ 2.0 # Default to 2.0 if the scale factor cannot be determined
122
122
  end
123
123
  end
124
124
  end
@@ -4,11 +4,19 @@ module Chromate
4
4
  module Hardwares
5
5
  module Mouses
6
6
  class VirtualController < Chromate::Hardwares::MouseController
7
- def hover
8
- steps = rand(25..50)
9
- points = bezier_curve(steps: steps)
10
- duration = rand(0.1..0.3)
7
+ def hover # rubocop:disable Metrics/AbcSize
8
+ # Define the target position
9
+ target_x = element.x + (element.width / 2) + rand(-20..20)
10
+ target_y = element.y + (element.height / 2) + rand(-20..20)
11
+ start_x = mouse_position[:x]
12
+ start_y = mouse_position[:y]
13
+ steps = rand(25..50)
14
+ duration = rand(0.1..0.3)
11
15
 
16
+ # Generate a Bézier curve for natural movement
17
+ points = bezier_curve(steps: steps, start_x: start_x, start_y: start_y, t_x: target_x, t_y: target_y)
18
+
19
+ # Move the mouse along the Bézier curve
12
20
  points.each do |point|
13
21
  dispatch_mouse_event('mouseMoved', point[:x], point[:y])
14
22
  sleep(duration / steps)
@@ -35,12 +43,53 @@ module Chromate
35
43
  dispatch_mouse_event('mouseReleased', target_x, target_y, button: 'right', click_count: 1)
36
44
  end
37
45
 
46
+ # @param [Chromate::Element] element
47
+ # @return [self]
48
+ def drag_and_drop_to(element) # rubocop:disable Metrics/AbcSize
49
+ hover
50
+
51
+ target_x = element.x + (element.width / 2)
52
+ target_y = element.y + (element.height / 2)
53
+ start_x = mouse_position[:x]
54
+ start_y = mouse_position[:y]
55
+ steps = rand(25..50)
56
+ duration = rand(0.1..0.3)
57
+
58
+ # Generate a Bézier curve for natural movement
59
+ points = bezier_curve(steps: steps, start_x: start_x, start_y: start_y, t_x: target_x, t_y: target_y)
60
+
61
+ # Step 1: Start the drag (dragStart, dragEnter)
62
+ move_mouse_to(start_x, start_y)
63
+ dispatch_drag_event('dragEnter', start_x, start_y)
64
+
65
+ # Step 2: Drag the element (dragOver)
66
+ points.each do |point|
67
+ move_mouse_to(point[:x], point[:y])
68
+ dispatch_drag_event('dragOver', point[:x], point[:y])
69
+ sleep(duration / steps)
70
+ end
71
+
72
+ # Step 3: Drop the element (drop)
73
+ move_mouse_to(target_x, target_y)
74
+ dispatch_drag_event('drop', target_x, target_y)
75
+
76
+ # Step 4: End the drag (dragEnd)
77
+ dispatch_drag_event('dragEnd', target_x, target_y)
78
+
79
+ update_mouse_position(target_x, target_y)
80
+
81
+ self
82
+ end
83
+
38
84
  private
39
85
 
86
+ # @return [self]
40
87
  def click!
41
88
  dispatch_mouse_event('mousePressed', target_x, target_y, button: 'left', click_count: 1)
42
89
  sleep(rand(CLICK_DURATION_RANGE))
43
90
  dispatch_mouse_event('mouseReleased', target_x, target_y, button: 'left', click_count: 1)
91
+
92
+ self
44
93
  end
45
94
 
46
95
  # @param [String] type mouseMoved, mousePressed, mouseReleased
@@ -64,9 +113,48 @@ module Chromate
64
113
  client.send_message('Input.dispatchMouseEvent', params)
65
114
  end
66
115
 
67
- def update_mouse_position(target_x, target_y)
68
- @mouse_position[:x] = target_x
69
- @mouse_position[:y] = target_y
116
+ # @param [Integer] steps
117
+ # @param [Integer] x
118
+ # @param [Integer] y
119
+ # @return [Array<Hash>]
120
+ def dispatch_drag_event(type, x, y) # rubocop:disable Naming/MethodParameterName
121
+ params = {
122
+ type: type,
123
+ x: x,
124
+ y: y,
125
+ data: {
126
+ items: [
127
+ {
128
+ mimeType: 'text/plain',
129
+ data: 'dragged'
130
+ }
131
+ ],
132
+ dragOperationsMask: 1
133
+ }
134
+ }
135
+
136
+ client.send_message('Input.dispatchDragEvent', params)
137
+ end
138
+
139
+ # @param [Integer] x_target
140
+ # @param [Integer] y_target
141
+ # @return [self]
142
+ def move_mouse_to(x_target, y_target)
143
+ params = {
144
+ type: 'mouseMoved',
145
+ x: x_target,
146
+ y: y_target,
147
+ button: 'none',
148
+ clickCount: 0,
149
+ deltaX: 0,
150
+ deltaY: 0,
151
+ modifiers: 0,
152
+ timestamp: (Time.now.to_f * 1000).to_i
153
+ }
154
+
155
+ client.send_message('Input.dispatchMouseEvent', params)
156
+
157
+ self
70
158
  end
71
159
  end
72
160
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ffi'
4
+ require 'chromate/helpers'
5
+
6
+ module X11
7
+ extend FFI::Library
8
+ ffi_lib 'X11'
9
+
10
+ # Types
11
+ typedef :ulong, :Window
12
+ typedef :pointer, :Display
13
+
14
+ # X11 functions
15
+ attach_function :XOpenDisplay, [:string], :pointer
16
+ attach_function :XCloseDisplay, [:pointer], :int
17
+ attach_function :XDefaultRootWindow, [:pointer], :ulong
18
+ attach_function :XWarpPointer, %i[pointer ulong ulong int int uint uint int int], :int
19
+ attach_function :XQueryPointer, %i[pointer ulong pointer pointer pointer pointer pointer pointer pointer], :bool
20
+ attach_function :XFlush, [:pointer], :int
21
+ attach_function :XQueryTree, %i[pointer ulong pointer pointer pointer pointer], :int
22
+ attach_function :XFetchName, %i[pointer ulong pointer], :int
23
+ attach_function :XFree, [:pointer], :int
24
+ attach_function :XRaiseWindow, %i[pointer ulong], :int
25
+ attach_function :XSetInputFocus, %i[pointer ulong int ulong], :int
26
+
27
+ # Constants
28
+ REVERT_TO_PARENT = 2
29
+ end
30
+
31
+ module Xtst
32
+ extend FFI::Library
33
+ ffi_lib 'Xtst'
34
+
35
+ attach_function :XTestFakeButtonEvent, %i[pointer uint int ulong], :int
36
+ end
@@ -1,33 +1,49 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'chromate/c_logger'
4
+ require 'chromate/hardwares/keyboard_controller'
4
5
  require 'chromate/hardwares/mouse_controller'
5
6
  require 'chromate/hardwares/mouses/virtual_controller'
7
+ require 'chromate/hardwares/keyboards/virtual_controller'
6
8
  require 'chromate/helpers'
7
9
 
8
10
  module Chromate
9
11
  module Hardwares
10
12
  extend Helpers
11
13
 
14
+ # @param [Hash] args
15
+ # @option args [Chromate::Client] :client
16
+ # @option args [Chromate::Element] :element
17
+ # @return [Chromate::Hardwares::MouseController]
12
18
  def mouse(**args)
13
19
  browser = args[:client].browser
14
20
  if browser.options[:native_control]
15
21
  if mac?
16
- Chromate::CLogger.log('🐁 Loading MacOs mouse controller')
22
+ Chromate::CLogger.log('👨🏼‍💻🐁 Loading MacOs mouse controller')
17
23
  require 'chromate/hardwares/mouses/mac_os_controller'
18
24
  return Mouses::MacOsController.new(**args)
19
25
  end
20
26
  if linux?
21
- Chromate::CLogger.log('🐁 Loading Linux mouse controller')
27
+ Chromate::CLogger.log('👨🏼‍💻🐁 Loading Linux mouse controller')
22
28
  require 'chromate/hardwares/mouses/linux_controller'
23
29
  return Mouses::LinuxController.new(**args)
24
30
  end
25
31
  raise 'Native mouse controller is not supported on Windows' if windows?
26
32
  else
27
- Chromate::CLogger.log('🐁 Loading Virtual mouse controller')
33
+ Chromate::CLogger.log('🤖🐁 Loading Virtual mouse controller')
28
34
  Mouses::VirtualController.new(**args)
29
35
  end
30
36
  end
31
37
  module_function :mouse
38
+
39
+ # @param [Hash] args
40
+ # @option args [Chromate::Client] :client
41
+ # @option args [Chromate::Element] :element
42
+ # @return [Chromate::Hardwares::KeyboardController]
43
+ def keyboard(**args)
44
+ Chromate::CLogger.log('🤖⌨️ Loading Virtual keyboard controller')
45
+ Keyboards::VirtualController.new(**args)
46
+ end
47
+ module_function :keyboard
32
48
  end
33
49
  end
@@ -1,23 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'rbconfig'
4
- module Helpers
5
- def linux?
6
- RbConfig::CONFIG['host_os'] =~ /linux|bsd/i
7
- end
8
4
 
9
- def mac?
10
- RbConfig::CONFIG['host_os'] =~ /darwin/i
11
- end
5
+ module Chromate
6
+ module Helpers
7
+ # @return [Boolean]
8
+ def linux?
9
+ RbConfig::CONFIG['host_os'] =~ /linux|bsd/i
10
+ end
12
11
 
13
- def windows?
14
- RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/i
15
- end
12
+ # @return [Boolean]
13
+ def mac?
14
+ RbConfig::CONFIG['host_os'] =~ /darwin/i
15
+ end
16
+
17
+ # @return [Boolean]
18
+ def windows?
19
+ RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/i
20
+ end
16
21
 
17
- def find_available_port
18
- server = TCPServer.new('127.0.0.1', 0)
19
- port = server.addr[1]
20
- server.close
21
- port
22
+ # @return [Integer]
23
+ def find_available_port
24
+ server = TCPServer.new('127.0.0.1', 0)
25
+ port = server.addr[1]
26
+ server.close
27
+ port
28
+ end
22
29
  end
23
30
  end
@@ -2,26 +2,25 @@
2
2
 
3
3
  module Chromate
4
4
  class UserAgent
5
+ # @return [String]
5
6
  def self.call
6
- new.call
7
- end
8
-
9
- attr_reader :os
10
-
11
- def initialize
12
- @os = find_os
13
- end
14
-
15
- def call
16
- 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36'
7
+ case os
8
+ when 'Linux'
9
+ linux_agent
10
+ when 'Mac'
11
+ mac_agent
12
+ when 'Windows'
13
+ windows_agent
14
+ else
15
+ raise 'Unknown OS'
16
+ end
17
17
  end
18
18
 
19
- private
20
-
21
- def find_os
19
+ # @return [String<'Mac', 'Linux', 'Windows', 'Unknown'>]
20
+ def self.os
22
21
  case RUBY_PLATFORM
23
22
  when /darwin/
24
- 'Macintosh'
23
+ 'Mac'
25
24
  when /linux/
26
25
  'Linux'
27
26
  when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
@@ -30,5 +29,32 @@ module Chromate
30
29
  'Unknown'
31
30
  end
32
31
  end
32
+
33
+ def self.arch
34
+ case RUBY_PLATFORM
35
+ when /x64-mingw32/
36
+ 'x64'
37
+ when /x86_64-mingw32/
38
+ 'x86_64'
39
+ else
40
+ 'x86'
41
+ end
42
+ end
43
+
44
+ def self.agents
45
+ @agents ||= JSON.parse(File.read(File.join(__dir__, 'files/agents.json')))
46
+ end
47
+
48
+ def self.linux_agent
49
+ agents['linux'].sample
50
+ end
51
+
52
+ def self.mac_agent
53
+ agents['mac'].sample
54
+ end
55
+
56
+ def self.windows_agent
57
+ agents['windows'].sample
58
+ end
33
59
  end
34
60
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Chromate
4
- VERSION = '0.0.1.pre'
4
+ VERSION = '0.0.3.pre'
5
5
  end
data/lib/chromate.rb CHANGED
@@ -6,10 +6,12 @@ require_relative 'chromate/configuration'
6
6
 
7
7
  module Chromate
8
8
  class << self
9
+ # @yield [Chromate::Configuration]
9
10
  def configure
10
11
  yield configuration
11
12
  end
12
13
 
14
+ # @return [Chromate::Configuration]
13
15
  def configuration
14
16
  @configuration ||= Configuration.new
15
17
  end
data/logo.png ADDED
Binary file
data/results/bot.png ADDED
Binary file
Binary file
Binary file
Binary file
Binary file
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chromate-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.pre
4
+ version: 0.0.3.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eth3rnit3
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-11-18 00:00:00.000000000 Z
11
+ date: 2025-02-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 1.17.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: user_agent_parser
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 2.18.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 2.18.0
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: websocket-client-simple
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -54,30 +68,59 @@ files:
54
68
  - LICENSE.txt
55
69
  - README.md
56
70
  - Rakefile
71
+ - docker_root/Gemfile
72
+ - docker_root/Gemfile.lock
73
+ - docker_root/TestInDocker.gif
74
+ - docker_root/app.rb
57
75
  - dockerfiles/Dockerfile
76
+ - dockerfiles/README.md
58
77
  - dockerfiles/docker-entrypoint.sh
78
+ - docs/BOT_BROWSER.md
79
+ - docs/README.md
59
80
  - docs/browser.md
81
+ - docs/client.md
82
+ - docs/element.md
83
+ - docs/elements/checkbox.md
84
+ - docs/elements/radio.md
85
+ - lib/bot_browser.rb
86
+ - lib/bot_browser/downloader.rb
87
+ - lib/bot_browser/installer.rb
60
88
  - lib/chromate.rb
61
89
  - lib/chromate/actions/dom.rb
62
90
  - lib/chromate/actions/navigate.rb
63
91
  - lib/chromate/actions/screenshot.rb
92
+ - lib/chromate/actions/stealth.rb
93
+ - lib/chromate/binary.rb
64
94
  - lib/chromate/browser.rb
65
95
  - lib/chromate/c_logger.rb
66
96
  - lib/chromate/client.rb
67
97
  - lib/chromate/configuration.rb
68
98
  - lib/chromate/element.rb
99
+ - lib/chromate/elements/checkbox.rb
100
+ - lib/chromate/elements/option.rb
101
+ - lib/chromate/elements/radio.rb
69
102
  - lib/chromate/elements/select.rb
103
+ - lib/chromate/elements/tags.rb
70
104
  - lib/chromate/exceptions.rb
105
+ - lib/chromate/files/agents.json
106
+ - lib/chromate/files/stealth.js
71
107
  - lib/chromate/hardwares.rb
108
+ - lib/chromate/hardwares/keyboard_controller.rb
109
+ - lib/chromate/hardwares/keyboards/virtual_controller.rb
72
110
  - lib/chromate/hardwares/mouse_controller.rb
73
111
  - lib/chromate/hardwares/mouses/linux_controller.rb
74
112
  - lib/chromate/hardwares/mouses/mac_os_controller.rb
75
113
  - lib/chromate/hardwares/mouses/virtual_controller.rb
114
+ - lib/chromate/hardwares/mouses/x11.rb
76
115
  - lib/chromate/helpers.rb
77
116
  - lib/chromate/user_agent.rb
78
117
  - lib/chromate/version.rb
118
+ - logo.png
119
+ - results/bot.png
79
120
  - results/brotector.png
80
121
  - results/cloudflare.png
122
+ - results/headers.png
123
+ - results/pixelscan.png
81
124
  - sig/chromate.rbs
82
125
  homepage: http://github.com/Eth3rnit3/chromate
83
126
  licenses: