Send answers with Biju and remove machine definition from the gem
This commit is contained in:
parent
8543374046
commit
eec4e58dd9
23
README.md
23
README.md
@ -1,4 +1,4 @@
|
|||||||
# Smsd
|
# SMSd
|
||||||
|
|
||||||
TODO: Write a gem description
|
TODO: Write a gem description
|
||||||
|
|
||||||
@ -18,7 +18,26 @@ Or install it yourself as:
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
TODO: Write usage instructions here
|
```ruby
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
|
require 'smsd'
|
||||||
|
require 'net/http'
|
||||||
|
|
||||||
|
cli = SMSd::CLI.new(ARGV) do
|
||||||
|
machine = SMSd::AnsweringMachine.new(I18n.t(:default_answer))
|
||||||
|
|
||||||
|
machine.add_action(/hello/i, 'Hello !!')
|
||||||
|
machine.add_action(/what/i) do |from, to, message|
|
||||||
|
"The phone number #{from} sent '#{message}' to #{to}"
|
||||||
|
end
|
||||||
|
machine.add_action(/myip/i) do
|
||||||
|
Net::HTTP.get('icanhazip.com', '/').chomp
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
cli.run
|
||||||
|
```
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
20
examples/monitor.rb
Executable file
20
examples/monitor.rb
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
|
require 'smsd'
|
||||||
|
require 'net/http'
|
||||||
|
|
||||||
|
cli = SMSd::CLI.new(ARGV) do
|
||||||
|
machine = SMSd::AnsweringMachine.new(I18n.t(:default_answer))
|
||||||
|
|
||||||
|
machine.add_action(/ping/i, 'PONG')
|
||||||
|
machine.add_action(/free/i) do
|
||||||
|
`free`
|
||||||
|
end
|
||||||
|
machine.add_action(/myip/i) do
|
||||||
|
Net::HTTP.get('icanhazip.com', '/').chomp
|
||||||
|
end
|
||||||
|
|
||||||
|
machine
|
||||||
|
end
|
||||||
|
|
||||||
|
cli.run
|
17
examples/polite.rb
Executable file
17
examples/polite.rb
Executable file
@ -0,0 +1,17 @@
|
|||||||
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
|
require 'smsd'
|
||||||
|
|
||||||
|
cli = SMSd::CLI.new(ARGV) do
|
||||||
|
machine = SMSd::AnsweringMachine.new('I didn\'t understand your message.')
|
||||||
|
|
||||||
|
machine.add_action(/hello|hi/i, 'Ahoy !!')
|
||||||
|
machine.add_action(/what/i) do |from, to, message|
|
||||||
|
"The phone number #{from} wrote '#{message}' to #{to}"
|
||||||
|
end
|
||||||
|
|
||||||
|
machine
|
||||||
|
end
|
||||||
|
|
||||||
|
cli.run
|
||||||
|
|
13
lib/smsd.rb
13
lib/smsd.rb
@ -5,14 +5,5 @@ require 'smsd/cli'
|
|||||||
require 'smsd/cli/options'
|
require 'smsd/cli/options'
|
||||||
require 'smsd/answering_machine'
|
require 'smsd/answering_machine'
|
||||||
require 'smsd/answering_machine/action'
|
require 'smsd/answering_machine/action'
|
||||||
|
require 'smsd/util/multi_io'
|
||||||
module SMSd
|
require 'smsd/util/sms'
|
||||||
def self.init_i18n
|
|
||||||
I18n.load_path = Dir[File.join(File.dirname(__FILE__),
|
|
||||||
'..', 'locale', '*.yml')]
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.locale=(locale)
|
|
||||||
I18n.locale = locale
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
@ -8,7 +8,7 @@ module SMSd
|
|||||||
end
|
end
|
||||||
|
|
||||||
def add_action(regexp, answer = nil, &block)
|
def add_action(regexp, answer = nil, &block)
|
||||||
self.actions << Action.new(regexp, answer, &block)
|
actions << Action.new(regexp, answer, &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
def execute(from, to, message)
|
def execute(from, to, message)
|
||||||
|
@ -1,25 +1,74 @@
|
|||||||
|
require 'biju'
|
||||||
|
require 'logger'
|
||||||
|
|
||||||
module SMSd
|
module SMSd
|
||||||
class CLI
|
class CLI
|
||||||
attr_accessor :machine, :options
|
attr_accessor :machine
|
||||||
|
attr_reader :modem, :options, :logger
|
||||||
|
|
||||||
def initialize(args)
|
def initialize(args = [], &block)
|
||||||
self.options = Options.parse(args)
|
@options = Options.parse(args)
|
||||||
|
|
||||||
SMSd.init_i18n
|
self.machine = yield block if block_given?
|
||||||
SMSd.locale = options[:locale] || :fr
|
|
||||||
|
|
||||||
define_actions
|
init_logger
|
||||||
|
@modem = Biju::Hayes.new(options[:modem], pin: options[:pin])
|
||||||
puts machine.execute(ARGV[0], ARGV[1], ARGV[2])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def define_actions
|
def run
|
||||||
self.machine = AnsweringMachine.new(I18n.t(:default_answer))
|
catch_signals
|
||||||
|
Process.daemon if options[:daemonize]
|
||||||
|
|
||||||
machine.add_action(/bonjour/i, 'Bonjour !!')
|
loop do
|
||||||
machine.add_action(/quoi/i) do |from, to, message|
|
break if @terminate
|
||||||
I18n.t(:what, from: from, to: to, message: message)
|
|
||||||
end
|
modem.messages.each do |sms|
|
||||||
|
handle_message sms
|
||||||
|
end
|
||||||
|
|
||||||
|
sleep 5
|
||||||
|
end
|
||||||
|
modem.modem.close
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def init_logger
|
||||||
|
@logger = Logger.new(
|
||||||
|
Util::MultiIO.new(STDOUT, File.open('debug.log', 'a')))
|
||||||
|
|
||||||
|
logger.formatter = proc do |severity, datetime, progrname, msg|
|
||||||
|
"#{datetime} [#{severity}] #{msg}\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def catch_signals
|
||||||
|
signal_term = proc { @terminate = true }
|
||||||
|
Signal.trap('SIGTERM', signal_term)
|
||||||
|
Signal.trap('SIGINT', signal_term)
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_message(sms)
|
||||||
|
if sms.valid?
|
||||||
|
send_answer(sms)
|
||||||
|
else
|
||||||
|
logger.warn "#{sms}: #{sms.errors.join(',')}"
|
||||||
|
end
|
||||||
|
modem.delete(sms.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def send_answer(sms)
|
||||||
|
message = machine.execute(sms.phone_number, nil, sms.message)
|
||||||
|
|
||||||
|
if message.nil? || message == ''
|
||||||
|
log = 'Empty answer'
|
||||||
|
else
|
||||||
|
modem.send(Biju::Sms.new(
|
||||||
|
phone_number: sms.phone_number, message: message))
|
||||||
|
log = message
|
||||||
|
end
|
||||||
|
|
||||||
|
logger.info "#{sms}: #{log}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -7,20 +7,24 @@ module SMSd
|
|||||||
options = {}
|
options = {}
|
||||||
|
|
||||||
parser = ::OptionParser.new do |opts|
|
parser = ::OptionParser.new do |opts|
|
||||||
opts.banner = "Usage: smsd [options]"
|
opts.banner = 'Usage: smsd [options] MODEM'
|
||||||
|
|
||||||
opts.separator ""
|
opts.separator ''
|
||||||
opts.separator "Specific options:"
|
opts.separator 'Specific options:'
|
||||||
|
|
||||||
opts.on('-l', '--locale LOCALE',
|
opts.on('-d', '--[no-]daemonize',
|
||||||
'Define the language of the script') do |locale|
|
'Run in the background') do |daemon|
|
||||||
options[:locale] = locale.to_sym
|
options[:daemonize] = daemon
|
||||||
end
|
end
|
||||||
|
|
||||||
opts.separator ""
|
opts.on('-p', '--pin PIN', 'Specify the SIM PIN') do |pin|
|
||||||
opts.separator "Common options:"
|
options[:pin] = pin
|
||||||
|
end
|
||||||
|
|
||||||
opts.on('-h', '--help', 'Show this message') do
|
opts.separator ''
|
||||||
|
opts.separator 'Common options:'
|
||||||
|
|
||||||
|
opts.on_tail('-h', '--help', 'Show this message') do
|
||||||
puts opts
|
puts opts
|
||||||
exit
|
exit
|
||||||
end
|
end
|
||||||
@ -31,7 +35,18 @@ module SMSd
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
parser.parse!(args)
|
parser.parse!(args)
|
||||||
|
|
||||||
|
options[:modem] = args.first
|
||||||
|
raise OptionParser::MissingArgument,
|
||||||
|
'modem not specified' if options[:modem].nil?
|
||||||
|
rescue OptionParser::MissingArgument, OptionParser::InvalidOption => e
|
||||||
|
puts e.message
|
||||||
|
puts parser
|
||||||
|
exit
|
||||||
|
end
|
||||||
|
|
||||||
options
|
options
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
15
lib/smsd/util/multi_io.rb
Normal file
15
lib/smsd/util/multi_io.rb
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
module SMSd::Util
|
||||||
|
class MultiIO
|
||||||
|
def initialize(*targets)
|
||||||
|
@targets = targets
|
||||||
|
end
|
||||||
|
|
||||||
|
def write(*args)
|
||||||
|
@targets.each { |t| t.write(*args) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def close
|
||||||
|
@targets.each(&:close)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
12
lib/smsd/util/sms.rb
Normal file
12
lib/smsd/util/sms.rb
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
class Biju::Sms
|
||||||
|
attr_reader :errors
|
||||||
|
|
||||||
|
def valid?
|
||||||
|
@errors = []
|
||||||
|
|
||||||
|
@errors << 'Message too old' if datetime.to_time < Time.now - (5 * 60)
|
||||||
|
@errors << 'Phone number too short' if phone_number.length < 6
|
||||||
|
|
||||||
|
@errors.empty?
|
||||||
|
end
|
||||||
|
end
|
@ -1,3 +1,3 @@
|
|||||||
module SMSd
|
module SMSd
|
||||||
VERSION = "0.0.1"
|
VERSION = '0.0.1'
|
||||||
end
|
end
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
en:
|
|
||||||
default_answer: "I didn't understand your message"
|
|
||||||
what: 'The phone number %{from} wrote "%{message} to %{to}'
|
|
@ -1,3 +0,0 @@
|
|||||||
fr:
|
|
||||||
default_answer: "Je n'ai pas compris votre message"
|
|
||||||
what: 'Le numéro %{from} a écrit "%{message}" au numéro %{to}'
|
|
@ -18,6 +18,7 @@ Gem::Specification.new do |spec|
|
|||||||
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
||||||
spec.require_paths = ["lib"]
|
spec.require_paths = ["lib"]
|
||||||
|
|
||||||
|
spec.add_dependency 'biju'
|
||||||
spec.add_dependency 'i18n'
|
spec.add_dependency 'i18n'
|
||||||
|
|
||||||
spec.add_development_dependency "bundler", "~> 1.3"
|
spec.add_development_dependency "bundler", "~> 1.3"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user