deskbot 0.1.0
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/.rspec +3 -0
- data/.rubocop.yml +12 -0
- data/CHANGELOG.md +5 -0
- data/Cargo.lock +966 -0
- data/Cargo.toml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +236 -0
- data/Rakefile +18 -0
- data/ext/deskbot/Cargo.toml +16 -0
- data/ext/deskbot/extconf.rb +6 -0
- data/ext/deskbot/src/alert.rs +5 -0
- data/ext/deskbot/src/bitmap.rs +268 -0
- data/ext/deskbot/src/keys.rs +38 -0
- data/ext/deskbot/src/lib.rs +49 -0
- data/ext/deskbot/src/mouse.rs +55 -0
- data/ext/deskbot/src/screen.rs +34 -0
- data/lib/deskbot/area.rb +12 -0
- data/lib/deskbot/bitmap.rb +89 -0
- data/lib/deskbot/color.rb +36 -0
- data/lib/deskbot/point.rb +10 -0
- data/lib/deskbot/providers/autopilot/bitmap.rb +21 -0
- data/lib/deskbot/providers/autopilot.rb +28 -0
- data/lib/deskbot/screen.rb +131 -0
- data/lib/deskbot/size.rb +10 -0
- data/lib/deskbot/types.rb +30 -0
- data/lib/deskbot/version.rb +5 -0
- data/lib/deskbot.rb +28 -0
- data/sig/deskbot.rbs +4 -0
- metadata +132 -0
@@ -0,0 +1,55 @@
|
|
1
|
+
extern crate autopilot;
|
2
|
+
use std::collections::HashMap;
|
3
|
+
|
4
|
+
fn button(symbol: String) -> autopilot::mouse::Button {
|
5
|
+
match symbol.as_str() {
|
6
|
+
"left" => autopilot::mouse::Button::Left,
|
7
|
+
"middle" => autopilot::mouse::Button::Middle,
|
8
|
+
"right" => autopilot::mouse::Button::Right,
|
9
|
+
_ => panic!("Invalid button"),
|
10
|
+
}
|
11
|
+
}
|
12
|
+
|
13
|
+
fn scroll_direction(symbol: String) -> autopilot::mouse::ScrollDirection {
|
14
|
+
match symbol.as_str() {
|
15
|
+
"up" => autopilot::mouse::ScrollDirection::Up,
|
16
|
+
"down" => autopilot::mouse::ScrollDirection::Down,
|
17
|
+
_ => panic!("Invalid scroll direction"),
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
pub fn location() -> HashMap<String, f64> {
|
22
|
+
let point = autopilot::mouse::location();
|
23
|
+
return HashMap::from([("x".to_string(), point.x), ("y".to_string(), point.y)]);
|
24
|
+
}
|
25
|
+
|
26
|
+
pub fn move_to(x: f64, y: f64) -> bool {
|
27
|
+
let command = autopilot::mouse::move_to(autopilot::geometry::Point::new(x, y));
|
28
|
+
match command {
|
29
|
+
Ok(_) => true,
|
30
|
+
Err(_) => false,
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
pub fn smooth_move(x: f64, y: f64, duration: Option<f64>) -> bool {
|
35
|
+
let command = autopilot::mouse::smooth_move(autopilot::geometry::Point::new(x, y), duration);
|
36
|
+
|
37
|
+
match command {
|
38
|
+
Ok(_) => true,
|
39
|
+
Err(_) => false,
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
pub fn toggle(_button: String, down: bool) -> () {
|
44
|
+
let button = button(_button);
|
45
|
+
autopilot::mouse::toggle(button, down);
|
46
|
+
}
|
47
|
+
|
48
|
+
pub fn click(_button: String, delay_ms: Option<u64>) -> () {
|
49
|
+
let button = button(_button);
|
50
|
+
autopilot::mouse::click(button, delay_ms);
|
51
|
+
}
|
52
|
+
|
53
|
+
pub fn scroll(direction: String, clicks: u32) -> () {
|
54
|
+
autopilot::mouse::scroll(scroll_direction(direction), clicks);
|
55
|
+
}
|
@@ -0,0 +1,34 @@
|
|
1
|
+
extern crate autopilot;
|
2
|
+
use std::collections::HashMap;
|
3
|
+
|
4
|
+
pub fn get_color(x: f64, y: f64) -> Option<Vec<u8>> {
|
5
|
+
let color = autopilot::screen::get_color(autopilot::geometry::Point::new(x, y));
|
6
|
+
match color {
|
7
|
+
Ok(color) => Some(color.0.to_vec()),
|
8
|
+
Err(_) => None
|
9
|
+
}
|
10
|
+
}
|
11
|
+
|
12
|
+
pub fn size() -> HashMap<String, f64> {
|
13
|
+
let size = autopilot::screen::size();
|
14
|
+
|
15
|
+
HashMap::from([
|
16
|
+
("width".to_string(), size.width),
|
17
|
+
("height".to_string(), size.height)
|
18
|
+
])
|
19
|
+
}
|
20
|
+
|
21
|
+
pub fn scale() -> f64 {
|
22
|
+
autopilot::screen::scale()
|
23
|
+
}
|
24
|
+
|
25
|
+
pub fn is_point_visible(x: f64, y: f64) -> bool {
|
26
|
+
let point = autopilot::geometry::Point::new(x, y);
|
27
|
+
autopilot::screen::is_point_visible(point)
|
28
|
+
}
|
29
|
+
|
30
|
+
pub fn is_rect_visible(x: f64, y: f64, width: f64, height: f64) -> bool {
|
31
|
+
let point = autopilot::geometry::Point::new(x, y);
|
32
|
+
let size = autopilot::geometry::Size::new(width, height);
|
33
|
+
autopilot::screen::is_rect_visible(autopilot::geometry::Rect::new(point, size))
|
34
|
+
}
|
data/lib/deskbot/area.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Deskbot
|
4
|
+
class Bitmap
|
5
|
+
include Dry::Monads[:result]
|
6
|
+
include Dry::Matcher.for(
|
7
|
+
:find_color,
|
8
|
+
:find,
|
9
|
+
with: Dry::Matcher::ResultMatcher
|
10
|
+
)
|
11
|
+
|
12
|
+
Rgba = Types::Array
|
13
|
+
.of(Types::Integer.constrained(gteq: 0, lteq: 255))
|
14
|
+
.constrained(size: 4)
|
15
|
+
|
16
|
+
def initialize(provider)
|
17
|
+
@provider = provider
|
18
|
+
end
|
19
|
+
|
20
|
+
def save(image_path)
|
21
|
+
@provider.save(Types::String[image_path])
|
22
|
+
end
|
23
|
+
|
24
|
+
def bounds
|
25
|
+
Area.new(@provider.bounds)
|
26
|
+
end
|
27
|
+
|
28
|
+
def color_at(x, y) # rubocop:disable Naming/MethodParameterName
|
29
|
+
red, green, blue, alpha = @provider.color_at(x, y)
|
30
|
+
Color.new(red:, green:, blue:, alpha:)
|
31
|
+
end
|
32
|
+
|
33
|
+
def eql?(image_path, tolerance: nil)
|
34
|
+
@provider.bitmap_eq(
|
35
|
+
Types::String[image_path],
|
36
|
+
Types::Float.optional[tolerance]
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
def find(image_path, tolerance: nil)
|
41
|
+
result = @provider.find(
|
42
|
+
Types::String[image_path],
|
43
|
+
Types::Float.optional[tolerance]
|
44
|
+
)
|
45
|
+
|
46
|
+
if result
|
47
|
+
Success(Point.new(result))
|
48
|
+
else
|
49
|
+
Failure(:not_found)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def find_color(color, tolerance: nil)
|
54
|
+
found = @provider.find_color(
|
55
|
+
Rgba[color],
|
56
|
+
Types::Float.optional[tolerance]
|
57
|
+
)
|
58
|
+
|
59
|
+
if found
|
60
|
+
Success(Point.new(found))
|
61
|
+
else
|
62
|
+
Failure(:not_found)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def all(image_path, tolerance: nil)
|
67
|
+
@provider.all(
|
68
|
+
Types::String[image_path],
|
69
|
+
Types::Float.optional[tolerance]
|
70
|
+
)
|
71
|
+
.map { |point| Point.new(point) }
|
72
|
+
end
|
73
|
+
|
74
|
+
def all_color(color, tolerance: nil)
|
75
|
+
@provider.all_color(
|
76
|
+
Rgba[color],
|
77
|
+
Types::Float.optional[tolerance]
|
78
|
+
)
|
79
|
+
.map { |point| Point.new(point) }
|
80
|
+
end
|
81
|
+
|
82
|
+
def count(image_path, tolerance: nil)
|
83
|
+
@provider.count(
|
84
|
+
Types::String[image_path],
|
85
|
+
Types::Float.optional[tolerance]
|
86
|
+
)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Deskbot
|
4
|
+
class Color < Dry::Struct
|
5
|
+
attribute :red, Types::Integer
|
6
|
+
attribute :green, Types::Integer
|
7
|
+
attribute :blue, Types::Integer
|
8
|
+
attribute :alpha, Types::Integer
|
9
|
+
|
10
|
+
transform_keys do |key|
|
11
|
+
{
|
12
|
+
"r" => :red,
|
13
|
+
"g" => :green,
|
14
|
+
"b" => :blue,
|
15
|
+
"a" => :alpha
|
16
|
+
# rubocop:enable Style/StringHashKeys
|
17
|
+
}.fetch(key, key)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.from_hex(hex)
|
21
|
+
red, green, blue, alpha = hex
|
22
|
+
.match(/^#(..)(..)(..)(..)?$/)
|
23
|
+
.captures
|
24
|
+
.map do |hex_pair|
|
25
|
+
hex_pair&.hex
|
26
|
+
end
|
27
|
+
|
28
|
+
new(
|
29
|
+
red:,
|
30
|
+
green:,
|
31
|
+
blue:,
|
32
|
+
alpha: alpha || 255
|
33
|
+
)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Deskbot
|
4
|
+
module Providers
|
5
|
+
module Autopilot
|
6
|
+
class Bitmap # rubocop:disable Lint/EmptyClass
|
7
|
+
# Holds rust autopilot bitmap bindings
|
8
|
+
# See ext/deskbot/src/bitmap.rs for more details
|
9
|
+
#
|
10
|
+
# def bounds
|
11
|
+
# def color_at
|
12
|
+
# def bitmap_eq
|
13
|
+
# def find
|
14
|
+
# def find_color
|
15
|
+
# def all
|
16
|
+
# def all_color
|
17
|
+
# def count
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Deskbot
|
4
|
+
module Providers
|
5
|
+
module Autopilot
|
6
|
+
# Holds rust autopilot bindings
|
7
|
+
# See ext/deskbot/src/lib.rs for more details
|
8
|
+
#
|
9
|
+
# def type
|
10
|
+
# def alert
|
11
|
+
# def toggle_key
|
12
|
+
# def tap_key
|
13
|
+
# def mouse_location
|
14
|
+
# def move_mouse
|
15
|
+
# def smooth_move_mouse
|
16
|
+
# def toggle_mouse
|
17
|
+
# def scroll
|
18
|
+
# def click
|
19
|
+
# def color_at
|
20
|
+
# def screen_size
|
21
|
+
# def screen_scale
|
22
|
+
# def is_point_visible
|
23
|
+
# def is_area_visible
|
24
|
+
# def capture_screen
|
25
|
+
# def capture_screen_portion
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Deskbot
|
4
|
+
class Screen
|
5
|
+
# This is the API for any provider
|
6
|
+
|
7
|
+
def initialize(provider)
|
8
|
+
@provider = provider
|
9
|
+
end
|
10
|
+
|
11
|
+
def alert(message)
|
12
|
+
@provider.alert(Types::String[message])
|
13
|
+
end
|
14
|
+
|
15
|
+
def type(text, flags: [], wpm: 60.0, noise: 0.0)
|
16
|
+
@provider.type(
|
17
|
+
Types::String[text],
|
18
|
+
Types::Flags[flags],
|
19
|
+
Types::Float[wpm],
|
20
|
+
Types::Float[noise]
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
def toggle_key(key, down: true, flags: [], modifier_delay_ms: 0.0)
|
25
|
+
@provider.toggle_key(
|
26
|
+
Types::Character[key],
|
27
|
+
Types::Bool[down],
|
28
|
+
Types::Flags[flags],
|
29
|
+
Types::Float[modifier_delay_ms]
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
def tap_key(key, flags: [], delay_ms: 0.0, modifier_delay_ms: 0.0)
|
34
|
+
@provider.tap_key(
|
35
|
+
Types::Character[key],
|
36
|
+
Types::Flags[flags],
|
37
|
+
Types::Float[delay_ms],
|
38
|
+
Types::Float[modifier_delay_ms]
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
def mouse_location
|
43
|
+
Point.new(@provider.mouse_location)
|
44
|
+
end
|
45
|
+
|
46
|
+
def move_mouse(x, y) # rubocop:disable Naming/MethodParameterName
|
47
|
+
@provider.move_mouse(
|
48
|
+
Types::Coercible::Float[x],
|
49
|
+
Types::Coercible::Float[y]
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
def smooth_move_mouse(x, y, duration: 1) # rubocop:disable Naming/MethodParameterName
|
54
|
+
@provider.smooth_move_mouse(
|
55
|
+
Types::Coercible::Float[x],
|
56
|
+
Types::Coercible::Float[y],
|
57
|
+
Types::Coercible::Float[duration]
|
58
|
+
)
|
59
|
+
end
|
60
|
+
|
61
|
+
def toggle_mouse(button = "left", down: true)
|
62
|
+
@provider.toggle_mouse(
|
63
|
+
Types::Button[button],
|
64
|
+
Types::Bool[down]
|
65
|
+
)
|
66
|
+
end
|
67
|
+
|
68
|
+
def click(button = "left", delay_ms: nil)
|
69
|
+
@provider.click(
|
70
|
+
Types::Button[button],
|
71
|
+
Types::Float.optional[delay_ms]
|
72
|
+
)
|
73
|
+
end
|
74
|
+
|
75
|
+
def scroll(direction = "up", clicks: 1)
|
76
|
+
@provider.scroll(
|
77
|
+
Types::ScrollDirection[direction],
|
78
|
+
Types::Integer[clicks]
|
79
|
+
)
|
80
|
+
end
|
81
|
+
|
82
|
+
def color_at(x, y) # rubocop:disable Naming/MethodParameterName
|
83
|
+
red, green, blue, alpha = @provider.color_at(
|
84
|
+
Types::Coercible::Float[x],
|
85
|
+
Types::Coercible::Float[y]
|
86
|
+
)
|
87
|
+
|
88
|
+
Color.new(red:, green:, blue:, alpha:)
|
89
|
+
end
|
90
|
+
|
91
|
+
def size
|
92
|
+
Size.new(@provider.screen_size)
|
93
|
+
end
|
94
|
+
|
95
|
+
def scale
|
96
|
+
@provider.screen_scale
|
97
|
+
end
|
98
|
+
|
99
|
+
def point_visible?(x, y) # rubocop:disable Naming/MethodParameterName
|
100
|
+
@provider.is_point_visible(
|
101
|
+
Types::Coercible::Float[x],
|
102
|
+
Types::Coercible::Float[y]
|
103
|
+
)
|
104
|
+
end
|
105
|
+
|
106
|
+
def area_visible?(x:, y:, width:, height:) # rubocop:disable Naming/MethodParameterName
|
107
|
+
@provider.is_area_visible(
|
108
|
+
Types::Coercible::Float[x],
|
109
|
+
Types::Coercible::Float[y],
|
110
|
+
Types::Coercible::Float[width],
|
111
|
+
Types::Coercible::Float[height]
|
112
|
+
)
|
113
|
+
end
|
114
|
+
|
115
|
+
def capture
|
116
|
+
bitmap = @provider.capture_screen
|
117
|
+
Deskbot::Bitmap.new(bitmap)
|
118
|
+
end
|
119
|
+
|
120
|
+
def capture_area(x:, y:, width:, height:) # rubocop:disable Naming/MethodParameterName
|
121
|
+
bitmap = @provider.capture_screen_area(
|
122
|
+
Types::Coercible::Float[x],
|
123
|
+
Types::Coercible::Float[y],
|
124
|
+
Types::Coercible::Float[width],
|
125
|
+
Types::Coercible::Float[height]
|
126
|
+
)
|
127
|
+
|
128
|
+
Deskbot::Bitmap.new(bitmap)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
data/lib/deskbot/size.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Deskbot
|
4
|
+
module Types
|
5
|
+
include Dry.Types(default: :strict)
|
6
|
+
|
7
|
+
Flag = Types::Coercible::String.enum(
|
8
|
+
"shift",
|
9
|
+
"control",
|
10
|
+
"alt",
|
11
|
+
"meta",
|
12
|
+
"help"
|
13
|
+
)
|
14
|
+
|
15
|
+
Button = Types::Coercible::String.enum(
|
16
|
+
"left",
|
17
|
+
"middle",
|
18
|
+
"right"
|
19
|
+
)
|
20
|
+
|
21
|
+
Flags = Types::Array.of(Flag)
|
22
|
+
|
23
|
+
Character = Types::Coercible::String.constrained(size: 1)
|
24
|
+
|
25
|
+
ScrollDirection = Types::Coercible::String.enum(
|
26
|
+
"up",
|
27
|
+
"down"
|
28
|
+
)
|
29
|
+
end
|
30
|
+
end
|
data/lib/deskbot.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/types"
|
4
|
+
require "dry/struct"
|
5
|
+
require "dry/monads"
|
6
|
+
require "dry/matcher/result_matcher"
|
7
|
+
|
8
|
+
require_relative "deskbot/version"
|
9
|
+
require_relative "deskbot/deskbot"
|
10
|
+
require_relative "deskbot/types"
|
11
|
+
require_relative "deskbot/point"
|
12
|
+
require_relative "deskbot/color"
|
13
|
+
require_relative "deskbot/size"
|
14
|
+
require_relative "deskbot/area"
|
15
|
+
require_relative "deskbot/bitmap"
|
16
|
+
|
17
|
+
require "deskbot/providers/autopilot/bitmap"
|
18
|
+
require "deskbot/providers/autopilot"
|
19
|
+
|
20
|
+
require "deskbot/screen"
|
21
|
+
|
22
|
+
module Deskbot
|
23
|
+
class Error < StandardError; end
|
24
|
+
|
25
|
+
def self.screen(provider: Providers::Autopilot)
|
26
|
+
@screen ||= Screen.new(provider)
|
27
|
+
end
|
28
|
+
end
|
data/sig/deskbot.rbs
ADDED
metadata
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: deskbot
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nolan J Tait
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-05-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: dry-matcher
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: dry-monads
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.6'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.6'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: dry-struct
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.6'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.6'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: dry-types
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.7'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.7'
|
69
|
+
description: Ruby desktop automation
|
70
|
+
email:
|
71
|
+
- nolanjtait@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions:
|
74
|
+
- ext/deskbot/Cargo.toml
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- ".rspec"
|
78
|
+
- ".rubocop.yml"
|
79
|
+
- CHANGELOG.md
|
80
|
+
- Cargo.lock
|
81
|
+
- Cargo.toml
|
82
|
+
- LICENSE.txt
|
83
|
+
- README.md
|
84
|
+
- Rakefile
|
85
|
+
- ext/deskbot/Cargo.toml
|
86
|
+
- ext/deskbot/extconf.rb
|
87
|
+
- ext/deskbot/src/alert.rs
|
88
|
+
- ext/deskbot/src/bitmap.rs
|
89
|
+
- ext/deskbot/src/keys.rs
|
90
|
+
- ext/deskbot/src/lib.rs
|
91
|
+
- ext/deskbot/src/mouse.rs
|
92
|
+
- ext/deskbot/src/screen.rs
|
93
|
+
- lib/deskbot.rb
|
94
|
+
- lib/deskbot/area.rb
|
95
|
+
- lib/deskbot/bitmap.rb
|
96
|
+
- lib/deskbot/color.rb
|
97
|
+
- lib/deskbot/point.rb
|
98
|
+
- lib/deskbot/providers/autopilot.rb
|
99
|
+
- lib/deskbot/providers/autopilot/bitmap.rb
|
100
|
+
- lib/deskbot/screen.rb
|
101
|
+
- lib/deskbot/size.rb
|
102
|
+
- lib/deskbot/types.rb
|
103
|
+
- lib/deskbot/version.rb
|
104
|
+
- sig/deskbot.rbs
|
105
|
+
homepage: https://github.com/nolantait/desktbot
|
106
|
+
licenses:
|
107
|
+
- MIT
|
108
|
+
metadata:
|
109
|
+
homepage_uri: https://github.com/nolantait/desktbot
|
110
|
+
source_code_uri: https://github.com/nolantait/desktbot
|
111
|
+
changelog_uri: https://github.com/nolantait/desktbot
|
112
|
+
rubygems_mfa_required: 'true'
|
113
|
+
post_install_message:
|
114
|
+
rdoc_options: []
|
115
|
+
require_paths:
|
116
|
+
- lib
|
117
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - ">="
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '3.3'
|
122
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - ">="
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: 3.3.11
|
127
|
+
requirements: []
|
128
|
+
rubygems_version: 3.5.9
|
129
|
+
signing_key:
|
130
|
+
specification_version: 4
|
131
|
+
summary: Ruby dekstop automation
|
132
|
+
test_files: []
|