manymessage 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1314729bc6ffc052a1c3ee29cf3b4b36ce076ecfdf36198433388393f37b2dcd
4
+ data.tar.gz: 412607bdc3f5710b5f45d18945021010f78f0573c4ed82fc751aa3fa31ec39d7
5
+ SHA512:
6
+ metadata.gz: df451253342918a0d18ed260c6823f1b062b31f24624d78277c74beecc84662d8570e923288b5bf00718a444f4cda7add067913aff9cbc3077d353986deeb6f8
7
+ data.tar.gz: e18f900dddd1e2df784485242b1be63670c18e50513eb724c54c870ec67410b29858a88cf02a6b388c31129b7c7b99dd7c38594495e689196072e14c085ac0de
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.standard.yml ADDED
@@ -0,0 +1,3 @@
1
+ # For available configuration options, see:
2
+ # https://github.com/testdouble/standard
3
+ ruby_version: 2.6
data/.tool-versions ADDED
@@ -0,0 +1 @@
1
+ ruby 3.1.2
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ # manymessage changelog
2
+
3
+ ## [0.0.1] - 2022-10-08
4
+
5
+ - Initial release!
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in manymessage.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+
10
+ gem "rspec", "~> 3.0"
11
+
12
+ gem "standard", "~> 1.3"
data/Gemfile.lock ADDED
@@ -0,0 +1,97 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ manymessage (0.1.0)
5
+ imessage (~> 0.4.0)
6
+ json (~> 2.6)
7
+ os (~> 1.1)
8
+ paint (~> 2.2)
9
+ phony (~> 2.19)
10
+ ptools (~> 1.4)
11
+ shellwords (~> 0.1.0)
12
+ tty-progressbar (~> 0.18.2)
13
+ tty-prompt (~> 0.23.1)
14
+
15
+ GEM
16
+ remote: https://rubygems.org/
17
+ specs:
18
+ ast (2.4.2)
19
+ diff-lcs (1.5.0)
20
+ imessage (0.4.0)
21
+ json (2.6.2)
22
+ os (1.1.4)
23
+ paint (2.3.0)
24
+ parallel (1.22.1)
25
+ parser (3.1.2.1)
26
+ ast (~> 2.4.1)
27
+ pastel (0.8.0)
28
+ tty-color (~> 0.5)
29
+ phony (2.20.1)
30
+ ptools (1.4.2)
31
+ rainbow (3.1.1)
32
+ rake (13.0.6)
33
+ regexp_parser (2.6.0)
34
+ rexml (3.2.5)
35
+ rspec (3.11.0)
36
+ rspec-core (~> 3.11.0)
37
+ rspec-expectations (~> 3.11.0)
38
+ rspec-mocks (~> 3.11.0)
39
+ rspec-core (3.11.0)
40
+ rspec-support (~> 3.11.0)
41
+ rspec-expectations (3.11.1)
42
+ diff-lcs (>= 1.2.0, < 2.0)
43
+ rspec-support (~> 3.11.0)
44
+ rspec-mocks (3.11.1)
45
+ diff-lcs (>= 1.2.0, < 2.0)
46
+ rspec-support (~> 3.11.0)
47
+ rspec-support (3.11.1)
48
+ rubocop (1.35.1)
49
+ json (~> 2.3)
50
+ parallel (~> 1.10)
51
+ parser (>= 3.1.2.1)
52
+ rainbow (>= 2.2.2, < 4.0)
53
+ regexp_parser (>= 1.8, < 3.0)
54
+ rexml (>= 3.2.5, < 4.0)
55
+ rubocop-ast (>= 1.20.1, < 2.0)
56
+ ruby-progressbar (~> 1.7)
57
+ unicode-display_width (>= 1.4.0, < 3.0)
58
+ rubocop-ast (1.21.0)
59
+ parser (>= 3.1.1.0)
60
+ rubocop-performance (1.14.3)
61
+ rubocop (>= 1.7.0, < 2.0)
62
+ rubocop-ast (>= 0.4.0)
63
+ ruby-progressbar (1.11.0)
64
+ shellwords (0.1.0)
65
+ standard (1.16.1)
66
+ rubocop (= 1.35.1)
67
+ rubocop-performance (= 1.14.3)
68
+ strings-ansi (0.2.0)
69
+ tty-color (0.6.0)
70
+ tty-cursor (0.7.1)
71
+ tty-progressbar (0.18.2)
72
+ strings-ansi (~> 0.2)
73
+ tty-cursor (~> 0.7)
74
+ tty-screen (~> 0.8)
75
+ unicode-display_width (>= 1.6, < 3.0)
76
+ tty-prompt (0.23.1)
77
+ pastel (~> 0.8)
78
+ tty-reader (~> 0.8)
79
+ tty-reader (0.9.0)
80
+ tty-cursor (~> 0.7)
81
+ tty-screen (~> 0.8)
82
+ wisper (~> 2.0)
83
+ tty-screen (0.8.1)
84
+ unicode-display_width (2.3.0)
85
+ wisper (2.0.1)
86
+
87
+ PLATFORMS
88
+ x86_64-darwin-21
89
+
90
+ DEPENDENCIES
91
+ manymessage!
92
+ rake (~> 13.0)
93
+ rspec (~> 3.0)
94
+ standard (~> 1.3)
95
+
96
+ BUNDLED WITH
97
+ 2.3.23
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022 jltml
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,44 @@
1
+ # Manymessage
2
+
3
+ Hi! This is a simple program that sends a message to many people all at once. (Or at least in very, very quick succession.)
4
+
5
+ ## Installation
6
+
7
+ You can install with RubyGems!
8
+
9
+ ```shell
10
+ $ gem install manymessage
11
+ ```
12
+
13
+ I'm hopefully going to add Homebrew soon, too.
14
+
15
+ ## Usage
16
+
17
+ Here's an example:
18
+ ```shell
19
+ manymessage --to input_names.txt --message message.txt
20
+ ```
21
+
22
+ `input_names.txt` (or whatever you name the file) should be a plain-text list of names, like First Last, with a name on each line. Manymessage will download and run [contacts-cli](https://github.com/pepebecker/contacts-cli) to get all your contacts, then will filter them according to the names in the aforementioned text file before pairing each name with that person's phone number. Then, it uses the [imessage gem](https://github.com/linjunpop/imessage) to send your message to each person, which in turn actually uses AppleScript.
23
+
24
+ `message.txt` is… surprise, the message you'd like to send (it also doesn't have to be named `message.txt`)
25
+
26
+ ---
27
+
28
+ *Note: all of the stuff below is from the default README generated by Bundler, so it wasn't written by me, but all of it is applicable!*
29
+
30
+ ---
31
+
32
+ ## Development
33
+
34
+ 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.
35
+
36
+ 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 the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
37
+
38
+ ## Contributing
39
+
40
+ Bug reports and pull requests are welcome on GitHub at https://github.com/jltml/manymessage.
41
+
42
+ ## License
43
+
44
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "standard/rake"
9
+
10
+ task default: %i[spec standard]
data/exe/manymessage ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift(
4
+ "#{__dir__}/../lib"
5
+ )
6
+
7
+ require "manymessage"
8
+
9
+ Manymessage::Cli.new(ARGV).run
@@ -0,0 +1,46 @@
1
+ module Manymessage
2
+ class Cli
3
+ def initialize(argv)
4
+ @argv = argv
5
+ @options = {}
6
+ end
7
+
8
+ def run
9
+ OptionParser.new do |parser|
10
+ parser.on("-t", "--to FILE", "Input text file to read recipient contacts from (where each line is 'First Last')") do |input_path|
11
+ @options[:input_path] = input_path
12
+ end
13
+ parser.on("-m", "--message FILE", "Input text file containing the message you'd like to send") do |message_path|
14
+ @options[:message_path] = message_path
15
+ end
16
+ # parser.on("-o", "--output FILE", "Output .vcf file to write to (include .vcf extension in argument)") do |output|
17
+ # @options[:output] = output
18
+ # end
19
+ parser.on("-c", "--contacts-cli PATH/TO/CONTACTS-CLI", "Manually specify where the contacts-cli executable is") do |path|
20
+ @options[:contacts_cli_path] = path
21
+ end
22
+ parser.on("-s", "--[no-]self", "Include your own contact in the output") do |include_self|
23
+ @options[:include_self] = include_self
24
+ end
25
+ parser.on("-V", "--verbose", "Make the output more verbose") do |verbosity|
26
+ @options[:verbose] = verbosity
27
+ end
28
+ # parser.on("--phone-input", "DOESN'T WORK YET: Use phone numbers as an input instead of names and skip matching") do |phone_input|
29
+ # @options[:phone_input] = phone_input
30
+ # end
31
+ parser.on("-v", "--version", "Print manymessage's version") do
32
+ puts "manymessage #{Manymessage::VERSION}"
33
+ puts "https://github.com/jltml/manymessage"
34
+ begin
35
+ puts OS.report
36
+ puts "ruby_bin: #{OS.ruby_bin}"
37
+ rescue
38
+ nil
39
+ end
40
+ exit
41
+ end
42
+ end.parse!
43
+ Manymessage.send(@options)
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Manymessage
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,173 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "optparse"
4
+ require "json"
5
+ require "ptools"
6
+ require "os"
7
+ require "pathname"
8
+ require "phony"
9
+ require "paint"
10
+ require "shellwords"
11
+ require "imessage"
12
+ require "tty-progressbar"
13
+ require "tty-prompt"
14
+ require_relative "manymessage/version"
15
+ require_relative "manymessage/cli"
16
+
17
+ module Manymessage
18
+ class Error < StandardError; end
19
+ # Your code goes here...
20
+
21
+ def self.send(options)
22
+ if !options[:input_path] && !options[:message_path]
23
+ warn Paint["Missing both required input files (list of contacts and message)", :red, :bold]
24
+ warn Paint["Please try again with something like `manymessage --to FILE --message FILE`", :red]
25
+ warn Paint["See `manymessage --help for more help`", :red]
26
+ abort
27
+ end
28
+ abort Paint["No input file specified with list of contacts", :red, :bold] unless options[:input_path]
29
+ abort Paint["No message file specified", :red, :bold] unless options[:input_path]
30
+ input_path = options[:input_path]
31
+ contacts_cli_path = options[:contacts_cli_path] || Pathname.new(__dir__).parent.to_s + "/exe/contacts_cli"
32
+
33
+ if File.exist?(contacts_cli_path) || File.which("contacts-cli")
34
+ puts Paint["→ contacts-cli already found; skipping download and chmod", :faint]
35
+ elsif File.which("curl")
36
+ puts Paint["→ Downloading contacts-cli from https://github.com/pepebecker/contacts-cli/releases/download/v0.1.0/contacts-cli…", :bold]
37
+ puts Paint["→ Downloading to #{contacts_cli_path}"]
38
+ `curl -o '#{contacts_cli_path}' -L 'https://github.com/pepebecker/contacts-cli/releases/download/v0.1.0/contacts-cli'`
39
+ `chmod +x '#{contacts_cli_path}'`
40
+ puts
41
+ else
42
+ abort Paint[<<~ERROR, :red]
43
+ → cURL doesn't seem to be installed (or at least it's not in your $PATH)
44
+ can't install dependency contacts-cli
45
+ ERROR
46
+ end
47
+
48
+ unless File.binary?(contacts_cli_path)
49
+ abort Paint[<<~ERROR, :red]
50
+ → error: #{contacts_cli_path} exists but is not a binary
51
+ (please delete it and try running this again)
52
+ ERROR
53
+ end
54
+
55
+ puts Paint["→ Running `contacts-cli` to gather contacts"]
56
+
57
+ contacts_cli_output = `#{contacts_cli_path.shellescape}`
58
+ contacts_cli_output.gsub!(/\R+/, ", ").delete_suffix!(", ")
59
+ contacts_cli_output = "[#{contacts_cli_output}]"
60
+
61
+ contacts = JSON.parse(contacts_cli_output)
62
+
63
+ names = []
64
+
65
+ File.read(input_path).each_line do |line|
66
+ line_array = line.split(" ")
67
+ names << {first: line_array[0], last: line_array[1]}
68
+ end
69
+
70
+ if options[:include_self]
71
+ id_f = `id -F`
72
+ line_array = id_f.split(" ")
73
+ names << {first: line_array[0], last: line_array[1]}
74
+ end
75
+
76
+ matches = []
77
+
78
+ puts Paint["→ Matching names in #{File.basename(input_path)} with their contact"]
79
+
80
+ contacts.each do |entry|
81
+ first_name = entry["firstName"]
82
+ last_name = entry["lastName"]
83
+ if first_name && last_name && names.any? { |name| (name[:first] == first_name && name[:last] == last_name) }
84
+ matches << entry
85
+ end
86
+ end
87
+
88
+ matches.sort_by! { |matches| matches["lastName"] }
89
+
90
+ matches_list = []
91
+ failed_list = []
92
+ phones = {}
93
+
94
+ # I have no idea why I have to do this, but this avoids entries vanishing when trying to delete them as a result of failed phone number validation
95
+ to_delete = []
96
+
97
+ matches.each do |entry|
98
+ first_name = entry["firstName"]
99
+ last_name = entry["lastName"]
100
+ if entry["phones"].nil?
101
+ $stderr.print Paint[<<~WARNING, :red].chomp
102
+ → error: no phone number found for #{first_name} #{last_name}, though their contact was found
103
+ WARNING
104
+ to_delete << entry
105
+ else
106
+ tel = entry["phones"][0]["value"]
107
+ if tel.include?("+")
108
+ formatted_tel = Phony.format(Phony.normalize(tel))
109
+ phones["#{first_name}_#{last_name}"] = formatted_tel.to_s
110
+ matches_list << "#{first_name} #{last_name} - #{formatted_tel}"
111
+ else
112
+ $stderr.print Paint[<<~WARNING, :red].chomp
113
+ → error: failed to normalize #{tel} (#{first_name} #{last_name})
114
+ (please add a country code to their phone number in Contacts; US is +1)
115
+ WARNING
116
+ to_delete << entry
117
+ end
118
+ end
119
+ end
120
+
121
+ to_delete.each do |entry|
122
+ matches.delete(entry)
123
+ end
124
+
125
+ puts Paint["→ Successful matches:", :green]
126
+ puts matches_list
127
+
128
+ matches_names = []
129
+ matches.each do |match|
130
+ matches_names << {first: match["firstName"], last: match["lastName"]}
131
+ end
132
+
133
+ (names - matches_names).each do |failed|
134
+ failed_list << "#{failed[:first]} #{failed[:last]}"
135
+ end
136
+
137
+ unless failed_list.empty?
138
+ puts Paint["→ Unsuccessful matches:", :red]
139
+ puts failed_list
140
+ end
141
+
142
+ members_count = File.foreach(input_path).count
143
+ members_count += 1 if options[:self]
144
+ matches_count = matches_list.count
145
+ puts Paint["→ #{matches_count} total matches of #{members_count} members (#{(matches_count.to_f / members_count.to_f * 100).round}% success)#{" [including self]" if options[:self]}", :green]
146
+
147
+ prompt = TTY::Prompt.new
148
+
149
+ unless prompt.yes? "→ Send to successfully-matched people?"
150
+ abort Paint["Cancelled", :red, :bold]
151
+ end
152
+
153
+ sender = Imessage::Sender.new
154
+ counter = 0
155
+ bar = TTY::ProgressBar.new("sending… [:bar] :current/:total • :eta", total: phones.length, bar_format: :box, clear: true)
156
+
157
+ message = File.read(options[:message_path]).strip
158
+
159
+ phones.each do |name, phone|
160
+ sender.deliver({
161
+ text: message,
162
+ contacts: [phone]
163
+ })
164
+ counter += 1
165
+ if options[:verbose]
166
+ bar.log Paint["→ Sent to #{name.tr("_", " ")} at #{phone}", :faint]
167
+ end
168
+ bar.advance
169
+ end
170
+
171
+ puts Paint["→ Sent message to #{counter} #{counter == 1 ? "person" : "people"}", :green, :bold]
172
+ end
173
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/manymessage/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "manymessage"
7
+ spec.version = Manymessage::VERSION
8
+ spec.authors = ["jltml"]
9
+ spec.email = ["8261330+jltml@users.noreply.github.com"]
10
+
11
+ spec.summary = "Send mass texts super easily!"
12
+ spec.description = "Given a text file with a list of names, this CLI will find their phone numbers from your Contacts app and then send a message to each of them."
13
+ spec.homepage = "https://github.com/jltml/manymessage"
14
+ spec.license = "MIT"
15
+ spec.required_ruby_version = ">= 2.6.0"
16
+
17
+ spec.metadata["homepage_uri"] = spec.homepage
18
+ spec.metadata["source_code_uri"] = spec.homepage
19
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
20
+
21
+ # Specify which files should be added to the gem when it is released.
22
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
+ spec.files = Dir.chdir(__dir__) do
24
+ `git ls-files -z`.split("\x0").reject do |f|
25
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
26
+ end
27
+ end
28
+ spec.bindir = "exe"
29
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ["lib"]
31
+
32
+ # Uncomment to register a new dependency of your gem
33
+ # spec.add_dependency "example-gem", "~> 1.0"
34
+ spec.add_dependency "json", "~> 2.6"
35
+ spec.add_dependency "imessage", "~> 0.4.0"
36
+ spec.add_dependency "paint", "~> 2.2"
37
+ spec.add_dependency "ptools", "~> 1.4"
38
+ spec.add_dependency "os", "~> 1.1"
39
+ spec.add_dependency "phony", "~> 2.19"
40
+ spec.add_dependency "shellwords", "~> 0.1.0"
41
+ spec.add_dependency "tty-progressbar", "~> 0.18.2"
42
+ spec.add_dependency "tty-prompt", "~> 0.23.1"
43
+
44
+ # For more information and examples about making a new gem, check out our
45
+ # guide at: https://bundler.io/guides/creating_gem.html
46
+ end
@@ -0,0 +1,4 @@
1
+ module Manymessage
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,189 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: manymessage
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - jltml
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2022-10-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: json
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.6'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: imessage
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.4.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.4.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: paint
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.2'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: ptools
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.4'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.4'
69
+ - !ruby/object:Gem::Dependency
70
+ name: os
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.1'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.1'
83
+ - !ruby/object:Gem::Dependency
84
+ name: phony
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '2.19'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '2.19'
97
+ - !ruby/object:Gem::Dependency
98
+ name: shellwords
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 0.1.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.1.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: tty-progressbar
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 0.18.2
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 0.18.2
125
+ - !ruby/object:Gem::Dependency
126
+ name: tty-prompt
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 0.23.1
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 0.23.1
139
+ description: Given a text file with a list of names, this CLI will find their phone
140
+ numbers from your Contacts app and then send a message to each of them.
141
+ email:
142
+ - 8261330+jltml@users.noreply.github.com
143
+ executables:
144
+ - manymessage
145
+ extensions: []
146
+ extra_rdoc_files: []
147
+ files:
148
+ - ".rspec"
149
+ - ".standard.yml"
150
+ - ".tool-versions"
151
+ - CHANGELOG.md
152
+ - Gemfile
153
+ - Gemfile.lock
154
+ - LICENSE.txt
155
+ - README.md
156
+ - Rakefile
157
+ - exe/manymessage
158
+ - lib/manymessage.rb
159
+ - lib/manymessage/cli.rb
160
+ - lib/manymessage/version.rb
161
+ - manymessage.gemspec
162
+ - sig/manymessage.rbs
163
+ homepage: https://github.com/jltml/manymessage
164
+ licenses:
165
+ - MIT
166
+ metadata:
167
+ homepage_uri: https://github.com/jltml/manymessage
168
+ source_code_uri: https://github.com/jltml/manymessage
169
+ changelog_uri: https://github.com/jltml/manymessage/blob/main/CHANGELOG.md
170
+ post_install_message:
171
+ rdoc_options: []
172
+ require_paths:
173
+ - lib
174
+ required_ruby_version: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - ">="
177
+ - !ruby/object:Gem::Version
178
+ version: 2.6.0
179
+ required_rubygems_version: !ruby/object:Gem::Requirement
180
+ requirements:
181
+ - - ">="
182
+ - !ruby/object:Gem::Version
183
+ version: '0'
184
+ requirements: []
185
+ rubygems_version: 3.3.7
186
+ signing_key:
187
+ specification_version: 4
188
+ summary: Send mass texts super easily!
189
+ test_files: []