#!/usr/bin/env ruby require 'motion_vj' require 'fileutils' require 'optparse' require 'yaml' class App attr_accessor :options, :config def initialize(argv) parse!(argv) load_config! start end private def parse!(argv) self.options = {} opt_parser = OptionParser.new do |opts| opts.banner = 'Usage: motionvj [options]' opts.separator 'Required:' opts.on('-c', '--config-file [CONFIG_YAML_FILE]', 'Path to the configuration YAML file') do |config_filepath| self.options[:config_filepath] = config_filepath end opts.separator 'Optional:' opts.on('-t', '--get-token', 'Get the Dropbox token') do self.options[:get_token] = true end opts.separator 'Common:' opts.on_tail('-h', '--help', 'Show this message') do puts opts exit end opts.on_tail('-v', '--version', 'Show version') do puts MotionVj::VERSION exit end end begin opt_parser.parse!(argv) rescue OptionParser::InvalidOption => e $stderr.puts 'Invalid option.' abort opt_parser.to_s end if self.options[:config_filepath].nil? || self.options[:config_filepath].to_s.strip.empty? $stderr.puts 'The configuration YAML file is required.' abort opt_parser.to_s end end def load_config! self.config = YAML.load_file(self.options[:config_filepath]) blank_config_msg = %w( db_videos_dir motion_cmd pid_file videos_dir videos_extension ).map { |key| key if /\A[[:space:]]*\z/ === self.config[key].to_s }.compact abort "The following configuration options are missing:\n#{ blank_config_msg.join("\n") }" unless blank_config_msg.empty? rescue Errno::ENOENT abort "Could not open the configuration file: #{ self.options[:config_filepath] }" end def start trap('INT') do remove_pid_file exit 2 end create_pid_file if options[:get_token] MotionVj.get_dropbox_token(self.config['db_app_key'], self.config['db_app_secret']) else MotionVj.start(db_app_token: self.config['db_app_token'], videos_dir: self.config['videos_dir'], videos_extension: self.config['videos_extension'], motion_cmd: self.config['motion_cmd'], db_videos_dir: self.config['db_videos_dir']) sleep end ensure remove_pid_file end def read_pid pid = nil if File.exist?(self.config['pid_file']) File.open(self.config['pid_file'], 'r') do |f| pid = f.gets.to_i rescue nil end end pid end def create_pid_file pid = read_pid if pid && !pid.zero? pid_exist = !!Process.kill(0, pid) rescue false abort "motionvj is already running. Please check the PID in '#{ self.config['pid_file'] }'." if pid_exist end File.open(self.config['pid_file'], 'w') do |f| f.puts Process.pid end end def remove_pid_file pid = read_pid FileUtils.rm_f(self.config['pid_file']) if pid && pid === Process.pid end end App.new(ARGV)