captured 0.2.3 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,10 +10,10 @@ While I would love to tinker with this to make it easy to install (it is really
10
10
 
11
11
  So, I am making some assumptions about the environment that captured runs in. In particular it expects:
12
12
 
13
- * A decent understanding of scp and ssh
13
+ * A decent understanding of installing ruby gems
14
14
  * That [Growl](http://growl.info/) (and the [growlnotify](http://growl.info/documentation/growlnotify.php) command-line tool) are installed
15
15
 
16
- With that said, once things are installed and configured it really is handy.
16
+ With that said, once things are installed and configured it really is handy.
17
17
 
18
18
  Install
19
19
  =======
@@ -28,7 +28,19 @@ Then you will need to exit that config file with the appropriate settings for yo
28
28
 
29
29
  When you install it will copy an example config file to ~/.captured.yml, which has a few examples of possible configuration types.
30
30
 
31
- The simplest of this is to the scp type:
31
+ Install Type: Imageshack
32
+ ------------------------
33
+ The easiest way to do this is to use the image shack service. This service is a little slower, but is free and easy.
34
+
35
+ <pre>
36
+ upload:
37
+ type: scp
38
+ </pre>
39
+
40
+ Install Type: scp
41
+ -----------------
42
+
43
+ If you have you own web server scp is a very handy way to host your own captures.
32
44
 
33
45
  * user - optional if your remote user is the same as your local user
34
46
  * password - optional if you have setup key pair authentication
@@ -46,14 +58,11 @@ The simplest of this is to the scp type:
46
58
  url: "http://example.com/captured/"
47
59
  </pre>
48
60
 
49
-
50
-
51
61
  Icons
52
62
  =====
53
63
 
54
64
  Icons from the [Crystal Clear](http://www.everaldo.com/crystal/) icon set by [Everaldo Coelho](http://en.wikipedia.org/wiki/Everaldo_Coelho). – The icons are [licensed](http://www.everaldo.com/crystal/?action=license) under the [GNU Lesser General Public License (LGPL)](http://en.wikipedia.org/wiki/GNU_Lesser_General_Public_License).
55
65
 
56
-
57
66
  Copyright
58
67
  =========
59
68
 
@@ -1,11 +1,40 @@
1
1
  # Example captured configuration file
2
2
  #
3
- # Eval
4
- # ====
3
+ # Standard upload type: Image Shack
4
+ # =================================
5
5
  #
6
- # Complete control for the complete nerd. This allows you to execute arbtrary
7
- # ruby code when a matching file is found. Normally this would be used to
8
- # invoke a command line upload (such as scp, curl, etc).
6
+ # The default option is to post your images to imageshack.us, if you want to
7
+ # use one of the more advances and felxable types simply comment this out.
8
+
9
+ upload:
10
+ type: imageshack
11
+
12
+ #
13
+ # Powerful upload type: scp
14
+ # =========================
15
+ #
16
+ # Standard scp, using the ruby net/ssh library.
17
+ #
18
+ # * user - optinal if your remote user is the same as your local user
19
+ # * password - optional if you have setup key pair authentication
20
+ # * host - the remote host name
21
+ # * url - the public url to the remote host+path
22
+ # * path - the remote path to upload to
23
+
24
+ #upload:
25
+ # type: scp
26
+ # user: user
27
+ # host: example.com
28
+ # path: example.com/captured/
29
+ # url: "http://example.com/captured/"
30
+
31
+ #
32
+ # Advanced upload type: Eval
33
+ # ==========================
34
+ #
35
+ # Complete control for the complete nerd. This allows you to execute arbtrary
36
+ # ruby code when a matching file is found. Normally this would be used to
37
+ # invoke a command line upload (such as scp, curl, etc).
9
38
  #
10
39
  # One advantage with calling scp this way is it will be aware of all the custom
11
40
  # settings made in ~/.ssh/config.
@@ -30,21 +59,3 @@
30
59
  # remote_path="http://twitter.com/user"
31
60
  # system "curl -F media='@#{file}' -F username=user -F password=secret -F message=Captured http://twitpic.com/api/uploadAndPost"
32
61
  #
33
- # scp
34
- # ===
35
- #
36
- # Standard scp, using the ruby net/ssh library.
37
- #
38
- # * user - optinal if your remote user is the same as your local user
39
- # * password - optional if you have setup key pair authentication
40
- # * host - the remote host name
41
- # * url - the public url to the remote host+path
42
- # * path - the remote path to upload to
43
-
44
- #upload:
45
- # type: scp
46
- # user: user
47
- # host: example.com
48
- # path: example.com/captured/
49
- # url: "http://example.com/captured/"
50
-
@@ -21,6 +21,7 @@ class Captured
21
21
  end
22
22
  end
23
23
 
24
+ # Depricated this is now handeled by launchd
24
25
  def self.run_and_watch!(options)
25
26
  require 'captured/fs_events'
26
27
  watch_path = options[:watch_path] || "#{ENV['HOME']}/Desktop/"
@@ -12,42 +12,19 @@ class FileUploader
12
12
  @config = YAML.load_file(options[:config_file])
13
13
  case @config['upload']['type']
14
14
  when"eval"
15
- @upload_proc = eval_proc
15
+ require File.expand_path(File.dirname(__FILE__) + '/uploaders/eval_uploader')
16
+ @uploader = EvalUploader.new(@config)
16
17
  when"scp"
17
- @upload_proc = scp_proc
18
- when"ftp"
18
+ require File.expand_path(File.dirname(__FILE__) + '/uploaders/scp_uploader')
19
+ @uploader = ScpUploader.new(@config)
20
+ when"imageshack"
21
+ require File.expand_path(File.dirname(__FILE__) + '/uploaders/imageshack_uploader')
22
+ @uploader = ImageshackUploader.new(@config)
19
23
  else
20
24
  raise "Invalid Type"
21
25
  end
22
26
  end
23
27
 
24
- def eval_proc
25
- lambda do |file, remote_name|
26
- remote_path = nil
27
- unless eval @config['upload']['command']
28
- raise "Upload failed: Bad Eval in config file"
29
- end
30
- # if the eval defines remote_path we will copy that to the clipboard
31
- # otherwise we compute it ouselves
32
- remote_path || "#{@config['upload']['url']}#{remote_name}"
33
- end
34
- end
35
-
36
- def scp_proc
37
- require 'net/scp'
38
- require 'etc'
39
- settings = @config['upload']
40
- lambda do |file, remote_name|
41
- Net::SCP.upload!(settings['host'],
42
- settings['user'] || Etc.getlogin,
43
- file,
44
- settings['path']+remote_name,
45
- :password => settings['password'])
46
-
47
- "#{@config['upload']['url']}#{remote_name}"
48
- end
49
- end
50
-
51
28
  def pbcopy(str)
52
29
  system "ruby -e \"print '#{str}'\" | pbcopy"
53
30
  # I prefer the following method but it was being intermitant about actually
@@ -62,7 +39,8 @@ class FileUploader
62
39
  def process_upload(file)
63
40
  remote_name = Digest::MD5.hexdigest(file+Time.now.to_i.to_s) + File.extname(file)
64
41
  growl("Processing Upload", "#{File.dirname(File.expand_path(__FILE__))}/../../resources/action_run.png")
65
- remote_path = @upload_proc.call(file, remote_name)
42
+ @uploader.upload(file)
43
+ remote_path = @uploader.url
66
44
  puts "Uploaded '#{file}' to '#{remote_path}'"
67
45
  pbcopy remote_path
68
46
  growl("Upload Succeeded", "#{File.dirname(File.expand_path(__FILE__))}/../../resources/green_check.png")
@@ -0,0 +1,23 @@
1
+ class EvalUploader
2
+ attr_accessor :url
3
+
4
+ def initialize(config = {})
5
+ @config = config
6
+ end
7
+
8
+ def gen_remote_name(file)
9
+ Digest::MD5.hexdigest(file+Time.now.to_i.to_s) + File.extname(file)
10
+ end
11
+
12
+ def upload(file)
13
+ remote_path = nil
14
+ remote_name = gen_remote_name(file)
15
+ unless eval @config['upload']['command']
16
+ raise "Upload failed: Bad Eval in config file"
17
+ end
18
+ # if the eval defines remote_path we will copy that to the clipboard
19
+ # otherwise we compute it ouselves
20
+ @url = remote_path || "#{@config['upload']['url']}#{remote_name}"
21
+ @url
22
+ end
23
+ end
@@ -0,0 +1,126 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+ require 'cgi'
4
+ require 'mime/types'
5
+
6
+ # Adapted from http://codesnippets.joyent.com/posts/show/1156
7
+ class ImageshackUploader
8
+ attr_reader :url
9
+ USER_AGENT = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en) AppleWebKit/419 (KHTML, like Gecko) Safari/419.3"
10
+ BOUNDARY = '----------PuSHerInDaBUSH_$'
11
+
12
+ def initialize(config = {})
13
+ @config = config
14
+ @shack_id = config['upload']['shackid'] || "captured"
15
+ end
16
+
17
+ def upload(file_name)
18
+ unless file_name =~ /jpe?g|png|gif|bmp|tif|tiff|swf$/
19
+ raise(NonImageTypeError, 'Expected image file.')
20
+ end
21
+ @img = file_name
22
+ @posted_url, @hosturi, @res = "","",""
23
+ @header, @params = {}, {}
24
+ @header['Cookie'] = "myimages=#{@shack_id}"
25
+ @header['User-Agent'] = USER_AGENT
26
+ @params['uploadtype'] = 'on'
27
+ @params['brand'] = ''
28
+ @params['refer'] = ''
29
+ @params['MAX_FILE_SIZE'] = '13145728'
30
+ @params['optimage'] = '0'
31
+ @params['rembar'] = '1'
32
+ transfer
33
+ getdirect
34
+ @url = @posted_url.gsub("content.php?page=done&l=", "")
35
+ end
36
+
37
+ def prepare_multipart ( params )
38
+ fp = []
39
+ params.each do |k,v|
40
+ if v.respond_to?(:read)
41
+ fp.push(FileParam.new(k,v.path,v.read))
42
+ else fp.push(Param.new(k,v))
43
+ end
44
+ end
45
+ query = fp.collect {|p| "--" + BOUNDARY + "\r\n" + p.to_multipart }.join("") + "--" + BOUNDARY + "--"
46
+ return query
47
+ end
48
+
49
+ def prepFile(path_to_file)
50
+ file = File.new(path_to_file)
51
+ @header['Content-Type'] = "multipart/form-data, boundary=" + BOUNDARY + " "
52
+ @params['url'] = 'paste image url here'
53
+ @params['fileupload'] = file
54
+ $query = prepare_multipart(@params)
55
+ file.close
56
+ end
57
+
58
+ def locate(path)
59
+ path !~ /^http/ ? "local" : "remote"
60
+ end
61
+
62
+ def process_upload( query, headers={} )
63
+ Net::HTTP.start(@hosturi.host) do | http |
64
+ http.post(@hosturi.path, query, headers);
65
+ end
66
+ end
67
+
68
+ def transload(url)
69
+ @header['Content-Type'] = 'form-data'
70
+ @params['url'] = url
71
+ @params['fileupload'] = ''
72
+ postreq = Net::HTTP::Post.new(@hosturi.path, @header)
73
+ postreq.set_form_data(@params)
74
+ return Net::HTTP.new(@hosturi.host, @hosturi.port).start { |http| http.request(postreq) }
75
+ end
76
+
77
+ def transfer
78
+ case locate(@img)
79
+ when "local"
80
+ @hosturi = URI.parse('http://load.imageshack.us/index.php')
81
+ prepFile(@img)
82
+ @res = process_upload($query,@header)
83
+ when "remote"
84
+ @hosturi = URI.parse('http://imageshack.us/transload.php')
85
+ @res = transload(@img)
86
+ end
87
+ end
88
+
89
+ def getdirect
90
+ puts @res.header
91
+ puts @res.body
92
+ @posted_url = @res.header['location']
93
+ end
94
+
95
+ end
96
+
97
+ class Param
98
+ attr_accessor :k, :v
99
+
100
+ def initialize(k,v)
101
+ @k = k
102
+ @v = v
103
+ end
104
+
105
+ def to_multipart
106
+ return "Content-Disposition: form-data; name=\"#{CGI::escape(k)}\"\r\n\r\n#{v}\r\n"
107
+ end
108
+ end
109
+
110
+ class FileParam
111
+ attr_accessor :k, :filename, :content
112
+
113
+ def initialize(k, filename, content)
114
+ @k = k
115
+ @filename = filename
116
+ @content = content
117
+ end
118
+
119
+ def to_multipart
120
+ return "Content-Disposition: form-data; name=\"#{CGI::escape(k)}\"; filename=\"#{filename}\"\r\n" +
121
+ "Content-Type: #{MIME::Types.type_for(@filename)}\r\n\r\n" + content + "\r\n"
122
+ end
123
+ end
124
+
125
+
126
+
@@ -0,0 +1,30 @@
1
+ class ScpUploader
2
+ attr_accessor :url
3
+
4
+ def initialize(config = {})
5
+ @config = config
6
+ end
7
+
8
+ def gen_remote_name(file)
9
+ Digest::MD5.hexdigest(file+Time.now.to_i.to_s) + File.extname(file)
10
+ end
11
+
12
+ def upload(file)
13
+ puts "Uploading #{file}"
14
+ # TODO: This needs to be called from file upload
15
+ # and this calss needs to be completed
16
+ # maybe some tests
17
+ require 'net/scp'
18
+ require 'etc'
19
+ settings = @config['upload']
20
+ remote_name = gen_remote_name(file)
21
+ puts Net::SCP.upload!(settings['host'],
22
+ settings['user'] || Etc.getlogin,
23
+ file,
24
+ settings['path']+remote_name,
25
+ :password => settings['password'])
26
+
27
+ @url = "#{@config['upload']['url']}#{remote_name}"
28
+ @url
29
+ end
30
+ end
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env ruby
2
+ require 'optparse'
3
+
4
+ def red(s); colorize(s, "\e[0m\e[31m"); end
5
+ def green(s); colorize(s, "\e[0m\e[32m"); end
6
+ def dark_green(s); colorize(s, "\e[32m"); end
7
+ def yellow(s); colorize(s, "\e[0m\e[33m"); end
8
+ def blue(s); colorize(s, "\e[0m\e[34m"); end
9
+ def dark_blue(s); colorize(s, "\e[34m"); end
10
+ def pur(s); colorize(s, "\e[0m\e[35m"); end
11
+ def colorize(text, color_code) "#{color_code}#{text}\e[0m" end
12
+
13
+ def log(msg)
14
+ puts yellow " #{msg}"
15
+ end
16
+
17
+ options = {}
18
+ OptionParser.new do |opts|
19
+ # -h,--help Display this help
20
+ # -v,--version Display version number
21
+ # -n,--name Set the name of the application that sends the notification
22
+ # [Default: growlnotify]
23
+ # -s,--sticky Make the notification sticky
24
+ # -a,--appIcon Specify an application name to take the icon from
25
+ # -i,--icon Specify a file type or extension to look up for the
26
+ # notification icon
27
+ # -I,--iconpath Specify a file whose icon will be the notification icon
28
+ # --image Specify an image file to be used for the notification icon
29
+
30
+ opts.on('--image IMAGE', "Specify an image file to be used for the notification icon") do |img|
31
+ options[:image] = true
32
+ if !File.exists? img
33
+ log "GROWL ERROR: Image file does not exist"
34
+ exit 1
35
+ end
36
+ end
37
+
38
+ # -m,--message Sets the message to be used instead of using stdin
39
+ opts.on('-m', '--message MSG', "Specify an image file to be used for the notification icon") do |msg|
40
+ options[:message] = true
41
+ if !msg
42
+ log "GROWL ERROR: No message"
43
+ exit 1
44
+ else
45
+ log "growl: #{msg}"
46
+ end
47
+ end
48
+ # Passing - as the argument means read from stdin
49
+ # -p,--priority Specify an int or named key (default is 0)
50
+ # -d,--identifier Specify a notification identifier (used for coalescing)
51
+ # -H,--host Specify a hostname to which to send a remote notification.
52
+ # -P,--password Password used for remote notifications.
53
+ # -u,--udp Use UDP instead of DO to send a remote notification.
54
+ # --port Port number for UDP notifications.
55
+ # -A,--auth Specify digest algorithm for UDP authentication.
56
+ # Either MD5 [Default], SHA256 or NONE.
57
+ # -c,--crypt Encrypt UDP notifications.
58
+ # -w,--wait Wait until the notification has been dismissed.
59
+ # --progress Set a progress value for this notification.
60
+
61
+ # -t,--title Does nothing. Any text following will be treated as the
62
+ # title because that's the default argument behaviour
63
+ opts.on('-t', "Does nothing") do |msg|
64
+ options[:title] = true
65
+ if !msg
66
+ log "GROWL ERROR: No title"
67
+ exit 1
68
+ end
69
+ log "growl: #{msg}"
70
+ end
71
+
72
+ #puts " Grrrr! #{ARGV.inspect}"
73
+ end.parse!
74
+
@@ -1,7 +1,30 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
- describe "Captured" do
4
- it "fails" do
5
- fail "hey buddy, you should probably rename this file and start specing for real"
3
+ describe "File Uploader" do
4
+ before(:all) do
5
+ # This is run once and only once, before all of the examples
6
+
7
+ #Make a backup of the clipboard
8
+ $pb_backup = `pbpaste`
9
+
10
+ system "mkdir -p #{File.dirname(__FILE__) + '/../tmp/watch_path'}"
11
+ @options = {:config_file => File.dirname(__FILE__) + '/fixtures/scp_config.yml',
12
+ :watch_path => File.dirname(__FILE__) + '/../tmp/watch_path',
13
+ :watch_pattern => Captured.guess_watch_path,
14
+ :growl_path => "/usr/local/bin/growlnotify" }
15
+ end
16
+
17
+ after(:all) do
18
+ # This is run once and only once, after all of the examples
19
+ # Restore the clipboard contents
20
+ FileUploader.new(@options).pbcopy $pb_backup
21
+ end
22
+
23
+
24
+ it "should copy text to the system clipboard" do
25
+ fu = FileUploader.new @options
26
+ str = "Testing captured is fun for you"
27
+ fu.pbcopy str
28
+ `pbpaste`.should == str
6
29
  end
7
30
  end
@@ -0,0 +1,35 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "File Uploader" do
4
+ before(:all) do
5
+ # This is run once and only once, before all of the examples
6
+
7
+ #Make a backup of the clipboard
8
+ $pb_backup = `pbpaste`
9
+
10
+ system "mkdir -p #{File.dirname(__FILE__) + '/../tmp/watch_path'}"
11
+ @options = {:config_file => File.dirname(__FILE__) + '/fixtures/scp_config.yml',
12
+ :watch_path => File.dirname(__FILE__) + '/../tmp/watch_path',
13
+ :watch_pattern => Captured.guess_watch_path,
14
+ :growl_path => File.dirname(__FILE__) + '/bin/mockgrowlnotify'}
15
+ end
16
+
17
+ after(:all) do
18
+ # This is run once and only once, after all of the examples
19
+ # Restore the clipboard contents
20
+ FileUploader.new(@options).pbcopy $pb_backup
21
+ end
22
+
23
+
24
+ it "should copy text to the system clipboard" do
25
+ fu = FileUploader.new @options
26
+ str = "Testing captured is fun for you"
27
+ fu.pbcopy str
28
+ `pbpaste`.should == str
29
+ end
30
+ it "should call growl" do
31
+ fu = FileUploader.new @options
32
+ str = "Testing captured is fun for you"
33
+ fu.growl str
34
+ end
35
+ end
@@ -0,0 +1,7 @@
1
+ upload:
2
+ type: scp
3
+ user: user
4
+ host: example.com
5
+ path: example.com/captured/
6
+ url: "http://example.com/captured/"
7
+
@@ -1,3 +1,4 @@
1
+ require 'rubygems'
1
2
  require 'spec'
2
3
 
3
4
  $LOAD_PATH.unshift(File.dirname(__FILE__))
@@ -0,0 +1,14 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/../../lib/captured/uploaders/imageshack_uploader')
3
+
4
+ describe "SCP File Uploader" do
5
+ it "should upload to the server" do
6
+ config = {"upload"=>{"url"=>"http://fuzzymonk.com/captured/",
7
+ "type"=>"imageshack",
8
+ "shackid"=>"capturedspec"}}
9
+
10
+ @uploader = ImageshackUploader.new(config)
11
+ @uploader.upload(File.expand_path(File.dirname(__FILE__) + '/../../resources/captured.png'))
12
+ system "open #{@uploader.url}"
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/../../lib/captured/uploaders/scp_uploader')
3
+
4
+ describe "SCP File Uploader" do
5
+ it "should upload to the server" do
6
+ # This spec requires a scp_spec section in the config file with the
7
+ # scp settings
8
+ config = YAML.load_file("#{ENV['HOME']}/.captured.yml")['scp_spec']
9
+ @uploader = ScpUploader.new(config)
10
+ @uploader.upload(File.expand_path(File.dirname(__FILE__) + '/../../resources/captured.png'))
11
+ system "open #{@uploader.url}"
12
+ end
13
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: captured
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christopher Sexton
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-28 00:00:00 -04:00
12
+ date: 2009-11-02 00:00:00 -05:00
13
13
  default_executable: captured
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -22,7 +22,7 @@ dependencies:
22
22
  - !ruby/object:Gem::Version
23
23
  version: "0"
24
24
  version:
25
- description:
25
+ description: Because <shift>-<command>-4 is the single most useful shorcut in Macdom
26
26
  email: csexton@gmail.com
27
27
  executables:
28
28
  - captured
@@ -40,6 +40,9 @@ files:
40
40
  - lib/captured/file_tracker.rb
41
41
  - lib/captured/file_uploader.rb
42
42
  - lib/captured/fs_events.rb
43
+ - lib/captured/uploaders/eval_uploader.rb
44
+ - lib/captured/uploaders/imageshack_uploader.rb
45
+ - lib/captured/uploaders/scp_uploader.rb
43
46
  - resources/2uparrow.png
44
47
  - resources/action_run.png
45
48
  - resources/captured.png
@@ -47,8 +50,13 @@ files:
47
50
  - resources/red_star.png
48
51
  - resources/red_x.png
49
52
  - resources/ruby.png
53
+ - spec/bin/mockgrowlnotify
50
54
  - spec/captured_spec.rb
55
+ - spec/file_uploader_spec.rb
56
+ - spec/fixtures/scp_config.yml
51
57
  - spec/spec_helper.rb
58
+ - spec/uploader_specs/imageshack_uploader_spec.rb
59
+ - spec/uploader_specs/scp_uploader_spec.rb
52
60
  - LICENSE
53
61
  has_rdoc: true
54
62
  homepage: http://github.com/csexton/captured
@@ -80,4 +88,7 @@ specification_version: 3
80
88
  summary: Quick screenshot sharing for OS X
81
89
  test_files:
82
90
  - spec/captured_spec.rb
91
+ - spec/file_uploader_spec.rb
83
92
  - spec/spec_helper.rb
93
+ - spec/uploader_specs/imageshack_uploader_spec.rb
94
+ - spec/uploader_specs/scp_uploader_spec.rb