pcloud_api 0.2.3 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fcef0e50f4deec3483d2ce4f23882a453ed3cea1fac57ef507ee1523824aba33
4
- data.tar.gz: 287a6037d5f81652a936d611a69cd2b40dd4ce5cdfbde03093242e0bcc7e061a
3
+ metadata.gz: 45e0e46ad9b58dd65f1ce2674c247fd72377fcb376bec9bdc29b3cb285216519
4
+ data.tar.gz: 25a81544a107633c7c3c4459a1ab0f3e7c1a4c6092d5231b59a22ccbce55bb9b
5
5
  SHA512:
6
- metadata.gz: b9cc930698584cfebe1fbb501798cb15ccb8116e8d231f632c30813f37bc0912550cee1d3bcdfee66fd21add00e8d2874b8471173ca4c77b67a544b7efe2740a
7
- data.tar.gz: ecdc92c74476eaed41515b5206d5c428f17fcddf870cd28f162fd382ba97abd11d095ef36ded8f155a188a36fe7a32afc4703df7275a779ec37628281de3da58
6
+ metadata.gz: dd0a131f94f7aec6ec700ad46ade522d37248d5475a23290d46b20f51025a5fd4043ccaf642fecdaeb387ef3cc85811282d0a52436dca6bdab1d8cbf23927211
7
+ data.tar.gz: 7597d199d6795c480d0b346ed021845993ad3f0bdd01fa9e6df1b129324c12c61dc181fa36f8990d85916016330d389413e6b6bdbeabb373c455e1ff4f3a1dfb
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  ## 0.2.3 2021-12-14
2
2
 
3
+ **Changes**
4
+ 1. You can now specify `recursive: true` on `Pcloud::Folder#find` and `Pcloud::Folder#find_by` methods to load all the folders contents recursively. Note that this may result in long request times for folders with many items in them.
5
+ 2. You can now configure the pCloud API read and connect timeouts via a new `timeout_seconds` argument to `Pcloud::Client.configure()`. The previous way to set this value via a `PCLOUD_API_TIMEOUT_SECONDS` environment variable continues to work as before.
6
+
7
+ ## 0.2.3 2021-12-14
8
+
3
9
  **Changes**
4
10
  1. `Pcloud::File`'s `upload` method no longer requires a `:filename` param, since pCloud just reads it off of the file object and ignores the param anyway
5
11
  2. Both `Pcloud::File` and `Pcloud::Folder`'s `update` and `update!` methods now allow either partial paths _(starting and ending with slashes)_ or full paths. This is a little more dangerous if you specify a full path and you meant partial, but it's a reasonable use case to support.
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![Gem Version](https://badge.fury.io/rb/pcloud_api.svg)](https://badge.fury.io/rb/pcloud_api)
5
5
  [![Gem Downloads](https://badgen.net/rubygems/dt/pcloud_api)](https://rubygems.org/gems/pcloud_api)
6
6
 
7
- The `pcloud_api` gem provides an intuitive Ruby interface for interacting with the [pCloud API](https://docs.pcloud.com/) using OAuth2. This gem does not attempt to replicate the entire functionality of the pCloud API but rather to provide quick and easy access for its most basic and common functionality. If you are looking for a lower-level pCloud API wrapper, [`pcloud`](https://github.com/7urkm3n/pcloud) might be a better fit for you.
7
+ The `pcloud_api` gem provides an intuitive Ruby interface for interacting with the [pCloud API](https://docs.pcloud.com/) using OAuth2. This gem does not attempt to replicate the entire functionality of the pCloud API but rather to provide quick and easy access for its most important functionality. If you are looking for a lower-level pCloud API wrapper, [`pcloud`](https://github.com/7urkm3n/pcloud) might be a better fit for you.
8
8
 
9
9
  ## Installation
10
10
 
@@ -41,6 +41,7 @@ The `Pcloud::Client` can be configured by directly calling the `Pcloud::Client.c
41
41
  Pcloud::Client.configure(
42
42
  access_token: "your-pcloud-app-access-token",
43
43
  data_region: "EU"
44
+ timeout_seconds: 8 # optional integer, defaults to 8 seconds if not specified
44
45
  )
45
46
  ```
46
47
 
@@ -55,8 +56,12 @@ The `Pcloud::File` API includes:
55
56
  # Find files by file :id or :path:
56
57
  Pcloud::File.find(1)
57
58
  Pcloud::File.find_by(path: "/images/jack_the_cat.jpg")
58
- # NOTE: `find_by` can also be used with :id, though this will take precedence
59
- # over :path so just pick one or the other
59
+ # NOTES:
60
+ # - `find_by` can also be used with :id, though this will take precedence over
61
+ # :path so pick only one or the other
62
+ # - Both `find` and `find_by` take an optional `recursive: true` argument which
63
+ # will recursively load all the folders contents. NOTE: this may result in
64
+ # long request times for folders with many items in them.
60
65
 
61
66
  # Check if a file exists by :id
62
67
  Pcloud::File.exists?(1)
@@ -106,8 +111,9 @@ The `Pcloud::Folder` API is very similar:
106
111
  # Find folders by folder :id or :path:
107
112
  Pcloud::Folder.find(1)
108
113
  Pcloud::Folder.find_by(path: "/images")
109
- # NOTE: `find_by` can also be used with :id, though this will take precedence
110
- # over :path so just pick one or the other
114
+ # NOTES:
115
+ # - `find_by` can also be used with :id, though this will take precedence over :path so pick only one or the other
116
+ # - When using :path the folder object will have a `path` value, when finding by :id, `path` will be `nil`
111
117
 
112
118
  # Check if a folder exists by id
113
119
  Pcloud::Folder.exists?(1)
@@ -147,12 +153,12 @@ jack_images.parent_folder
147
153
  jack_images.contents
148
154
  ```
149
155
 
150
- **Aside: path vs id**
156
+ **Params: path vs id**
151
157
 
152
- pCloud recommends using the `folder_id`, `parent_folder_id` or `file_id` params for API calls whenever possible, rather using an exact path. Folder and file ids are static, so this will make your code less brittle to changes in the file/folder tree. You can simply look up the id for a folder in the console ahead of time and then set it in your code, similar to how you would specify an AWS S3 bucket.
158
+ pCloud recommends using the `folder_id`, `parent_folder_id` or `file_id` params for API calls whenever possible, rather than using an exact path. Folder and file ids are static, so this will make your code less brittle to changes in the file/folder tree. You can simply look up the id for a folder in the console ahead of time and then set it in your code, similar to how you would specify an AWS S3 bucket. Note that when finding by one of these id values, the `path` value of a folder will come back as `nil`.
153
159
 
154
160
 
155
- **Aside: off-label client use**
161
+ **Off-label client use**
156
162
 
157
163
  The `Pcloud::File` and `Pcloud::Folder` APIs cover the most important, common functionality developers will want to access in a way that is easy to use without much onboarding. If you find that you still need to access other parts of the pCloud API that are not included in this gem yet, you can try calling other methods specified in [the pCloud API docs](https://docs.pcloud.com/) by interacting directly with the `Pcloud::Client`:
158
164
  ```ruby
@@ -160,6 +166,78 @@ Pcloud::Client.execute("listrevisions", query: { fileid: 90000 })
160
166
  ```
161
167
  _(There are a few methods on the raw pCloud API that require manual login, which this gem does not yet support. If you find that you need access to these methods you may wish to look at using the [`pcloud`](https://github.com/7urkm3n/pcloud) gem instead.)_
162
168
 
169
+ ### Example uses
170
+
171
+ In addition to the API docs above, here are some real-world ideas of how you might use the `pcloud_api` gem in a project. Feel free to submit a PR if you have an example that you think others would benefit from as well!
172
+
173
+ Upload a file from form params in Rails:
174
+ ```ruby
175
+ Pcloud::File.upload(
176
+ path: "/Jack",
177
+ file: File.open(params[:file].path)
178
+ )
179
+ ```
180
+
181
+ Backup a database for a local script:
182
+ ```ruby
183
+ Pcloud::File.upload(
184
+ folder_id: PCLOUD_FOLDER_ID,
185
+ filename: LOCAL_DB_FILENAME,
186
+ file: File.open("./#{LOCAL_DB_FILENAME}")
187
+ )
188
+ ```
189
+
190
+ Archive old state files and upload a new file for today:
191
+ ```ruby
192
+ # NOTE: This will overwrite existing archive files for each day such that
193
+ # there is only ever one database file stored per day.
194
+ Pcloud::Folder.find(PCLOUD_FOLDER_ID)
195
+ .contents
196
+ .filter { |item| item.is_a?(Pcloud::File) }
197
+ .filter { |file| file.name.match?(PCLOUD_STATE_FILE_REGEX) }
198
+ .each do |file|
199
+ file.update(
200
+ name: "#{file.created_at.strftime("%Y_%m_%d")}_#{file.name}",
201
+ parent_folder_id: PCLOUD_ARCHIVE_FOLDER_ID
202
+ )
203
+ end
204
+
205
+ Pcloud::File.upload(
206
+ folder_id: PCLOUD_FOLDER_ID,
207
+ filename: LOCAL_DB_FILENAME,
208
+ file: File.open("./#{LOCAL_DB_FILENAME}")
209
+ )
210
+ ```
211
+
212
+ Safely download previous state files for a local script:
213
+ ```ruby
214
+ Pcloud::Folder.find(PCLOUD_FOLDER_ID)
215
+ .contents
216
+ .filter { |item| item.is_a?(Pcloud::File) }
217
+ .filter { |file| file.name.match?(PCLOUD_STATE_FILE_REGEX) }
218
+ .each do |state_file|
219
+ filename = "./db/#{state_file.name}"
220
+ # prompt if local file is newer than cloud state file
221
+ if ::File.exist?(filename) && ::File.ctime(filename) > state_file.created_at
222
+ puts "Local #{filename} is newer than the version in pCloud. Are you sure you want to overwrite the local file with an older copy? [Y/N]".red
223
+ print "> ".red
224
+ unless ["yes", "y"].include?($stdin.gets.chomp.downcase)
225
+ puts "Skipping download of #{filename}...".yellow
226
+ next
227
+ end
228
+ end
229
+ # Only proceed with file download after confirmation or if cloud file is
230
+ # not older than local file.
231
+ ::File.open(filename, "w") do |file|
232
+ file.binmode
233
+ puts "Downloading #{filename} from pCloud...".yellow
234
+ HTTParty.get(state_file.download_url, stream_body: true) do |fragment|
235
+ file.write(fragment)
236
+ end
237
+ end
238
+ end
239
+ ```
240
+
163
241
  ## Development
164
242
 
165
243
  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.
data/RELEASEING.md CHANGED
@@ -3,5 +3,5 @@
3
3
  2. Make any documentation updates.
4
4
  3. Tag a new release in GitHub and summarize the changes since the last release.
5
5
  4. Build the gem locally: `gem build pcloud_api.gemspec`.
6
- * To test the gem in a local project, you can install it with `gem install --local pcloud_api-<VERSION>.gem`
6
+ * To test the gem in a local project, you can install it with `gem install --local pcloud_api-<VERSION>.gem`
7
7
  5. Publish the gem to rubygems.org: `gem push pcloud_api-<VERSION>.gem`.
data/lib/pcloud/client.rb CHANGED
@@ -9,20 +9,21 @@ module Pcloud
9
9
  ].freeze
10
10
  US_API_BASE = "api.pcloud.com".freeze
11
11
  EU_API_BASE = "eapi.pcloud.com".freeze
12
- TIMEOUT_SECONDS = ENV.fetch("PCLOUD_API_TIMEOUT_SECONDS", "8").to_i.freeze
12
+ DEFAULT_TIMEOUT_SECONDS = 8.freeze
13
13
 
14
14
  class << self
15
- def configure(access_token: nil, data_region: nil)
15
+ def configure(access_token: nil, data_region: nil, timeout_seconds: nil)
16
16
  @@access_token = access_token
17
17
  @@data_region = data_region
18
+ @@timeout_seconds = timeout_seconds.nil? ? nil : timeout_seconds.to_i
18
19
  true # Don't accidentally return any secrets from the configure method
19
20
  end
20
21
 
21
22
  def execute(method, query: {}, body: {})
22
23
  verb = ["uploadfile"].include?(method) ? :post : :get
23
24
  options = {
24
- headers: { "Authorization" => "Bearer #{access_token}" },
25
- timeout: TIMEOUT_SECONDS # this sets both the open and read timeouts to the same value
25
+ headers: { "Authorization" => "Bearer #{access_token_from_config_or_env}" },
26
+ timeout: timeout_seconds_from_config_or_env # this sets both the open and read timeouts to the same value
26
27
  }
27
28
  options[:query] = query unless query.empty?
28
29
  options[:body] = body unless body.empty?
@@ -34,26 +35,32 @@ module Pcloud
34
35
 
35
36
  private
36
37
 
37
- def data_region
38
+ def data_region_from_config_or_env
38
39
  @@data_region ||= ENV["PCLOUD_API_DATA_REGION"]
39
40
  return @@data_region if VALID_DATA_REGIONS.include?(@@data_region)
40
41
  raise ConfigurationError.new("Missing pCloud data region") if @@data_region.nil?
41
42
  raise ConfigurationError.new("Invalid pCloud data region, must be one of #{VALID_DATA_REGIONS}")
42
43
  end
43
44
 
44
- def access_token
45
+ def access_token_from_config_or_env
45
46
  @@access_token ||= ENV["PCLOUD_API_ACCESS_TOKEN"]
46
47
  return @@access_token unless @@access_token.nil?
47
48
  raise ConfigurationError.new("Missing pCloud API access token")
48
49
  end
49
50
 
51
+ def timeout_seconds_from_config_or_env
52
+ @@timeout_seconds ||= ENV.fetch("PCLOUD_API_TIMEOUT_SECONDS", DEFAULT_TIMEOUT_SECONDS).to_i
53
+ return @@timeout_seconds unless @@timeout_seconds.zero?
54
+ raise ConfigurationError.new("Invalid pCloud API timeout seconds: cannot be set to 0")
55
+ end
56
+
50
57
  # You can manually hit "https://<default_server_for_your_region>/getapiserver"
51
58
  # to get some JSON which will tell you if there is a server in your region
52
59
  # closer to you than the default.
53
60
  def closest_server
54
61
  @@closest_server ||= begin
55
62
  return ENV["PCLOUD_API_BASE_URI"] if ENV["PCLOUD_API_BASE_URI"]
56
- case data_region
63
+ case data_region_from_config_or_env
57
64
  when US_DATA_REGION
58
65
  US_API_BASE
59
66
  when EU_DATA_REGION
data/lib/pcloud/folder.rb CHANGED
@@ -8,7 +8,7 @@ module Pcloud
8
8
  include Pcloud::TimeHelper
9
9
 
10
10
  SUPPORTED_UPDATE_PARAMS = [:name, :parent_folder_id, :path].freeze
11
- SUPPORTED_FIND_BY_PARAMS = [:id, :path].freeze
11
+ SUPPORTED_FIND_BY_PARAMS = [:id, :path, :recursive].freeze
12
12
 
13
13
  attr_reader :id, :path, :name, :parent_folder_id, :is_deleted, :created_at,
14
14
  :modified_at
@@ -91,8 +91,8 @@ module Pcloud
91
91
  raise e
92
92
  end
93
93
 
94
- def find(id)
95
- parse_one(Client.execute("listfolder", query: { folderid: id }))
94
+ def find(id, opts={})
95
+ parse_one(Client.execute("listfolder", query: { folderid: id, recursive: opts[:recursive] == true }))
96
96
  end
97
97
 
98
98
  def find_by(params)
@@ -100,7 +100,7 @@ module Pcloud
100
100
  raise InvalidParameters.new("Must be one of #{SUPPORTED_FIND_BY_PARAMS}")
101
101
  end
102
102
  raise InvalidParameters.new(":id takes precedent over :path, please only use one or the other") if params[:path] && params[:id]
103
- query = { path: params[:path], folderid: params[:id] }.compact
103
+ query = { path: params[:path], folderid: params[:id], recursive: params[:recursive] == true }.compact
104
104
  parse_one(Client.execute("listfolder", query: query))
105
105
  end
106
106
  end
@@ -1,3 +1,3 @@
1
1
  module Pcloud
2
- VERSION = "0.2.3"
2
+ VERSION = "0.2.4"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pcloud_api
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
  - Joshua Hunsche Jones
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-12-14 00:00:00.000000000 Z
11
+ date: 2023-05-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -149,7 +149,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
149
149
  - !ruby/object:Gem::Version
150
150
  version: '0'
151
151
  requirements: []
152
- rubygems_version: 3.2.22
152
+ rubygems_version: 3.3.26
153
153
  signing_key:
154
154
  specification_version: 4
155
155
  summary: A Ruby library for interacting with the pCloud API