file-convert 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4ab5545b631ce1b728c55f51238e30c3f55e3459
4
+ data.tar.gz: 6c0170fd117a7030326857e34124102dbe57fe37
5
+ SHA512:
6
+ metadata.gz: 94c4e4c7dfec2285946452d565195756dfd761e9ffd3d448d5bf098ac30c667e0bcf17dddf059620f7865687d9a10aa4f44cdc996b508105d7740023feeb20e9
7
+ data.tar.gz: 33172e266792bd45830551e68d0a6641a350363189b91697d298d9acb48ea37b928beaace5c37a98e33602cb39bfff7e9c00b25e5f920c9fb43b45e8a9270014
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Roman Ernst and tolingo GmbH
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ 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, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,79 @@
1
+ # file-convert [![Build Status](https://travis-ci.org/tolingo/file-convert.svg?branch=feature%2Ffix-specs-and-refactor)](https://travis-ci.org/tolingo/file-convert) [![Test Coverage](https://codeclimate.com/repos/53f4984b6956807963019c1a/badges/7aef33ebfd86eb320a98/coverage.svg)](https://codeclimate.com/repos/53f4984b6956807963019c1a/feed) [![Code Climate](https://codeclimate.com/repos/53f4984b6956807963019c1a/badges/7aef33ebfd86eb320a98/gpa.svg)](https://codeclimate.com/repos/53f4984b6956807963019c1a/feed) [![Dependency Status](https://gemnasium.com/tolingo/file-convert.svg)](https://gemnasium.com/tolingo/file-convert)
2
+
3
+ > Use google-api-ruby-client and Google Drive to convert files from one mime-type to another.
4
+ For available formats see [Google Drive API Export Formats](https://developers.google.com/drive/web/integrate-open#open_and_convert_google_docs_in_your_app).
5
+
6
+ ## Installation
7
+
8
+ Simply add it to your Gemfile:
9
+
10
+ ```ruby
11
+ gem 'file-convert'
12
+ ```
13
+
14
+ ## Config
15
+
16
+ ### Via initializer
17
+
18
+ `FileConvert` exposes `.configure` which accepts a block and passes the config hash.
19
+ *Example*:
20
+
21
+ ```ruby
22
+ FileConvert.configure do |config|
23
+ config['google_service_account'] = {
24
+ 'email' => '<strange-hash>@developer.gserviceaccount.com',
25
+ 'pkcs12_file_path' => 'config/file_convert_key.p12'
26
+ }
27
+ end
28
+ ```
29
+
30
+ ### Via YAML
31
+
32
+ You need to add a YAML configuration file to `/config/file_convert.yml` that looks like `config/file_convert.sample.yml`.
33
+
34
+ In order to communicate with the Google API, `file_convert` requires a google developer email Address (`email`) and `pkcs12_file_path`.
35
+
36
+ Visit [Google Developers Console](console.developers.google.com) and check **Credentials**.
37
+ Here you can add a *new Client ID*. Select **Service Account** as application type.
38
+
39
+ You should now be able to download your *P12 key* and see your *developer email address*.
40
+ Place the *P12 key* somewhere accessible for your app and provide the location to the config. The sample config assumes your *P12 key* is located in `/config/file_convert_key.p12`.
41
+
42
+ Sample config as in `file_convert.samle.yml`:
43
+ ```yaml
44
+ file_convert:
45
+ google_service_account:
46
+ email: '<strange-hash>@developer.gserviceaccount.com'
47
+ pkcs12_file_path: 'config/file_convert_key.p12'
48
+ ```
49
+
50
+ ## Examples
51
+
52
+ ```ruby
53
+ # converts `path_to_some_file` from <txt> to <pdf>
54
+ conversion = FileConvert.convert('path_to_some_file.txt', 'text/plain', 'application/pdf')
55
+ # converted body is accessible via `#body`
56
+ conversion.body
57
+ # .. or define a path to save the converted document to
58
+ conversion.save('path_to_new_file.pdf')
59
+ ```
60
+
61
+ ## Specs
62
+
63
+ * `$ bundle exec rake` for `rspec` and `rubocop`.
64
+ * `$ bundle exec rake build` to also run the `integration` tests located at `spec/integration/**/*_integration.rb`.
65
+ Note that you need to have a valid `config/file_convert.yml` present for these tests to work,
66
+ since we want to actually test the integration with the Google API here. (Do not worry, TravisCI will run these test as well.)
67
+
68
+ ## Contributing
69
+
70
+ In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using the ways described [above](#specs).
71
+
72
+ ## Next Steps
73
+
74
+ * Enable OCR if necessary when uploading files
75
+ * Add CLI
76
+ * Add different adapter than Google?
77
+
78
+ ## License
79
+ file-convert is Copyright © 2014 [Roman Ernst](http://farbenmeer.net) and [tolingo GmbH](http://tolingo.com) and may be redistributed under the terms specified in the [LICENSE](https://github.com/tolingo/file-convert/blob/master/LICENSE) file.
@@ -0,0 +1,34 @@
1
+ module FileConvert
2
+ require 'file_convert/version'
3
+ require 'file_convert/exception'
4
+ require 'file_convert/configure'
5
+ require 'file_convert/client'
6
+ require 'file_convert/file'
7
+ require 'file_convert/upload'
8
+ require 'file_convert/conversion'
9
+
10
+ extend FileConvert::Configure
11
+
12
+ FileConvert::Configure.init_config!
13
+
14
+ ###
15
+ # @param [String] file_path
16
+ # Source file for conversions
17
+ # @param [String]
18
+ # Source file mime-type
19
+ # @param [String]
20
+ # Target file mime-type (converion target)
21
+ #
22
+ # @return [FileConvert::Conversion]
23
+ def self.convert(file_path, source_mime_type, target_mime_type)
24
+ upload = FileConvert::Upload.new(client, file_path, source_mime_type)
25
+ FileConvert::Conversion.new(client, upload.file, target_mime_type)
26
+ end
27
+
28
+ ###
29
+ # Initialize a new FileConvert::Client
30
+ def self.client
31
+ fail Exception::MissingConfig unless config_present?
32
+ @client ||= FileConvert::Client.new
33
+ end
34
+ end
@@ -0,0 +1,40 @@
1
+ module FileConvert
2
+ require 'google/api_client'
3
+
4
+ class Client < Google::APIClient
5
+ APP_OPTIONS = {
6
+ application_name: 'file-convert',
7
+ application_version: FileConvert::Version::STRING
8
+ }
9
+
10
+ attr_reader :drive
11
+
12
+ ###
13
+ # Inherits from Google::APIClient
14
+ # Basically wraps authentiation for simple configuration
15
+ #
16
+ # @return [FileConvert::Client] (inherits from Google::APIClient)
17
+ def initialize
18
+ gaccount = FileConvert.config['google_service_account']
19
+ gaccount['auth_url'] ||= 'https://www.googleapis.com/auth/drive'
20
+
21
+ key = load_key gaccount['pkcs12_file_path'], 'notasecret'
22
+ asserter = get_asserter gaccount['email'], gaccount['auth_url'], key
23
+
24
+ super(APP_OPTIONS).tap do |client|
25
+ client.authorization = asserter.authorize
26
+ @drive = client.discovered_api('drive', 'v2')
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def load_key(path, secret)
33
+ Google::APIClient::PKCS12.load_key(path, secret)
34
+ end
35
+
36
+ def get_asserter(email, auth_url, key)
37
+ Google::APIClient::JWTAsserter.new email, auth_url, key
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,41 @@
1
+ module FileConvert
2
+ module Configure
3
+ require 'yaml'
4
+
5
+ DEFAULT_CONFIG_PATH = 'config/file_convert.yml'
6
+
7
+ def self.config_yaml_present?
8
+ ::File.exist?(DEFAULT_CONFIG_PATH)
9
+ end
10
+
11
+ def self.config_from_yaml
12
+ ::File.open(DEFAULT_CONFIG_PATH) do |file|
13
+ YAML.load(file)['file_convert']
14
+ end
15
+ end
16
+
17
+ def self.config
18
+ @@config
19
+ end
20
+
21
+ ###
22
+ # Loads config/file_convert.yml['file_convert'] into Config
23
+ # Or defaults to empty Hash if config file is not present
24
+ def self.init_config!
25
+ @@config = config_yaml_present? ? config_from_yaml : {}
26
+ end
27
+
28
+ def configure
29
+ yield config
30
+ end
31
+
32
+ def config
33
+ Configure.config
34
+ end
35
+
36
+ def config_present?
37
+ provider = 'google_service_account'
38
+ config.is_a?(Hash) && config.key?(provider)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,70 @@
1
+ module FileConvert
2
+ class Conversion
3
+ attr_reader :file
4
+ attr_reader :body
5
+
6
+ ##
7
+ # Downloads remote file from Google Drive with given mime_type
8
+ #
9
+ # @param [FileConvert::Client] client
10
+ # @param [FileConvert::File] remote_file
11
+ # @param [String] mime_type
12
+ # Target mime_type the file gets converted to
13
+ #
14
+ # @return [FileConvert::File] remote_file with requested #conversions
15
+ def initialize(client, remote_file, mime_type)
16
+ @client = client
17
+ @remote_file = remote_file
18
+ @original_file_data = remote_file.data
19
+ @mime_type = mime_type
20
+
21
+ # Raise if requested mime-type is not available
22
+ fail missing_mime_type_exception unless export_links.key?(mime_type)
23
+ fail data_error_exception if @original_file_data.to_hash.key?('error')
24
+
25
+ @file = fetch_file
26
+ @body = @file.body
27
+ @remote_file.add_conversion(mime_type, self)
28
+ end
29
+
30
+ ##
31
+ # Saves result as file
32
+ # @param [String] target_path
33
+ #
34
+ # @return [FileConvert::Conversion]
35
+ def save(target_path)
36
+ ::File.open(target_path, 'w') { |file| file.write(@file.body) }
37
+ end
38
+
39
+ private
40
+
41
+ ##
42
+ # @return [Hash] available mime-type download URIs
43
+ def export_links
44
+ @original_file_data['exportLinks'].to_hash
45
+ end
46
+
47
+ ###
48
+ # Actually downloads the file
49
+ # Raises if request was not successfull
50
+ #
51
+ # @return [Google::APIClient::Result]
52
+ def fetch_file
53
+ @client.execute(uri: export_links[@mime_type]).tap do |result|
54
+ fail connection_error_exception unless result.status == 200
55
+ end
56
+ end
57
+
58
+ def data_error_exception
59
+ Exception::UploadedFileDataError.new(@original_file_data)
60
+ end
61
+
62
+ def missing_mime_type_exception
63
+ Exception::MissingConversionMimeType.new(@mime_type, export_links.keys)
64
+ end
65
+
66
+ def connection_error_exception
67
+ Exception::DownloadConnectionError.new(@file['error']['message'])
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,55 @@
1
+ module FileConvert
2
+ module Exception
3
+ class MissingConversionMimeType < StandardError
4
+ def initialize(requested_mime_type, available_mime_types)
5
+ super()
6
+ @requested_mime_type = requested_mime_type
7
+ @available_mime_types = available_mime_types
8
+ end
9
+
10
+ def message
11
+ ''"
12
+ The requested mime type '#{@requested_mime_type}' is not available.
13
+ Available mime types: #{@available_mime_types.join(', ')}.
14
+ "''
15
+ end
16
+ end
17
+
18
+ class UploadedFileDataError < StandardError
19
+ def initialize(file_data)
20
+ super()
21
+ @file_data = file_data
22
+ end
23
+
24
+ def message
25
+ ''"
26
+ An error occured while uploading the file.
27
+ Data was: #{@file_data}
28
+ "''
29
+ end
30
+ end
31
+
32
+ class DownloadConnectionError < StandardError
33
+ def initialize(error_message)
34
+ super()
35
+ @error_message = error_message
36
+ end
37
+
38
+ def message
39
+ ''"
40
+ An error occured connection to Google Drive.
41
+ Error message was: #{@error_message}
42
+ "''
43
+ end
44
+ end
45
+
46
+ class MissingConfig < StandardError
47
+ def message
48
+ ''"
49
+ Please define a config for FileConvert.
50
+ See https://github.com/tolingo/file-convert#config for default.
51
+ "''
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,30 @@
1
+ module FileConvert
2
+ class File
3
+ attr_reader :original_file
4
+ attr_reader :data
5
+ attr_reader :conversions
6
+
7
+ ##
8
+ # Hold original and conversion
9
+ #
10
+ # @params [File] original_file
11
+ #
12
+ # @return [FileConvert::File]
13
+ def initialize(original_file)
14
+ @original_file = original_file
15
+ @data = original_file.data
16
+ @conversions = {}
17
+ end
18
+
19
+ ##
20
+ # Adds a new conversion
21
+ #
22
+ # @param [String] mime_type
23
+ # @param [File] converted_file
24
+ #
25
+ # @return [FileConvert::File] (self)
26
+ def add_conversion(mime_type, converted_file)
27
+ tap { @conversions[mime_type] = converted_file }
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,50 @@
1
+ module FileConvert
2
+ class Upload
3
+ DEFAULT_PARAMS = {
4
+ 'uploadType' => 'multipart',
5
+ 'convert' => true,
6
+ 'alt' => 'json'
7
+ }
8
+
9
+ attr_reader :file
10
+
11
+ ##
12
+ # Uploads file to Google Drive
13
+ #
14
+ # @param [FileConvert::Client] client
15
+ # @param [String] file_path
16
+ # File to upload
17
+ # @param [String] mime_type
18
+ # Source mime_type of upload-file
19
+ #
20
+ # @return [FileConvert::File] New File object without conversions yet
21
+ def initialize(client, file_path, mime_type)
22
+ @client = client
23
+ @file_path = file_path
24
+ @mime_type = mime_type
25
+
26
+ uploaded_file = client.execute(
27
+ api_method: client.drive.files.insert,
28
+ body_object: touch_file,
29
+ media: upload_io,
30
+ parameters: DEFAULT_PARAMS
31
+ )
32
+
33
+ @file = FileConvert::File.new(uploaded_file)
34
+ end
35
+
36
+ private
37
+
38
+ def touch_file
39
+ @client.drive.files.insert.request_schema.new(
40
+ 'title' => SecureRandom.uuid,
41
+ 'description' => 'FileConvert Conversion-File',
42
+ 'mimeType' => @mime_type
43
+ )
44
+ end
45
+
46
+ def upload_io
47
+ Google::APIClient::UploadIO.new(@file_path, @mime_type)
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,9 @@
1
+ module FileConvert
2
+ module Version
3
+ MAJOR = 0
4
+ MINOR = 0
5
+ TINY = 1
6
+
7
+ STRING = [MAJOR, MINOR, TINY].compact.join('.')
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,141 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: file-convert
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Roman Ernst
8
+ - Jan Raasch
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-09-01 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: google-api-client
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: 0.7.0
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: 0.7.0
28
+ - !ruby/object:Gem::Dependency
29
+ name: rspec
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: 3.0.0
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: 3.0.0
42
+ - !ruby/object:Gem::Dependency
43
+ name: rubocop
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: 0.25.0
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: 0.25.0
56
+ - !ruby/object:Gem::Dependency
57
+ name: rake
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: 10.3.2
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: 10.3.2
70
+ - !ruby/object:Gem::Dependency
71
+ name: pry
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: 0.10.1
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: 0.10.1
84
+ - !ruby/object:Gem::Dependency
85
+ name: codeclimate-test-reporter
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - "~>"
89
+ - !ruby/object:Gem::Version
90
+ version: 0.4.0
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: 0.4.0
98
+ description: Uses google-api-ruby-client and Google Drive to convert files from one
99
+ mime-type to another
100
+ email:
101
+ - rernst@farbenmeer.net
102
+ - jan@janraasch.com
103
+ executables: []
104
+ extensions: []
105
+ extra_rdoc_files: []
106
+ files:
107
+ - LICENSE
108
+ - README.md
109
+ - lib/file_convert.rb
110
+ - lib/file_convert/client.rb
111
+ - lib/file_convert/configure.rb
112
+ - lib/file_convert/conversion.rb
113
+ - lib/file_convert/exception.rb
114
+ - lib/file_convert/file.rb
115
+ - lib/file_convert/upload.rb
116
+ - lib/file_convert/version.rb
117
+ homepage: https://github.com/tolingo/file-convert
118
+ licenses:
119
+ - MIT
120
+ metadata: {}
121
+ post_install_message:
122
+ rdoc_options: []
123
+ require_paths:
124
+ - lib
125
+ required_ruby_version: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ version: 1.9.2
130
+ required_rubygems_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ requirements: []
136
+ rubyforge_project:
137
+ rubygems_version: 2.2.0.rc.1
138
+ signing_key:
139
+ specification_version: 4
140
+ summary: Instrumentalize Google Drive to convert files
141
+ test_files: []