lmk 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Luke Winikates
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.
@@ -0,0 +1,31 @@
1
+ [![Code Climate](https://codeclimate.com/github/LukeWinikates/lmk.png)](https://codeclimate.com/github/LukeWinikates/lmk)
2
+ [![Build Status](https://travis-ci.org/LukeWinikates/lmk.png?branch=master)](https://travis-ci.org/LukeWinikates/lmk)
3
+ LMK
4
+ ===========
5
+
6
+ Don't sit around waiting for rake/make/tests/etc to finish. Let the machine tell you when it's done.
7
+
8
+ ## PREREQUISITES:
9
+ You need a twilio account, including API Key and Account SID for sending [SMSes](http://www.twilio.com/sms).
10
+
11
+ ## USAGE:
12
+ `$ lmk exec [command]`
13
+
14
+ executes [command], sending a digest of the result as an SMS to the specified phone number and creating a private, anonymous gist with the full command output.
15
+
16
+ For example:
17
+ `$ lmk exec bundle install`
18
+
19
+ ## INSTALLATION/CONFIGURATION:
20
+ LMK requires a ~/.lmkrc file in order to run. The .lmkrc is a simple YAML file with four required values:
21
+ - phone_number: The number at which you want to receive a message when the command has finished running.
22
+ - from: a number associated with your Twilio account & set up for SMS sending
23
+ - account_sid: from your Twilio Account
24
+ - auth_token: from your Twilio Account
25
+
26
+ You can validate your .lmkrc at any time by running LMK's `config` command:
27
+
28
+ `$ lmk config`
29
+
30
+ ## LICENSE:
31
+ MIT Licensed. See LICENSE file.
data/bin/lmk ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
3
+ $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
4
+ require 'lmk'
5
+ require 'thor'
6
+
7
+ LMK::CLI.start
@@ -0,0 +1,8 @@
1
+ require 'lmk/config'
2
+ require 'lmk/version'
3
+ require 'lmk/twilio_client_wrapper'
4
+ require 'lmk/twilio_sender'
5
+ require 'lmk/shell_command'
6
+ require 'lmk/runner'
7
+ require 'lmk/gist_sender'
8
+ require 'lmk/cli'
@@ -0,0 +1,28 @@
1
+ require 'thor'
2
+
3
+ module LMK
4
+ class CLI < ::Thor
5
+ desc "exec COMMAND", "run a command and get an SMS with its result"
6
+ def exec(*command)
7
+ command = command.join ' '
8
+ Runner.run(command, options)
9
+ end
10
+
11
+ desc "config", "read the current twilio config file"
12
+ def config
13
+ Kernel.puts Config.from_file.debug
14
+ end
15
+
16
+ desc "debug COMMAND", "view template output for the given command"
17
+ def debug(*command)
18
+ command = command.join ' '
19
+ cmd = ShellCommand.new(command).tap do |c|
20
+ c.html_url = "http://gist.example.com"
21
+ end
22
+ puts "concise"
23
+ puts cmd.concise_output
24
+ puts "\n\nfull"
25
+ puts cmd.full_output
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,52 @@
1
+ require 'yaml'
2
+ require 'hashie'
3
+
4
+ module LMK
5
+ class Config
6
+ def self.default_path
7
+ "#{ENV['HOME']}/.lmkrc"
8
+ end
9
+
10
+ def self.from_file(path = default_path)
11
+ attrs = ::YAML.load_file(path) if File.exists?(path)
12
+ new(attrs, path)
13
+ end
14
+
15
+ def initialize(attributes, file = nil)
16
+ (attributes || {}).each do |k, v|
17
+ setter = "#{k}=".to_sym
18
+ send(setter, v) if respond_to?(setter)
19
+ end
20
+ @file = file
21
+ end
22
+
23
+ def valid?
24
+ required_attributes.map { |attr| send(attr) }.all?
25
+ end
26
+
27
+ def required_attributes
28
+ [:auth_token, :from, :phone_number, :account_sid]
29
+ end
30
+
31
+ def missing_values
32
+ required_attributes.select { |method| send(method).nil? }
33
+ end
34
+
35
+ def debug
36
+ <<-RESULT
37
+ LMK Configuration #{valid? ? 'valid' : 'invalid'}
38
+ #{'Config file missing, create ' + @file + ' with required values.' if @file && !File.exists?(@file) }
39
+ missing values: #{valid? ? 'none' : missing_values }
40
+ #{raw}
41
+ RESULT
42
+ end
43
+
44
+ def raw
45
+ instance_variables.map do |ivar|
46
+ "#{ivar.to_s.gsub("@", "")}: #{instance_variable_get ivar}"
47
+ end.join "\n"
48
+ end
49
+
50
+ attr_accessor :auth_token, :from, :phone_number, :account_sid
51
+ end
52
+ end
@@ -0,0 +1,27 @@
1
+ require 'octokit'
2
+
3
+ module LMK
4
+ class GistSender
5
+ def send(commmand)
6
+ result = client.create_gist options(commmand)
7
+ commmand.html_url = result[:html_url]
8
+ commmand
9
+ end
10
+
11
+ def options(command)
12
+ {
13
+ :description => command.command,
14
+ :public => false,
15
+ :files => {
16
+ "#{command.timestamp.strftime '%FT%R'}.lmk" => {
17
+ :content => command.full_output
18
+ }
19
+ }
20
+ }
21
+ end
22
+
23
+ def client
24
+ Octokit::Client.new
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,64 @@
1
+ module LMK
2
+ class Runner
3
+ class Configuration
4
+ attr_accessor :sms_service, :gist_service, :console_service, :shell_service
5
+
6
+ def initialize
7
+ @sms_service = LMK::TwilioSender.new
8
+ @gist_service = LMK::GistSender.new
9
+ @console_service = Kernel
10
+ @shell_service = LMK::ShellCommand
11
+ end
12
+ end
13
+
14
+ def self.configure
15
+ yield self.configuration
16
+ end
17
+
18
+ def self.configuration
19
+ @@default_configuration ||= Configuration.new
20
+ end
21
+
22
+ def self.run(command, options)
23
+ new.run(command, options)
24
+ end
25
+
26
+ def initialize(configuration = Runner.configuration)
27
+ @configuration = configuration
28
+ end
29
+
30
+ def console(message)
31
+ @configuration.console_service.puts(message)
32
+ end
33
+
34
+ def shell(command)
35
+ @configuration.shell_service.exec(command)
36
+ end
37
+
38
+ def sms(command)
39
+ @configuration.sms_service.send(command)
40
+ end
41
+
42
+ def post_to_web(command)
43
+ @configuration.gist_service.send(command)
44
+ end
45
+
46
+ def run(command, options)
47
+ return unless validate!
48
+ console("running command `#{command}`")
49
+ result = shell(command)
50
+ result = post_to_web(result)
51
+ result = sms(result)
52
+ console(result.output)
53
+ end
54
+
55
+ def validate!
56
+ unless @configuration.sms_service.runnable?
57
+ console("Configuration invalid. Run `lmk config` for more info")
58
+ false
59
+ else
60
+ true
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,70 @@
1
+ require 'popen4'
2
+ require 'erb'
3
+
4
+ module LMK
5
+ class ShellCommand
6
+ attr_reader :command, :timestamp
7
+ attr_accessor :html_url
8
+
9
+ def initialize(command)
10
+ @timestamp = Time.now
11
+ @command = command
12
+ @status = ::POpen4.popen4(command) do |stdout, stderr, stdin, pid|
13
+ @error = stderr.read
14
+ @output = stdout.read
15
+ end
16
+ end
17
+
18
+ def get_binding
19
+ binding
20
+ end
21
+
22
+ def self.exec(command)
23
+ new(command)
24
+ end
25
+
26
+ def success?
27
+ status == 0
28
+ end
29
+
30
+ def status
31
+ @status.exitstatus
32
+ end
33
+
34
+ def output
35
+ if success?
36
+ @output
37
+ else
38
+ @error
39
+ end
40
+ end
41
+
42
+ def concise_output
43
+ concise_template.result get_binding
44
+ end
45
+
46
+ def full_output
47
+ full_template.result get_binding
48
+ end
49
+
50
+ def full_template
51
+ ERB.new %q{
52
+ %%% LMK Command Result: %%%
53
+ > <%= command %>
54
+ <% if success? %>succeeded
55
+ <% else %> failed (<%=status%>)<% end %>
56
+ full output:
57
+ ----------------------------
58
+ <%=output%>
59
+ }
60
+ end
61
+
62
+ def concise_template
63
+ ERB.new %q{LMK Command Result:
64
+ > <%=command%>
65
+ <% if success? %>succeeded
66
+ <% else %>failed (<%=status%>)<% end %>
67
+ <% if html_url %>full result @ <%= html_url %><% end %>}
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,26 @@
1
+ require 'twilio-ruby'
2
+
3
+ module LMK
4
+ class TwilioClientWrapper
5
+ def initialize(config = Config.from_file)
6
+ @config = config
7
+ @client = ::Twilio::REST::Client.new(@config.account_sid, @config.auth_token) if runnable?
8
+ end
9
+
10
+ def runnable?
11
+ @config.valid?
12
+ end
13
+
14
+ def send(message)
15
+ @client.account.sms.messages.create options.merge(:body => message)
16
+ end
17
+
18
+ private
19
+ def options
20
+ {
21
+ :from => @config.from,
22
+ :to => @config.phone_number
23
+ }
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,16 @@
1
+ module LMK
2
+ class TwilioSender
3
+ def initialize(client = TwilioClientWrapper.new)
4
+ @client = client
5
+ end
6
+
7
+ def runnable?
8
+ !!@client && @client.runnable?
9
+ end
10
+
11
+ def send(command)
12
+ @client.send command.concise_output
13
+ command
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,3 @@
1
+ module LMK
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,15 @@
1
+ lib = File.expand_path('../lib/', __FILE__)
2
+ $:.unshift lib unless $:.include?(lib)
3
+
4
+ require 'lmk/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'lmk'
8
+ s.summary = 'runs a command and sends the output via sms'
9
+ s.authors = ["Luke Winikates"]
10
+ s.version = LMK::VERSION
11
+ s.executables << 'lmk'
12
+ s.files = %w(LICENSE README.md lmk.gemspec)
13
+ s.files += Dir.glob("bin/**/*")
14
+ s.files += Dir.glob("lib/**/*.rb")
15
+ end
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lmk
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Luke Winikates
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-05-06 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description:
15
+ email:
16
+ executables:
17
+ - lmk
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - LICENSE
22
+ - README.md
23
+ - lmk.gemspec
24
+ - bin/lmk
25
+ - lib/lmk/cli.rb
26
+ - lib/lmk/config.rb
27
+ - lib/lmk/gist_sender.rb
28
+ - lib/lmk/runner.rb
29
+ - lib/lmk/shell_command.rb
30
+ - lib/lmk/twilio_client_wrapper.rb
31
+ - lib/lmk/twilio_sender.rb
32
+ - lib/lmk/version.rb
33
+ - lib/lmk.rb
34
+ homepage:
35
+ licenses: []
36
+ post_install_message:
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ requirements: []
53
+ rubyforge_project:
54
+ rubygems_version: 1.8.16
55
+ signing_key:
56
+ specification_version: 3
57
+ summary: runs a command and sends the output via sms
58
+ test_files: []
59
+ has_rdoc: