motion_vj 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- OWUwMzVjNGM0YWFjMzEwNmMxMGJmMGZmOTlkMjA0MDVhMzBkNWFmMw==
4
+ NmUzNGIxZDY1ZjAwMDI4YTU5OTM2YWExMmFiZDAyODdmNGNkZDc0Mg==
5
5
  data.tar.gz: !binary |-
6
- MTgwODhmYzliNjRiNTM2MjBkNzdjZWQxODFiZDZkZTdkMGJjNTM3ZQ==
6
+ NTE5ZDViYTQ1ZGVjYjRkMDhiNGI0ZjUzYmNlMDg2YTY0ZWVjMjk0YQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MjJlMTEyM2I1MjM3NGYwODU3NTY5OGJmMTA2NjdlZjlhOTEwYmZmZjAzN2Q4
10
- YTcwZjczZGIzMzI0N2FiMmNiOGFhMjlkZjQ3MDMyZTc1OTI5Y2VmYzlkNGY1
11
- NDdiODljZjg5NmJjZGJjYzcwMWE4MTc0YmUxY2I1YTEwZmFkZWU=
9
+ MDA2NDQzMzFhMTQ3ODNjZTFkYTEyMGM5NWRlYjE2ZGE1MWY2NjI1NjU4MWQz
10
+ NmU1NjFkNGJjZTZkOWExOWE5Y2QxYWFlNjczNjgxZGIwMzIxYmQ2MGIwMGQ4
11
+ N2E1MTk1YjljYWQ1ZGIxNTQwYzdiNTE5ZmFiN2UyNjM5ZTFkMTA=
12
12
  data.tar.gz: !binary |-
13
- ZTQ0NWJiOGFkZGYxOThlNjQ3YTk0NGRkM2E5MTdhZGJjM2VjNTFhZWZlZjJm
14
- Mjg4Y2VjNjc0MjNlMzJlYmI3OTI5MWEzNjc2MTdkMGFlN2QwNGNjMjU3ZjIz
15
- YmY4MTQ3ODY4N2NlMGIzNDk5YWFhNWQ0ODUwNjE3NDdhODNmYzU=
13
+ NjU3Y2FlYjAzOTFjOGNiMjIyMzQ3N2FjNmJmM2U3MDQ1MmQ2NjJjM2M1NDAy
14
+ MjI2NmU3Y2Y3OTFlMzNkMjA4ODExYmY4OTk1ZTg4NWMwYTI4M2Y5NzljMWJh
15
+ M2U3ZTg0YmQzYWM3ODA1ODhiMWE0YzJkYmIzNDIwYzE4NWU1OTM=
data/README.md CHANGED
@@ -8,11 +8,40 @@ Install the gem and make the executable available:
8
8
 
9
9
  $ gem install motion_vj
10
10
 
11
+ ## Configuration
12
+
13
+ The configuration file should look like this:
14
+
15
+ ```yaml
16
+ # config.yml
17
+
18
+ # To obtain the app key and secret, go to https://www.dropbox.com/developers/apps/create
19
+ db_app_key: <App key from Dropbox>
20
+ db_app_secret: <App secret from Dropbox>
21
+ # The token can be generated using `--get-token`. Please see the Usage section of the README.
22
+ db_app_token: <App token from Dropbox>
23
+ # The Dropbox directory where the files will be uploaded.
24
+ db_videos_dir: /
25
+
26
+ # The motion CLI name.
27
+ motion_cmd: motion
28
+ # Path to the PID file that will be created when running.
29
+ pid_file: /var/run/motion/motion.pid
30
+ # Directory where motion save the videos.
31
+ videos_dir: /var/run/motion/videos
32
+ # Extension of the videos that should be uploaded.
33
+ videos_extension: avi
34
+ ```
35
+
36
+ You must provide it using the `--config-file` option as pointed by the [Usage](#usage) section.
37
+
11
38
  ## Usage
12
39
 
13
- Once installed, a Dropbox token is needed to start. Run `motionvj --get-token` and follow the instructions.
40
+ So that `motionvj` can access a Dropbox account, a Dropbox token needs to be created. This will be a one time action, and it can be acomplished running `motionvj --get-token --config-file config.yml`, where `config.yml` is the file detailed by the [Configuration](#configuration) section of this README. Once the token is created, it should be added to the same configuration file.
41
+
42
+ To start uploading new videos, just run `motionvj --config-file config.yml`. This should upload new videos that end with the extension indicated by the configuration file. After a file is uploaded to Dropbox, it is then deleted from the local filesystem.
14
43
 
15
- For more details, run `motionvj --help`:
44
+ For more options, run `motionvj --help`:
16
45
 
17
46
  ```
18
47
  Usage: motionvj [options]
@@ -2,26 +2,36 @@
2
2
 
3
3
  require 'motion_vj'
4
4
 
5
- require 'dotenv'
6
5
  require 'fileutils'
7
6
  require 'optparse'
7
+ require 'yaml'
8
8
 
9
9
  class App
10
- def self.parse!(argv)
11
- options = {}
10
+ attr_accessor :options, :config
11
+
12
+ def initialize(argv)
13
+ parse!(argv)
14
+ load_config!
15
+ start
16
+ end
17
+
18
+ private
19
+
20
+ def parse!(argv)
21
+ self.options = {}
12
22
  opt_parser = OptionParser.new do |opts|
13
23
  opts.banner = 'Usage: motionvj [options]'
14
24
 
15
25
  opts.separator 'Required:'
16
26
 
17
- opts.on('-c', '--config-file [CONFIG_FILE]', 'Path to the configuration file') do |config_filepath|
18
- options[:config_filepath] = config_filepath
27
+ opts.on('-c', '--config-file [CONFIG_YAML_FILE]', 'Path to the configuration YAML file') do |config_filepath|
28
+ self.options[:config_filepath] = config_filepath
19
29
  end
20
30
 
21
31
  opts.separator 'Optional:'
22
32
 
23
33
  opts.on('-t', '--get-token', 'Get the Dropbox token') do
24
- options[:get_token] = true
34
+ self.options[:get_token] = true
25
35
  end
26
36
 
27
37
  opts.separator 'Common:'
@@ -44,72 +54,70 @@ class App
44
54
  abort opt_parser.to_s
45
55
  end
46
56
 
47
- if options[:config_filepath].nil? || options[:config_filepath].to_s.strip.empty?
48
- $stderr.puts 'The configuration file is required.'
57
+ if self.options[:config_filepath].nil? || self.options[:config_filepath].to_s.strip.empty?
58
+ $stderr.puts 'The configuration YAML file is required.'
49
59
  abort opt_parser.to_s
50
60
  end
51
-
52
- options
53
61
  end
54
62
 
55
- def self.start(options)
56
- Dotenv.load(options[:config_filepath])
57
- self.check_config
63
+ def load_config!
64
+ self.config = YAML.load_file(self.options[:config_filepath])
65
+ blank_config_msg = %w( db_videos_dir motion_cmd pid_file videos_dir videos_extension ).map { |key|
66
+ key if /\A[[:space:]]*\z/ === self.config[key].to_s
67
+ }.compact
68
+ abort "The following configuration options are missing:\n#{ blank_config_msg.join("\n") }" unless blank_config_msg.empty?
69
+ rescue Errno::ENOENT
70
+ abort "Could not open the configuration file: #{ self.options[:config_filepath] }"
71
+ end
58
72
 
73
+ def start
59
74
  trap('INT') do
60
- self.remove_pid_file
75
+ remove_pid_file
61
76
  exit 2
62
77
  end
63
78
 
64
- self.create_pid_file
79
+ create_pid_file
65
80
 
66
81
  if options[:get_token]
67
- MotionVj.get_dropbox_token(self.get_env('DP_APP_KEY'), self.get_env('DP_APP_SECRET'))
82
+ MotionVj.get_dropbox_token(self.config['db_app_key'], self.config['db_app_secret'])
68
83
  else
69
- MotionVj.start(get_env('DP_APP_TOKEN'))
84
+ MotionVj.start(db_app_token: self.config['db_app_token'],
85
+ videos_dir: self.config['videos_dir'],
86
+ videos_extension: self.config['videos_extension'],
87
+ motion_cmd: self.config['motion_cmd'],
88
+ db_videos_dir: self.config['db_videos_dir'])
70
89
  sleep
71
90
  end
91
+ ensure
92
+ remove_pid_file
72
93
  end
73
94
 
74
- private
75
-
76
- def self.check_config
77
- %w( MOTION_CMD VIDEOS_DIR VIDEO_EXTENTION PID_FILE DB_VIDEOS_DIR ).each { |key| self.get_env(key) }
78
- end
79
-
80
- def self.get_env(key)
81
- value = ENV[key]
82
- abort "The environment variable '#{key}' is blank or defined." if value.to_s.strip.empty?
83
- value
84
- end
85
-
86
- def self.read_pid
95
+ def read_pid
87
96
  pid = nil
88
- if File.exist?(ENV['PID_FILE'])
89
- File.open(ENV['PID_FILE'], 'r') do |f|
97
+ if File.exist?(self.config['pid_file'])
98
+ File.open(self.config['pid_file'], 'r') do |f|
90
99
  pid = f.gets.to_i rescue nil
91
100
  end
92
101
  end
93
102
  pid
94
103
  end
95
104
 
96
- def self.create_pid_file
97
- pid = self.read_pid
105
+ def create_pid_file
106
+ pid = read_pid
98
107
  if pid && !pid.zero?
99
108
  pid_exist = !!Process.kill(0, pid) rescue false
100
- abort "motionvj is already running. Please check the PID in '#{ENV['PID_FILE']}'." if pid_exist
109
+ abort "motionvj is already running. Please check the PID in '#{ self.config['pid_file'] }'." if pid_exist
101
110
  end
102
111
 
103
- File.open(ENV['PID_FILE'], 'w') do |f|
112
+ File.open(self.config['pid_file'], 'w') do |f|
104
113
  f.puts Process.pid
105
114
  end
106
115
  end
107
116
 
108
- def self.remove_pid_file
109
- pid = self.read_pid
110
- FileUtils.rm_f(ENV['PID_FILE']) if pid && pid === Process.pid
117
+ def remove_pid_file
118
+ pid = read_pid
119
+ FileUtils.rm_f(self.config['pid_file']) if pid && pid === Process.pid
111
120
  end
112
121
  end
113
122
 
114
- options = App.parse!(ARGV)
115
- App.start(options)
123
+ App.new(ARGV)
@@ -9,20 +9,20 @@ require 'listen'
9
9
  module MotionVj
10
10
  def self.get_dropbox_token(app_key, app_secret)
11
11
  token = MotionVj::Client.get_token(app_key, app_secret)
12
- puts "Your Dropbox access token for this app is: #{token}"
12
+ puts "Your Dropbox access token for this app is: #{ token }"
13
13
  end
14
14
 
15
- def self.start(token)
16
- listener = Listen.to(ENV['VIDEOS_DIR'], only: /\.#{Regexp.escape ENV['VIDEO_EXTENTION']}$/) do |modified_filepaths, _, removed_filepaths|
15
+ def self.start(options)
16
+ listener = Listen.to(options[:videos_dir], only: /\.#{ Regexp.escape options[:videos_extension] }$/) do |modified_filepaths, _, removed_filepaths|
17
17
  # handle addded files
18
18
  unless modified_filepaths.empty?
19
- client = MotionVj::Client.new(token)
20
- motion_lsof = `lsof -c #{ENV['MOTION_CMD']}`
19
+ client = MotionVj::Client.new(options[:db_app_token], options[:db_videos_dir])
20
+ motion_lsof = `lsof -c #{ options[:motion_cmd] }`
21
21
 
22
22
  modified_filepaths.each do |filepath|
23
23
  file_basename = File.basename filepath
24
24
 
25
- if motion_lsof =~ /#{Regexp.escape file_basename}/
25
+ if motion_lsof =~ /#{ Regexp.escape(file_basename) }/
26
26
  Logger.error "Added file still in use."
27
27
  next
28
28
  end
@@ -32,12 +32,12 @@ module MotionVj
32
32
  begin
33
33
  if client.upload(filepath)
34
34
  FileUtils.rm_f(filepath)
35
- Logger.info "'#{file_basename}' was uploaded."
35
+ Logger.info "'#{ file_basename }' was uploaded."
36
36
  else
37
- Logger.error "Could not upload '#{file_basename}'."
37
+ Logger.error "Could not upload '#{ file_basename }'."
38
38
  end
39
39
  rescue => e
40
- Logger.error "Could not upload '#{file_basename}'."
40
+ Logger.error "Could not upload '#{ file_basename }'."
41
41
  end
42
42
  end
43
43
  end
@@ -45,7 +45,7 @@ module MotionVj
45
45
 
46
46
  # handle removed files
47
47
  removed_filepaths.each do |filepath|
48
- Logger.info "'#{File.basename(filepath)}' deleted."
48
+ Logger.info "'#{ File.basename(filepath) }' deleted."
49
49
  end
50
50
  end
51
51
  listener.start
@@ -2,15 +2,16 @@ require 'dropbox_sdk'
2
2
 
3
3
  module MotionVj
4
4
  class Client
5
- attr_reader :db_client
5
+ attr_reader :db_client, :videos_dir
6
6
 
7
- def initialize(token)
7
+ def initialize(token, videos_dir)
8
8
  @db_client = DropboxClient.new(token)
9
+ @videos_dir = videos_dir
9
10
  end
10
11
 
11
12
  def file_exist?(filename)
12
13
  begin
13
- metadata = db_client.metadata(File.join(ENV['DB_VIDEOS_DIR'], filename))
14
+ metadata = self.db_client.metadata(File.join(self.videos_dir, filename))
14
15
  metadata && !metadata['is_dir'] && metadata['bytes'] && metadata['bytes'] > 0
15
16
  rescue DropboxError => e
16
17
  false
@@ -19,7 +20,7 @@ module MotionVj
19
20
 
20
21
  def upload(filepath)
21
22
  open(filepath) do |file|
22
- metadata = db_client.put_file(File.join(ENV['DB_VIDEOS_DIR'], File.basename(filepath)), file, true)
23
+ metadata = self.db_client.put_file(File.join(self.videos_dir, File.basename(filepath)), file, true)
23
24
  metadata && !metadata['is_dir'] && metadata['bytes'] && metadata['bytes'] > 0
24
25
  end
25
26
  end
@@ -28,7 +29,7 @@ module MotionVj
28
29
  flow = DropboxOAuth2FlowNoRedirect.new(app_key, app_secret)
29
30
  authorize_url = flow.start
30
31
 
31
- puts "1. Go to: #{authorize_url}"
32
+ puts "1. Go to: #{ authorize_url }"
32
33
  puts '2. Click "Allow" (you might have to log in first)'
33
34
  puts '3. Copy the authorization code'
34
35
  print 'Enter the authorization code here: '
@@ -5,7 +5,7 @@ module MotionVj
5
5
  loop do
6
6
  value = $stdin.gets.to_s.strip
7
7
  if value.empty?
8
- print("Please provide a valid #{input_name}:")
8
+ print("Please provide a valid #{ input_name }: ")
9
9
  else
10
10
  return value
11
11
  end
@@ -11,7 +11,7 @@ module MotionVj
11
11
  private
12
12
 
13
13
  def self.format(msg, type)
14
- "[motionvj][#{Time.now.utc.strftime("%Y-%m-%d %H:%M:%S %Z")}][#{type}]: #{msg}"
14
+ "[motionvj][#{ Time.now.utc.strftime("%Y-%m-%d %H:%M:%S %Z") }][#{ type }]: #{ msg }"
15
15
  end
16
16
  end
17
17
  end
@@ -1,3 +1,3 @@
1
1
  module MotionVj
2
- VERSION = "0.1.0"
2
+ VERSION = '0.2.0'
3
3
  end
@@ -19,7 +19,6 @@ Gem::Specification.new do |spec|
19
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
20
  spec.require_paths = ["lib"]
21
21
 
22
- spec.add_dependency 'dotenv', "~> 2.0"
23
22
  spec.add_dependency 'dropbox-sdk', "~> 1.6"
24
23
  spec.add_dependency 'listen', "~> 3.0"
25
24
 
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: motion_vj
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roque Pinel
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-01-29 00:00:00.000000000 Z
11
+ date: 2016-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: dotenv
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ~>
18
- - !ruby/object:Gem::Version
19
- version: '2.0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ~>
25
- - !ruby/object:Gem::Version
26
- version: '2.0'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: dropbox-sdk
29
15
  requirement: !ruby/object:Gem::Requirement