s2d 0.0.1

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.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in s2d.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Steffen Uhlig
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,59 @@
1
+ s2d - Send to Device
2
+ ====================
3
+
4
+ Send text and documentation from the command line to various devices.
5
+
6
+ Examples
7
+ --------
8
+ - Found an interesting URL that I want to have on my iPhone
9
+ - Send the PDF I just produced to my iPad
10
+ - Send a file to my Kindle
11
+
12
+ User Interface
13
+ --------------
14
+ I am mostly working on the command line, therefore I want something that works as pipe:
15
+
16
+ cat file.txt | 2iphone
17
+ 2iphone file.txt
18
+ 2kindle book.mobi
19
+ 2ipad document.pdf
20
+
21
+ All of these commands are actualy aliased versions of the `s2d` command:
22
+
23
+ # assuming that s2d has a device called 'iPhone' configured
24
+ alias 2iphone="s2d --device=iPhone"
25
+ alias 2kindle="s2d --device=Kindle"
26
+ alias 2ipad="s2d --device=iPad"
27
+
28
+ Concepts
29
+ ========
30
+
31
+ Target Device
32
+ -------------
33
+ Identifies a device. Holds device name and transport. Examples names are 'iPhone', 'MyKindle' or 'Paula's iPad'.
34
+
35
+ Transport
36
+ ---------
37
+ A transport defines how to reach a device and holds all information required to reach it:
38
+
39
+ * [Prowl](http://www.prowlapp.com/) (for iPhone/iPad)
40
+
41
+ Not implemented yet:
42
+
43
+ * Mail
44
+ * SMS
45
+ * Twitter DM
46
+ * Custom (potentially requires a device-specific app e.g. on the iPhone)
47
+
48
+ Delivery Strategy
49
+ -----------------
50
+ Belongs to a transport.
51
+
52
+ * iPhone & iPad
53
+ - Smaller text, URLs, etc: Send directly
54
+ - Larger files: Upload to Dropbox and send private link
55
+ - Limit probably needs configuration
56
+
57
+ * Kindle
58
+ - File attachment of an eMail. s2d will create one if input was passed as pipe.
59
+
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/bin/s2d ADDED
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler'
4
+ Bundler.require
5
+
6
+ def die(msg, code = 1)
7
+ STDERR.puts(msg)
8
+ exit(code)
9
+ end
10
+
11
+ # TODO Add wizard for initial device config
12
+ # TODO Add parameters for selecting the default device
13
+
14
+ device = 'iPhone' # TODO Add --device parameter
15
+ verbose = true # TODO Add --verbose parameter
16
+
17
+ if device
18
+ target = S2D::Configuration::Repository.instance.device(device.to_sym)
19
+ die("No device #{device} not configured") if target.nil?
20
+ else
21
+ target = S2D::Configuration::Repository.instance.active_device
22
+ die("No active device configured") if target.nil?
23
+ end
24
+
25
+ message = S2D::Message.new
26
+
27
+ if ARGV.size > 0
28
+ message.body = ARGV.join(' ')
29
+ else
30
+ puts 'Type your message and end with Control-D.' if verbose && STDIN.tty?
31
+ message.body = ARGF.read
32
+ end
33
+
34
+ if message.invalid?
35
+ die('Invalid message') # TODO Add message.errors from ActiveSupport::Validations
36
+ else
37
+ begin
38
+ puts "Delivering your message via #{target.transport}" if verbose
39
+ target.deliver(message)
40
+ puts "Done." if verbose
41
+ rescue
42
+ if verbose
43
+ die($!.backtrace.join('\n'))
44
+ else
45
+ die($!.message)
46
+ end
47
+ end
48
+ end
data/lib/s2d.rb ADDED
@@ -0,0 +1,20 @@
1
+ require 'prowler'
2
+ require 'active_support/inflector'
3
+
4
+ require 's2d/version'
5
+
6
+ require 's2d/configuration/attribute'
7
+ require 's2d/configuration/repository'
8
+
9
+ require 's2d/device'
10
+ require 's2d/message'
11
+
12
+ require 's2d/transports/transport'
13
+ require 's2d/transports/prowler'
14
+
15
+ require 's2d/mappers/device_mapper'
16
+ require 's2d/mappers/transport_mapper'
17
+
18
+ module S2D
19
+ # Your code goes here...
20
+ end
@@ -0,0 +1,33 @@
1
+ module S2D
2
+ module Configuration
3
+ class Attribute
4
+ attr_reader :key, :description
5
+
6
+ protected
7
+
8
+ def initialize(mandatory, key, description)
9
+ @mandatory, @key, @description = mandatory, key, description
10
+ end
11
+
12
+ def mandatory?
13
+ @mandatory
14
+ end
15
+ end
16
+
17
+ class MandatoryAttribute < Attribute
18
+ def initialize(key, description)
19
+ super(true, key, description)
20
+ end
21
+ end
22
+
23
+ class OptionalAttribute < Attribute
24
+ attr_reader :default_value
25
+
26
+ def initialize(key, description, default_value)
27
+ super(false, key, description)
28
+ @default_value = default_value
29
+ end
30
+ end
31
+ end
32
+ end
33
+
@@ -0,0 +1,74 @@
1
+ require 'singleton'
2
+ require 'yaml'
3
+
4
+ module S2D
5
+ module Configuration
6
+ class Repository
7
+ include Singleton
8
+
9
+ attr_reader :path
10
+
11
+ def initialize
12
+ @path = File.join(File.expand_path('~'), FILE_NAME)
13
+ @data = load
14
+ end
15
+
16
+ def load
17
+ YAML.load_file(@path)
18
+ rescue Errno::ENOENT
19
+ default_structure
20
+ end
21
+
22
+ def devices
23
+ @data[:devices].keys
24
+ end
25
+
26
+ def device(key)
27
+ selected = @data[:devices][key]
28
+
29
+ if selected.nil?
30
+ nil
31
+ else
32
+ Mappers::DeviceMapper.to_object(selected)
33
+ end
34
+ end
35
+
36
+ def add_device(device, activate = false)
37
+ @data[:devices][device.name.to_sym] = Mappers::DeviceMapper.to_hash(device)
38
+ self.active_device = device if activate
39
+ write
40
+ end
41
+
42
+ def active_device
43
+ device(:default)
44
+ end
45
+
46
+ def active_device=(device)
47
+ add_device(device, false) unless device(device.name.to_sym)
48
+ @data[:devices][:default] = device.name.to_sym
49
+ write
50
+ end
51
+
52
+ def empty?
53
+ @data == default_structure
54
+ end
55
+
56
+ def reset
57
+ self.send(:initialize)
58
+ end
59
+
60
+ private
61
+ FILE_NAME = '.s2drc'
62
+
63
+ def default_structure
64
+ { :devices => {}}
65
+ end
66
+
67
+ def write
68
+ File.open(@path, File::RDWR|File::TRUNC|File::CREAT, 0600) do |rcfile|
69
+ rcfile.write(@data.to_yaml)
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
data/lib/s2d/device.rb ADDED
@@ -0,0 +1,13 @@
1
+ module S2D
2
+ class Device
3
+ extend Forwardable
4
+ def_delegator :transport, :deliver
5
+
6
+ attr_reader :name
7
+ attr_accessor :transport
8
+
9
+ def initialize(name)
10
+ @name = name
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,2 @@
1
+ require 'openssl'
2
+ OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
@@ -0,0 +1,20 @@
1
+ module S2D
2
+ module Mappers
3
+ class DeviceMapper
4
+ class << self
5
+ def to_hash(device)
6
+ {}.tap do |h|
7
+ h[:name] = device.name
8
+ h[:transport] = TransportMapper.to_hash(device.transport)
9
+ end
10
+ end
11
+
12
+ def to_object(h)
13
+ Device.new(h[:name]).tap do |d|
14
+ d.transport = TransportMapper.to_object(h[:transport])
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,18 @@
1
+ module S2D
2
+ module Mappers
3
+ class TransportMapper
4
+ class << self
5
+ def to_hash(transport)
6
+ {}.tap do |h|
7
+ h[:name] = transport.class
8
+ h[:config] = transport.config
9
+ end
10
+ end
11
+
12
+ def to_object(h)
13
+ h[:name].new(h[:config])
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ module S2D
2
+ class Message
3
+ attr_accessor :subject, :body
4
+
5
+ def initialize(subject = "from #{%x[hostname].chomp}:", body = nil)
6
+ @subject, @body = subject, body
7
+ end
8
+
9
+ def valid?
10
+ valid?
11
+ end
12
+
13
+ def invalid?
14
+ @subject.nil? || @body.nil? || @subject.empty? || @body.empty?
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,65 @@
1
+ require 'singleton'
2
+ require 'yaml'
3
+
4
+ module S2D
5
+ module Configuration
6
+ class Repository
7
+ include Singleton
8
+
9
+ attr_reader :path
10
+
11
+ def initialize
12
+ @path = File.join(File.expand_path('~'), FILE_NAME)
13
+ @data = load
14
+ end
15
+
16
+ def load
17
+ YAML.load_file(@path)
18
+ rescue Errno::ENOENT
19
+ default_structure
20
+ end
21
+
22
+ def add_device(device, activate = false)
23
+ @data[:devices][device.name.to_sym] = Mappers::DeviceMapper.to_hash(device)
24
+ self.active_device = device if activate
25
+ write
26
+ end
27
+
28
+ def active_device
29
+ default = devices[:default]
30
+
31
+ if default.nil?
32
+ raise "No default device configured"
33
+ else
34
+ device(default)
35
+ end
36
+ end
37
+
38
+ def active_device=(device)
39
+ devices[:default] = device.name.to_sym
40
+ write
41
+ end
42
+
43
+ def empty?
44
+ @data == default_structure
45
+ end
46
+
47
+ def reset
48
+ self.send(:initialize)
49
+ end
50
+
51
+ private
52
+ FILE_NAME = '.s2drc'
53
+
54
+ def default_structure
55
+ { :devices => {}}
56
+ end
57
+
58
+ def write
59
+ File.open(@path, File::RDWR|File::TRUNC|File::CREAT, 0600) do |rcfile|
60
+ rcfile.write(@data.to_yaml)
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,27 @@
1
+ module S2D
2
+ module Transports
3
+ class Prowler < Transport
4
+ include S2D::Configuration
5
+
6
+ def initialize(config)
7
+ super(config)
8
+ ::Prowler.logger.level = Logger::WARN
9
+ @prowler = ::Prowler.new(:application => $0, :api_key => config[:api_key])
10
+ end
11
+
12
+ def deliver(message)
13
+ @prowler.notify(message.subject, message.body)
14
+ end
15
+
16
+ #
17
+ # Config wizard uses this information to collect required and optional
18
+ # config parameters
19
+ #
20
+ def attributes
21
+ [ MandatoryAttribute.new(:api_key, 'API key for prowlapp.com'),
22
+ OptionalAttribute.new(:application, 'Application name to be passed to Prowl', $0),
23
+ ]
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ module S2D
2
+ module Transports
3
+ class Transport
4
+ attr_reader :config
5
+
6
+ def initialize(config)
7
+ @config = config
8
+ end
9
+
10
+ def deliver(message)
11
+ raise "Transport class #{self.class} does not implement #deliver(message)"
12
+ end
13
+
14
+ #
15
+ # Config wizard uses this information to collect required and optional
16
+ # config parameters
17
+ #
18
+ def attributes
19
+ []
20
+ end
21
+
22
+ def to_s
23
+ self.class.name.demodulize
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,3 @@
1
+ module S2D
2
+ VERSION = "0.0.1"
3
+ end
data/s2d.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/s2d/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Nicholas E. Rabenau"]
6
+ gem.email = ["nerab@gmx.at"]
7
+ gem.description = %q{Send text and documents to various mobile devices from the command line.}
8
+ gem.summary = %q{s2d - Send to Device}
9
+ gem.homepage = "http://github.com/nerab/s2d"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "s2d"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = S2D::VERSION
17
+
18
+ gem.add_dependency 'prowler', '~> 1.3'
19
+ gem.add_dependency 'activesupport', '~> 3.2'
20
+
21
+ gem.add_development_dependency 'guard-test', '~> 0.5'
22
+ gem.add_development_dependency 'guard-bundler', '~> 1.0'
23
+ gem.add_development_dependency 'rake', '~> 0.9'
24
+ gem.add_development_dependency 'pry'
25
+ end
metadata ADDED
@@ -0,0 +1,161 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: s2d
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Nicholas E. Rabenau
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-24 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: prowler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.3'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.3'
30
+ - !ruby/object:Gem::Dependency
31
+ name: activesupport
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '3.2'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '3.2'
46
+ - !ruby/object:Gem::Dependency
47
+ name: guard-test
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '0.5'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '0.5'
62
+ - !ruby/object:Gem::Dependency
63
+ name: guard-bundler
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '1.0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '1.0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: rake
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: '0.9'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: '0.9'
94
+ - !ruby/object:Gem::Dependency
95
+ name: pry
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ description: Send text and documents to various mobile devices from the command line.
111
+ email:
112
+ - nerab@gmx.at
113
+ executables:
114
+ - s2d
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - .gitignore
119
+ - Gemfile
120
+ - LICENSE
121
+ - README.md
122
+ - Rakefile
123
+ - bin/s2d
124
+ - lib/s2d.rb
125
+ - lib/s2d/configuration/attribute.rb
126
+ - lib/s2d/configuration/repository.rb
127
+ - lib/s2d/device.rb
128
+ - lib/s2d/disable_peer_verification.rb
129
+ - lib/s2d/mappers/device_mapper.rb
130
+ - lib/s2d/mappers/transport_mapper.rb
131
+ - lib/s2d/message.rb
132
+ - lib/s2d/repository.rb
133
+ - lib/s2d/transports/prowler.rb
134
+ - lib/s2d/transports/transport.rb
135
+ - lib/s2d/version.rb
136
+ - s2d.gemspec
137
+ homepage: http://github.com/nerab/s2d
138
+ licenses: []
139
+ post_install_message:
140
+ rdoc_options: []
141
+ require_paths:
142
+ - lib
143
+ required_ruby_version: !ruby/object:Gem::Requirement
144
+ none: false
145
+ requirements:
146
+ - - ! '>='
147
+ - !ruby/object:Gem::Version
148
+ version: '0'
149
+ required_rubygems_version: !ruby/object:Gem::Requirement
150
+ none: false
151
+ requirements:
152
+ - - ! '>='
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ requirements: []
156
+ rubyforge_project:
157
+ rubygems_version: 1.8.24
158
+ signing_key:
159
+ specification_version: 3
160
+ summary: s2d - Send to Device
161
+ test_files: []