undrive_google 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6309df259e4c0ec3a6853a2e2362a01a1ae21c92f9cf02254727318c084b3f47
4
+ data.tar.gz: ff5130695837c720b1ead438f3cfbcebc903ea8da2f78e3e9007295055984bdb
5
+ SHA512:
6
+ metadata.gz: df150a3aa25129d41bf43889b635627c03a33ce68884653de461e039595a0c7fa7592d0f96edd63287e4a5a834412c42b333d5e0ac1ec6dbb44858434493616a
7
+ data.tar.gz: 1e850de4f83df8be4b09cea304fde2448af115106767afd4241b049f8cf9347dcd1dc1e6936d15dc83fa789573bd7fe8855923945967d2c78f4c89b4152a7313
checksums.yaml.gz.sig ADDED
@@ -0,0 +1,3 @@
1
+ ��a�S������Y>J���^�V��Znӯ�v�?z�`��6����g9\0�N��7)n�
2
+ � �?����G� DP�c��+��<C�l�:�D4 ���PVp���>\��=o\�4�$?�"��Q<�Y�
3
+ Y곺��z�
data/CHANGELOG.md ADDED
@@ -0,0 +1,14 @@
1
+ # Changelog
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## Unreleased
8
+ ### Added
9
+ ### Changed
10
+ ### Fixed
11
+ ### Removed
12
+
13
+ ## 1.0.0 - 2022-10-24
14
+ - Initial release
@@ -0,0 +1,84 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
6
+
7
+ We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
8
+
9
+ ## Our Standards
10
+
11
+ Examples of behavior that contributes to a positive environment for our community include:
12
+
13
+ * Demonstrating empathy and kindness toward other people
14
+ * Being respectful of differing opinions, viewpoints, and experiences
15
+ * Giving and gracefully accepting constructive feedback
16
+ * Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
17
+ * Focusing on what is best not just for us as individuals, but for the overall community
18
+
19
+ Examples of unacceptable behavior include:
20
+
21
+ * The use of sexualized language or imagery, and sexual attention or
22
+ advances of any kind
23
+ * Trolling, insulting or derogatory comments, and personal or political attacks
24
+ * Public or private harassment
25
+ * Publishing others' private information, such as a physical or email
26
+ address, without their explicit permission
27
+ * Other conduct which could reasonably be considered inappropriate in a
28
+ professional setting
29
+
30
+ ## Enforcement Responsibilities
31
+
32
+ Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
33
+
34
+ Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
35
+
36
+ ## Scope
37
+
38
+ This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
39
+
40
+ ## Enforcement
41
+
42
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at peter.boling@gmail.com. All complaints will be reviewed and investigated promptly and fairly.
43
+
44
+ All community leaders are obligated to respect the privacy and security of the reporter of any incident.
45
+
46
+ ## Enforcement Guidelines
47
+
48
+ Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
49
+
50
+ ### 1. Correction
51
+
52
+ **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
53
+
54
+ **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
55
+
56
+ ### 2. Warning
57
+
58
+ **Community Impact**: A violation through a single incident or series of actions.
59
+
60
+ **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
61
+
62
+ ### 3. Temporary Ban
63
+
64
+ **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
65
+
66
+ **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
67
+
68
+ ### 4. Permanent Ban
69
+
70
+ **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
71
+
72
+ **Consequence**: A permanent ban from any sort of public interaction within the community.
73
+
74
+ ## Attribution
75
+
76
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0,
77
+ available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
78
+
79
+ Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
80
+
81
+ [homepage]: https://www.contributor-covenant.org
82
+
83
+ For answers to common questions about this code of conduct, see the FAQ at
84
+ https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,44 @@
1
+ ## Contributing
2
+
3
+ Bug reports are welcome on GitLab at [https://todo.sr.ht/~galtzo/undrive_google][bug-reports].
4
+ This project is intended to be a safe, welcoming space for collaboration, and
5
+ contributors are expected to adhere to the [code of conduct][conduct].
6
+
7
+ When you submit a patch, please include updated tests.
8
+ Send the patch to the [mailing list][⛳mail-list].
9
+ For help sending patches to this list, please consult [git-send-email.io][git-send-email].
10
+ Please review our mailing list [etiquette guide][mail-list-etiquette-guide]
11
+ and ensure your email client is
12
+ correctly configured before posting. Thanks!
13
+
14
+ No one has posted to this list yet.
15
+
16
+
17
+ ## Release
18
+
19
+ To release a new version:
20
+
21
+ 1. update the version number in `version.rb`
22
+ 2. run `bundle exec rake build:checksum`
23
+ 3. move the built gem to project root
24
+ 4. run `bin/checksum` to create the missing SHA256 checksum
25
+ 5. move the built gem back to `pkg/`
26
+ 6. run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org][rubygems].
27
+
28
+ NOTE: You will need to have a public key in `certs/`, and list your cert in the
29
+ `gemspec`, in order to sign the new release.
30
+ See: [RubyGems Security Guide][rubygems-security-guide]
31
+
32
+ ## Contributors
33
+
34
+ [![Contributors][🖐contributors-img]][🖐contributors]
35
+
36
+ [comment]: <> (Following links are used by README, CONTRIBUTING, Homepage)
37
+
38
+ [conduct]: https://git.sr.ht/~galtzo/undrive_google/tree/main/item/CODE_OF_CONDUCT.md
39
+ [bug-reports]: https://todo.sr.ht/~galtzo/undrive_google
40
+ [git-send-email]: https://git-send-email.io/
41
+ [⛳mail-list]: https://lists.sr.ht/~galtzo/undrive_google-devel
42
+ [mail-list-etiquette-guide]: https://man.sr.ht/lists.sr.ht/etiquette.md
43
+ [rubygems-security-guide]: https://guides.rubygems.org/security/#building-gems
44
+ [rubygems]: https://rubygems.org
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022 Peter Boling
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.
data/README.md ADDED
@@ -0,0 +1,189 @@
1
+ # UndriveGoogle
2
+
3
+ Toolkit for:
4
+ 1. Liberating variously formatted files from your Google Drive
5
+ 2. Applying a set of transformations to liberated files
6
+ * patterned rename
7
+ * unzip
8
+ * correct HTML errors
9
+ 3. Profit
10
+
11
+ Want to link directly to the Google-Drive-hosted alternate format of a file?
12
+ If yes, DO NOT use this gem. Instead follow [these instructions](https://support.google.com/a/users/answer/9308985?hl=en).
13
+
14
+ OTOH, if you want to "own", host, track, etc your 'own' files
15
+ (e.g. your resume), DO use this gem.
16
+
17
+ ## NOTE: Export epub
18
+
19
+ There is a bug (missing feature) in `google_drive` gem preventing export of epub. You can use this patched branch:
20
+
21
+ ```ruby
22
+ gem "google_drive", github: "pboling/google-drive-ruby", branch: "pboling-epub-mimetype"
23
+ ```
24
+
25
+ And you can upvote this PR [#427](https://github.com/gimite/google-drive-ruby/pull/427).
26
+
27
+ ## Story Time
28
+
29
+ Imagine Google Drive is a 🐭
30
+ Imagine your file (e.g. resume) is a 🍪
31
+ 🐭's 🍪 exporter: 🖨
32
+
33
+ Tell me if you've heard this one already.
34
+
35
+ 1. Give 🐭 your 🍪 for "safe-keeping"
36
+ 2. Recognizing this SPoF, you ask 🐭 to give back a 🍪 copy
37
+ 3. "I'll run it through my 🍪 🖨", says 🐭
38
+ 4. 🖨 replicates various 🍪 extensions: `pdf`, `odt`, `docx`, `txt`, `rtf` and `epub`
39
+ 5. Rename 🍪 for web (e.g. replace ` ` with `_`)
40
+ 6. Extract replicated `.zip` format to `.html`
41
+ 7. Rename extracted HTML file for self-hosting
42
+ 8. Realize 🐭's HTML is invalid
43
+ 9. Fix 🐭's broke-ass (missing `lang` attribute and `title` element)
44
+ 10. Upload 🍪 to your website (you're on your own for this part)
45
+ 11. Finally Finished!
46
+ 12. Find mistakes 😭
47
+ 13. Bake a new 🍪
48
+ 14. GOTO 1
49
+
50
+ This gem solves the classic 🐭-🍪 problem by automating steps 3-8.
51
+ Will save at least 15 minutes each loop.
52
+
53
+ TODO:
54
+ Configuration supports step 9, but it hasn't been implemented yet.
55
+
56
+ Note that it doesn't have to be a resume.
57
+ There are likely other use cases that apply.
58
+
59
+ ## Installation
60
+
61
+ Install the gem and add to the application's Gemfile by executing:
62
+
63
+ $ bundle add undrive_google
64
+
65
+ If bundler is not being used to manage dependencies, install the gem by executing:
66
+
67
+ $ gem install undrive_google
68
+
69
+ ## Usage
70
+
71
+ Revisiting the original story...
72
+
73
+ 1. Give 🐭 your 🍪 for "safe-keeping"
74
+ 2. Recognizing this SPoF, you ask 🐭 to give back a 🍪 copy
75
+ 3. Run:
76
+ ```shell
77
+ undrive_google
78
+ ```
79
+ 4. Upload 🍪 to your website (you're on your own for this part)
80
+ 5. Finally Finished!
81
+ 6. Find mistakes 😭
82
+ 7. Bake a new 🍪
83
+ 8. GOTO 1
84
+
85
+ In order for the fantasy above to be realized,
86
+ you must to a bit of initial configuration, but you already knew that.
87
+
88
+ ## Configuration
89
+
90
+ You'll probably want to follow [these (outdated) steps](https://github.com/gimite/google-drive-ruby/blob/master/doc/authorization.md#on-behalf-of-no-existing-users-service-account)
91
+ to create a service account.
92
+
93
+ At the end of the process a `[siteid]-[first-12-chars-of-key].json` file will be
94
+ downloaded to your computer. **DO NOT EXPOSE THE KEY**, i.e. do not push it
95
+ to any public source repository.
96
+
97
+ When you run the `undrive_google` command this JSON key file should be in the
98
+ current directory.
99
+
100
+ Additionally, an optional `undrive_google.yml` file in the
101
+ current directory can give you control over the behavior.
102
+
103
+ What goes in the `undrive_google.yml` file?
104
+
105
+ ### Default: Liberate All Formats
106
+
107
+ All non-commented values shown are default.
108
+ ```yaml
109
+ # [PATH] Path to the JSON file with Google Service Account Key
110
+ key_file: 'service_account_private_key.json'
111
+
112
+ # ID of file to liberate, as key or title
113
+ file_id: '<actual-key-or-title>'
114
+ file_by: 'key' # or 'title'
115
+
116
+ # [String, Array<String>] Which extensions to download?
117
+ extensions: 'all'
118
+
119
+ # [Boolean] The HTML format download comes as a .zip archive.
120
+ # Want the .zip unzipped? (only relevant if extensions is `all`, or includes `zip`)
121
+ unzip: true
122
+ # [Boolean] Keep the .zip after extracting the `.html`?
123
+ keep_zip: true
124
+
125
+ # Rename downloaded files?
126
+ # rename_<type>, where type is:
127
+ # 1. a downloadable format name, like `odt`, `docx`, `pdf`, etc
128
+ # 2. html (which isn't downloadable, has to be unzipped from .zip)
129
+ # e.g.
130
+ # rename_html: 'resume.html'
131
+
132
+ # Rename downloaded files following a pattern?
133
+ # Only applies to files not explicitly specified with rename-<type>
134
+ # Value will be splatted to gsub
135
+ rename_pattern:
136
+ - "_"
137
+ - " "
138
+
139
+ # [PATH]
140
+ dir: '' # defaults to current working directory
141
+
142
+ verbose: true # or false
143
+
144
+ #
145
+ # TODO: implementation for title and lang
146
+ #
147
+ # [String] HTML title element inner text.
148
+ title: '' # When empty, defaults to the title of the file.
149
+
150
+ # [String] If unzipping `.zip`, adds lang attribute to html tag,
151
+ # value is like `fr`, `es`, etc.
152
+ lang: 'en'
153
+ ```
154
+
155
+ ### Example: Liberate Specific Formats (keeping other defaults)
156
+
157
+ In this example we choose to download only the `odt`, `txt`, and `epub` extensions,
158
+ and leave the remaining settings as default, except for `title`.
159
+
160
+ ```yaml
161
+ # [String, Array<String>] Which extensions to download?
162
+ extensions:
163
+ - 'odt'
164
+ - 'txt'
165
+ - 'epub'
166
+
167
+ title: 'My Cool HTML'
168
+ ```
169
+
170
+ ## Development
171
+
172
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
173
+
174
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
175
+
176
+ ## Contributing
177
+
178
+ Bug reports are welcome on Source Hut at [https://todo.sr.ht/~galtzo/undrive_google](https://todo.sr.ht/~galtzo/undrive_google).
179
+ Patches are welcome on Source Hut at [https://lists.sr.ht/~galtzo/undrive_google-devel](https://lists.sr.ht/~galtzo/undrive_google-devel)
180
+ This project is intended to be a safe, welcoming space for collaboration,
181
+ and contributors are expected to adhere to the [code of conduct](https://git.sr.ht/~galtzo/undrive_google/tree/main/item/CODE_OF_CONDUCT.md).
182
+
183
+ ## License
184
+
185
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
186
+
187
+ ## Code of Conduct
188
+
189
+ Everyone interacting in the UndriveGoogle project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://git.sr.ht/~galtzo/undrive_google/tree/main/item/CODE_OF_CONDUCT.md).
data/SECURITY.md ADDED
@@ -0,0 +1,25 @@
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ | Version | Supported | EOL | Post-EOL / Enterprise |
6
+ |---------|-----------|---------|---------------------------------------|
7
+ | 1.0.x | ✅ | 04/2025 | [Tidelift Subscription][tidelift-ref] |
8
+
9
+ ### EOL Policy
10
+
11
+ Non-commercial support for the oldest version of Ruby (which itself is going EOL) will be dropped each year in April.
12
+
13
+ ## Reporting a Vulnerability
14
+
15
+ To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security).
16
+ Tidelift will coordinate the fix and disclosure.
17
+
18
+ ## UndriveGoogle for Enterprise
19
+
20
+ Available as part of the Tidelift Subscription.
21
+
22
+ The maintainers of undrive_google and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications
23
+ Save time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use. [Learn more.][tidelift-ref]
24
+
25
+ [tidelift-ref]: https://tidelift.com/subscription/pkg/rubygems-undrive_google?utm_source=rubygems-undrive_google&utm_medium=referral&utm_campaign=enterprise&utm_term=repo
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Std-lib
5
+ require "optparse"
6
+
7
+ # Gems
8
+ require "bundler/setup"
9
+ require "byebug"
10
+
11
+ # This library
12
+ require "undrive_google"
13
+
14
+ cli = UndriveGoogle::CLI.instance
15
+ cli.parse(ARGV)
16
+ cli.liberate!
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UndriveGoogle
4
+ module Actions
5
+ # Download a particular version of the file.
6
+ class Download
7
+ attr_accessor :file, :extension, :dir
8
+
9
+ def initialize(extension)
10
+ @file = Session.instance.file
11
+ @extension = extension.to_s
12
+ @dir = Options.instance.dir
13
+ end
14
+
15
+ def download!
16
+ puts "Downloading #{file.title} as: #{extension} to: #{dir}/#{name}" if Options.instance.verbose
17
+ file.export_as_file("#{dir}/#{name}", extension)
18
+ end
19
+
20
+ private
21
+
22
+ def name
23
+ "#{rename}.#{extension}"
24
+ end
25
+
26
+ def rename
27
+ exact_name = Options.instance.rename[extension]
28
+ return exact_name if exact_name
29
+
30
+ Options.instance.rename_proc.call(file.title)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UndriveGoogle
4
+ # A file on Google Drive
5
+ class CaptiveFile
6
+ include Singleton
7
+ attr_accessor :options, :exports
8
+
9
+ # @return nil
10
+ def liberate!
11
+ @exports = []
12
+ extensions.each do |format|
13
+ download = Actions::Download.new(format)
14
+ exports << download
15
+ download.download!
16
+ end
17
+
18
+ nil
19
+ end
20
+
21
+ private
22
+
23
+ def extensions
24
+ Options.instance.extensions
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UndriveGoogle
4
+ # Defines the CLI behavior & provides the Google Drive Session
5
+ class CLI
6
+ include Singleton
7
+ attr_reader :parser, :options, :session
8
+
9
+ # Options specified on the command line are collected in *@options*.
10
+ #
11
+ # @param [ARGV] args
12
+ # @return nil
13
+ def parse(args)
14
+ @options = Options.instance
15
+ @parser = OptionParser.new do |parser|
16
+ @options.define_options(parser)
17
+ parser.parse!(args)
18
+ end
19
+ raise UndriveGoogle::Error, "file_id is required!" unless options.file_id
20
+ raise UndriveGoogle::Error, "dir is required!" unless options.dir
21
+
22
+ @session = Session.instance
23
+
24
+ nil
25
+ end
26
+
27
+ def liberate!
28
+ session.file
29
+ CaptiveFile.instance.liberate!
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UndriveGoogle
4
+ # Represents the YAML config file for this gem
5
+ class ConfigFile
6
+ DEFAULT = {}.freeze
7
+
8
+ attr_accessor :args
9
+
10
+ def initialize(path)
11
+ @args = config_file(path)
12
+
13
+ validate(@args)
14
+
15
+ return if @args == DEFAULT
16
+
17
+ rename_keys = (@args.keys - [:rename_pattern]).select { |k| k.start_with?("rename") }
18
+ if rename_keys.any?
19
+ @args[:rename] = rename_keys.each_with_object({}) do |k, rename|
20
+ key = k.to_s.sub("rename_", "")
21
+ rename[key.to_sym] = @args.delete(k.to_sym)
22
+ end
23
+ end
24
+ @args[:extensions] = Helpers::Parse.extensions(@args[:extensions]) if key?(:extensions)
25
+ rename_pattern = @args.delete(:rename_pattern)
26
+ @args[:rename_proc] = Helpers::Parse.rename_proc(rename_pattern) if rename_pattern
27
+ end
28
+
29
+ def [](val)
30
+ args[val]
31
+ end
32
+
33
+ def key?(k)
34
+ args.key?(k)
35
+ end
36
+
37
+ def any?
38
+ args.keys.any?
39
+ end
40
+
41
+ private
42
+
43
+ def config_file(path)
44
+ return DEFAULT unless File.exist?(path)
45
+
46
+ Psych.load_file(path, symbolize_names: true, fallback: DEFAULT)
47
+ end
48
+
49
+ def validate(config)
50
+ unknown = config.keys - YAML_KEYS
51
+ unknown.reject! { |key| key.start_with?("rename") }
52
+ return if unknown.empty?
53
+
54
+ raise UndriveGoogle::Error, "Unhandled config keys #{unknown.inspect}"
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UndriveGoogle
4
+ module Helpers
5
+ # Config Parsing Helpers
6
+ module Parse
7
+ module_function
8
+
9
+ def extensions(val)
10
+ if val.is_a?(Array)
11
+ unknown = val.map(&:to_sym) - FILE_TYPES
12
+ raise UndriveGoogle::Error, "Unknown extensions: #{unknown}" if unknown.any?
13
+
14
+ val
15
+ elsif val == "all"
16
+ FILE_TYPES
17
+ elsif FILE_TYPES.include?(val.to_sym)
18
+ [val]
19
+ else
20
+ raise UndriveGoogle::Error, "Unknown extensions: #{val}"
21
+ end
22
+ end
23
+
24
+ def rename_proc(val)
25
+ raise UndriveGoogle::Error, "invalid rename pattern #{val}" unless val.length == 2
26
+
27
+ pattern = Regexp.new(val[0])
28
+ replace = val[1]
29
+ ->(orig) { orig.gsub(pattern, replace) }
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,159 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UndriveGoogle
4
+ # Combine defaults with YAML and CLI provided options
5
+ class Options
6
+ include Singleton
7
+
8
+ attr_accessor :config_yaml, :key_file, :file_id, :file_by, :extensions, :unzip,
9
+ :keep_zip, :rename, :rename_proc, :lang, :title,
10
+ :dir, :verbose
11
+
12
+ def initialize
13
+ self.config_yaml = CONFIG_YAML_PATH
14
+ self.key_file = KEY_FILE_PATH
15
+ self.file_id = nil
16
+ self.file_by = :key
17
+ self.extensions = FILE_TYPES # On the command line, "all" expands to FILE_TYPES
18
+ self.unzip, self.keep_zip = true
19
+ self.rename = {}
20
+ self.rename_proc = RENAME_PROC
21
+ self.title, self.dir = nil
22
+ self.lang = "en"
23
+ self.verbose = false
24
+ load_yaml
25
+ end
26
+
27
+ def define_options(parser)
28
+ parser.banner = "Usage: undrive_google [options]"
29
+ parser.separator ""
30
+
31
+ # Handle YAML, as default overrides
32
+ config_yaml_option(parser)
33
+
34
+ # ARGV will override the defaults and YAML values
35
+ key_file_option(parser)
36
+ file_id_option(parser)
37
+ by_option(parser)
38
+ extensions_option(parser)
39
+ unzip_option(parser)
40
+ keep_zip_option(parser)
41
+ rename_options(parser)
42
+ dir_option(parser)
43
+ lang_option(parser)
44
+ title_option(parser)
45
+ verbose_option(parser)
46
+
47
+ parser.separator ""
48
+
49
+ # Print an options summary.
50
+ parser.on_tail("-h", "--help", "Show this message") do
51
+ puts parser
52
+ exit
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ # CLI options will take precedence over values in YAML
59
+ def config_yaml_option(parser)
60
+ parser.on("-c", "--config-yaml PATH", String,
61
+ "Path to UndriveGoogle config YAML file") do |config_yaml|
62
+ self.config_yaml = config_yaml
63
+ load_yaml
64
+ end
65
+ end
66
+
67
+ def key_file_option(parser)
68
+ parser.on("-k", "--key-file PATH", String,
69
+ "Path to Google Service Account Keys JSON file") do |key_file|
70
+ self.key_file = key_file
71
+ end
72
+ end
73
+
74
+ def file_id_option(parser)
75
+ parser.on("-i", "--file-id ID", String,
76
+ "ID used to find file (key or title)") do |file_id|
77
+ self.file_id = file_id
78
+ end
79
+ end
80
+
81
+ def by_option(parser)
82
+ parser.on("-b", "--file-by [TYPE]", %i[key title],
83
+ "Select type of ID used to find file (key, title)") do |file_by|
84
+ self.file_by = file_by
85
+ end
86
+ end
87
+
88
+ def extensions_option(parser)
89
+ # List of arguments.
90
+ parser.on("-e", "--extensions x,y,z", Array, "Formats to liberate (export/download)") do |extensions|
91
+ self.extensions = Helpers::Parse.extensions(extensions)
92
+ end
93
+ end
94
+
95
+ def unzip_option(parser)
96
+ # Boolean switch.
97
+ parser.on("-u", "--[no-]unzip", "Unzip liberated .zip") do |unzip|
98
+ self.unzip = unzip
99
+ end
100
+ end
101
+
102
+ def keep_zip_option(parser)
103
+ # Boolean switch.
104
+ parser.on("-z", "--[no-]keep-zip", "Keep liberated .zip after unzipping") do |keep_zip|
105
+ self.keep_zip = keep_zip
106
+ end
107
+ end
108
+
109
+ def rename_options(parser)
110
+ (FILE_TYPES + [:html]).each do |ft|
111
+ parser.on("--rename-#{ft} [FILENAME]", "Rename #{ft} to FILENAME") do |rename|
112
+ self.rename[ft] = rename
113
+ end
114
+ end
115
+ parser.on("--rename-pattern pattern,replace", Array, "Rename other files with gsub(pattern, replace)") do |arr|
116
+ self.rename_proc = Helpers::Parse.rename_proc(arr)
117
+ end
118
+ end
119
+
120
+ def dir_option(parser)
121
+ parser.on("-d", "--dir PATH", String,
122
+ "Path to directory where liberated files will go") do |dir|
123
+ self.dir = dir
124
+ end
125
+ end
126
+
127
+ def lang_option(parser)
128
+ parser.on("-l", "--lang LANG", String, '[NOOP] TODO: Add lang="LANG" attribute to HTML') do |lang|
129
+ self.lang = lang
130
+ end
131
+ end
132
+
133
+ def title_option(parser)
134
+ parser.on("-t", "--title TITLE", String, "[NOOP] TODO: Add <title>TITLE</title> element to HTML") do |title|
135
+ self.title = title
136
+ end
137
+ end
138
+
139
+ def verbose_option(parser)
140
+ # Boolean switch.
141
+ parser.on("-v", "--[no-]verbose", "Run verbosely") do |v|
142
+ self.verbose = v
143
+ end
144
+ end
145
+
146
+ def load_yaml
147
+ return unless config_yaml
148
+
149
+ cf = ConfigFile.new(config_yaml)
150
+ return unless cf.any?
151
+
152
+ (YAML_KEYS - [:rename_pattern]).each do |key|
153
+ send("#{key}=", cf[key]) if cf.key?(key)
154
+ end
155
+ self.rename = cf[:rename] if cf.key?(:rename)
156
+ self.rename_proc = cf[:rename_proc] if cf.key?(:rename_proc)
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UndriveGoogle
4
+ # A Google Drive Session
5
+ class Session
6
+ include Singleton
7
+
8
+ attr_reader :drive_session
9
+
10
+ def initialize
11
+ @drive_session = GoogleDrive::Session.from_service_account_key(Options.instance.key_file)
12
+ raise UndriveGoogle::Error, "no file_id" unless Options.instance.file_id
13
+ end
14
+
15
+ def file
16
+ @file ||= drive_session.send(file_by, Options.instance.file_id)
17
+ end
18
+
19
+ private
20
+
21
+ def file_by
22
+ return :file_by_title if Options.instance.file_by == FILE_BY[:title]
23
+
24
+ :file_by_id
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UndriveGoogle
4
+ module Version
5
+ VERSION = "1.0.0"
6
+ end
7
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Std-lib
4
+ require "psych" # The Ruby YAML library
5
+ require "singleton" # The Ruby Singleton library
6
+
7
+ # third party gems
8
+ require "version_gem"
9
+ require "google_drive"
10
+
11
+ require_relative "undrive_google/version"
12
+
13
+ require_relative "undrive_google/actions/download"
14
+ require_relative "undrive_google/helpers/parse"
15
+ require_relative "undrive_google/captive_file"
16
+ require_relative "undrive_google/cli"
17
+ require_relative "undrive_google/config_file"
18
+ require_relative "undrive_google/options"
19
+ require_relative "undrive_google/session"
20
+
21
+ module UndriveGoogle
22
+ class Error < StandardError; end
23
+
24
+ FILE_BY = {
25
+ title: :title,
26
+ key: :key
27
+ }.freeze
28
+ FILE_TYPES = %i[docx odt rtf pdf txt zip epub].freeze
29
+ RENAME_PROC = ->(orig) { orig.tr(" ", "_") }
30
+ YAML_KEYS = %i[
31
+ key_file
32
+ file_id
33
+ file_by
34
+ extensions
35
+ unzip
36
+ keep_zip
37
+ rename_pattern
38
+ title
39
+ dir
40
+ lang
41
+ verbose
42
+ ].freeze
43
+ CONFIG_YAML_PATH = "undrive_google.yaml"
44
+ KEY_FILE_PATH = "service_account_private_key.json"
45
+ end
46
+
47
+ UndriveGoogle::Version.class_eval do
48
+ extend VersionGem::Basic
49
+ end
data.tar.gz.sig ADDED
Binary file
metadata ADDED
@@ -0,0 +1,159 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: undrive_google
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Peter Boling
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIEgDCCAuigAwIBAgIBATANBgkqhkiG9w0BAQsFADBDMRUwEwYDVQQDDAxwZXRl
14
+ ci5ib2xpbmcxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkW
15
+ A2NvbTAeFw0yMjA5MTgyMzEyMzBaFw0yMzA5MTgyMzEyMzBaMEMxFTATBgNVBAMM
16
+ DHBldGVyLmJvbGluZzEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPy
17
+ LGQBGRYDY29tMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA2Dn1GM3W
18
+ 8K2/rvN1zz+06bQMcxD16ZKTihVwi7Pb1v3T98rM4Omnxohm3s+CwpDWGeiB9pj6
19
+ 0I/CTce0e4e3s8GKJSOrg93veImPSoH2PfsMsRsuB8wtqyiOCjLbF5o6S29x87r0
20
+ LA5EawH+Lh4xqrkkPjdffsmLk7TaCig/vlmNvnzxXKBdey/X/aEJZXzzBiWRfVdh
21
+ O1fmMbVKyieGv9HK7+pLotIoT08bjDv8NP6V7zZslwQRqW27bQc6cqC2LGIbTYO3
22
+ 3jt1kQxfMWmhOictS6SzG9VtKSrXf0L4Neq0Gh7CLBZBvJFWJYZPfb92YNITDbd8
23
+ emPOAQlXXNMN4mMXsEqtEhCPZRMnmwO+fOk/cC4AyglKi9lnQugCQoFV1XDMZST/
24
+ CYbzdQyadOdPDInTntG6V+Uw51d2QGXZ6PDDfrx9+toc/3sl5h68rCUGgE6Q3jPz
25
+ srinqmBsxv2vTpmd4FjmiAtEnwH5/ooLpQYL8UdAjEoeysxS3AwIh+5dAgMBAAGj
26
+ fzB9MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBQWU6D156a2cle+
27
+ lb5RBfvVXlxTwjAhBgNVHREEGjAYgRZwZXRlci5ib2xpbmdAZ21haWwuY29tMCEG
28
+ A1UdEgQaMBiBFnBldGVyLmJvbGluZ0BnbWFpbC5jb20wDQYJKoZIhvcNAQELBQAD
29
+ ggGBAJ4SqhPlgUiLYIrphGXIaxXScHyvx4kixuvdrwhI4VoQV2qXvO7R6ZjOXVwX
30
+ f/z84BWPiTZ8lzThPbt1UV/BGwkvLw9I4RjOdzvUz3J42j9Ly6q63isall07bo3F
31
+ QWe/OBvIMBF1IbjC3q5vKPg4rq8+TkNRJNoE86U2gfR+PkW3jYYs9uiy0GloHDCP
32
+ k5xgaj0vSL0Uy5mTOPdk3K6a/sUGZyYniWK05zdhIi956ynhfGaFO988FFdVw5Jq
33
+ LHtXfIpAU8F7ES04syZSslxOluw7VlcSKyRdVIr737J92ZTduppB4PRGSKRgBsWV
34
+ hXTahRE72Kyw53Q7FAuzF3v102WxAAQ7BuMjW+MyCUT75fwPm3W4ELPL8HYkNGE7
35
+ 2oA5CPghFitRnvYS3GNrDG+9bNiRMEskeaBYwZ9UgReBQIwGYVj7LZk3UhiAsn44
36
+ gwGrEXGQGDZ0NIgBcmvMOqlXjkGQwQvugKycJ024z89+fz2332vdZIKTrSxJrXGk
37
+ 4/bR9A==
38
+ -----END CERTIFICATE-----
39
+ date: 2022-10-25 00:00:00.000000000 Z
40
+ dependencies:
41
+ - !ruby/object:Gem::Dependency
42
+ name: google_drive
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: version_gem
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.1'
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: 1.1.1
65
+ type: :runtime
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - "~>"
70
+ - !ruby/object:Gem::Version
71
+ version: '1.1'
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: 1.1.1
75
+ - !ruby/object:Gem::Dependency
76
+ name: rspec-block_is_expected
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: rubocop-lts
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '22.0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '22.0'
103
+ description: "\U0001F3F4 Liberate files from your Google Drive with transformations"
104
+ email:
105
+ - peter.boling@gmail.com
106
+ executables:
107
+ - undrive_google
108
+ extensions: []
109
+ extra_rdoc_files: []
110
+ files:
111
+ - CHANGELOG.md
112
+ - CODE_OF_CONDUCT.md
113
+ - CONTRIBUTING.md
114
+ - LICENSE.txt
115
+ - README.md
116
+ - SECURITY.md
117
+ - exe/undrive_google
118
+ - lib/undrive_google.rb
119
+ - lib/undrive_google/actions/download.rb
120
+ - lib/undrive_google/captive_file.rb
121
+ - lib/undrive_google/cli.rb
122
+ - lib/undrive_google/config_file.rb
123
+ - lib/undrive_google/helpers/parse.rb
124
+ - lib/undrive_google/options.rb
125
+ - lib/undrive_google/session.rb
126
+ - lib/undrive_google/version.rb
127
+ homepage: https://sr.ht/~galtzo/undrive_google/
128
+ licenses:
129
+ - MIT
130
+ metadata:
131
+ homepage_uri: https://sr.ht/~galtzo/undrive_google/
132
+ source_code_uri: https://git.sr.ht/~galtzo/undrive_google
133
+ changelog_uri: https://git.sr.ht/~galtzo/undrive_google
134
+ bug_tracker_uri: https://todo.sr.ht/~galtzo/undrive_google
135
+ documentation_uri: https://www.rubydoc.info/gems/undrive_google/1.0.0
136
+ wiki_uri: https://man.sr.ht/~galtzo/undrive_google/
137
+ funding_uri: https://liberapay.com/pboling
138
+ mailing_list_uri: https://lists.sr.ht/~galtzo/undrive_google-devel
139
+ rubygems_mfa_required: 'true'
140
+ post_install_message:
141
+ rdoc_options: []
142
+ require_paths:
143
+ - lib
144
+ required_ruby_version: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ version: '3.1'
149
+ required_rubygems_version: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ requirements: []
155
+ rubygems_version: 3.3.24
156
+ signing_key:
157
+ specification_version: 4
158
+ summary: "\U0001F3F4 Liberate files from your Google Drive"
159
+ test_files: []
metadata.gz.sig ADDED
Binary file