gofile_ruby 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/gofile_ruby/http_helper.rb +99 -0
- data/lib/gofile_ruby.rb +339 -0
- metadata +58 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 47e057021b75d055e226caa9021dfcd19af569f5617cb4561fb4a105edacd297
|
4
|
+
data.tar.gz: aba9b1f550b6219cb64ae3a2aa7a537aa4b6586a621dfd4cfca2f6572b2d4a10
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 89f0ee65a45d8d1241a669db24960cb853a4631ca5087222468a0c8075ee957e1c8adb3a6475176eef5ce729148f5e78a0d54831b0f6083fcd092fe9706dd69a
|
7
|
+
data.tar.gz: e3083ce6c174358912b91bbc78c1d1201eeb12815be10a20656ab8215e6ff1998f84ed5bd12173cee3a427e5c41b16e9f06b1c04ad30264c9e1fc3325e307cc3
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'net/http'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
# A module for simplifying HTTP requests
|
6
|
+
module HTTPHelper
|
7
|
+
# Makes a GET request to the specified URL.
|
8
|
+
#
|
9
|
+
# If the given URL is a string, it gets converted to a URI.
|
10
|
+
# @param [String, URI] url The URL for the request.
|
11
|
+
def self.get(url)
|
12
|
+
url = URI(url) unless url.class == URI::Generic
|
13
|
+
res = Net::HTTP.get_response(url)
|
14
|
+
|
15
|
+
ret = res.body
|
16
|
+
ret = JSON.parse(ret)
|
17
|
+
|
18
|
+
ret
|
19
|
+
end
|
20
|
+
|
21
|
+
# POSTs the data as a form to the specified URL.
|
22
|
+
#
|
23
|
+
# If the given URL is a string, it gets converted to a URI.
|
24
|
+
# @param [String, URI] url The URL for the request.
|
25
|
+
# @param [Hash] data The data for the post request.
|
26
|
+
def self.post_form(url, data)
|
27
|
+
url = URI(url) unless url.class == URI::Generic
|
28
|
+
|
29
|
+
res = Net::HTTP.post_form(url, data)
|
30
|
+
|
31
|
+
ret = res.body
|
32
|
+
ret = JSON.parse(ret)
|
33
|
+
|
34
|
+
ret
|
35
|
+
end
|
36
|
+
|
37
|
+
# Takes an array of arrays and POSTs them as multipart form data to the specified URL.
|
38
|
+
#
|
39
|
+
# If the given URL is a string, it gets converted to a URI.
|
40
|
+
# @param [String, URI] url The URL for the request.
|
41
|
+
# @param [Array<Array<String, T>>] data The data for the post request.
|
42
|
+
def self.post_multipart_data(url, data)
|
43
|
+
url = URI(url) unless url.class == URI::Generic
|
44
|
+
|
45
|
+
http = Net::HTTP.new(url.host, url.port)
|
46
|
+
http.use_ssl = true
|
47
|
+
req = Net::HTTP::Post.new(url)
|
48
|
+
req.set_form data, 'multipart/form-data'
|
49
|
+
|
50
|
+
res = http.request(req)
|
51
|
+
|
52
|
+
ret = res.body
|
53
|
+
ret = JSON.parse(ret)
|
54
|
+
|
55
|
+
ret
|
56
|
+
end
|
57
|
+
|
58
|
+
# Makes a PUT request to the specified URL.
|
59
|
+
#
|
60
|
+
# If the given URL is a string, it gets converted to a URI.
|
61
|
+
# @param [String, URI] url The URL for the request.
|
62
|
+
# @param [Array<Array<String, T>>] data The data for the post request.
|
63
|
+
def self.put(url, data)
|
64
|
+
url = URI(url) unless url.class == URI::Generic
|
65
|
+
|
66
|
+
http = Net::HTTP.new(url.host, url.port)
|
67
|
+
http.use_ssl = true
|
68
|
+
req = Net::HTTP::Put.new(url, { 'Content-Type' => 'application/x-www-form-urlencoded' })
|
69
|
+
req.body = URI::encode_www_form(data)
|
70
|
+
|
71
|
+
res = http.request(req)
|
72
|
+
|
73
|
+
ret = res.body
|
74
|
+
ret = JSON.parse(ret)
|
75
|
+
|
76
|
+
ret
|
77
|
+
end
|
78
|
+
|
79
|
+
# Makes a DELETE request to the specified URL.
|
80
|
+
#
|
81
|
+
# If the given URL is a string, it gets converted to a URI.
|
82
|
+
# @param [String, URI] url The URL for the request.
|
83
|
+
# @param [Array<Array<String, T>>] data The data for the post request.
|
84
|
+
def self.delete(url, data)
|
85
|
+
url = URI(url) unless url.class == URI::Generic
|
86
|
+
|
87
|
+
http = Net::HTTP.new(url.host, url.port)
|
88
|
+
http.use_ssl = true
|
89
|
+
req = Net::HTTP::Delete.new(url, { 'Content-Type' => 'application/x-www-form-urlencoded' })
|
90
|
+
req.body = URI::encode_www_form(data)
|
91
|
+
|
92
|
+
res = http.request(req)
|
93
|
+
|
94
|
+
ret = res.body
|
95
|
+
ret = JSON.parse(ret)
|
96
|
+
|
97
|
+
ret
|
98
|
+
end
|
99
|
+
end
|
data/lib/gofile_ruby.rb
ADDED
@@ -0,0 +1,339 @@
|
|
1
|
+
require './lib/gofile_ruby/http_helper.rb'
|
2
|
+
|
3
|
+
# A wrapper for the GoFile API, containing methods for each available endpoint.
|
4
|
+
#
|
5
|
+
# @see https://gofile.io/api
|
6
|
+
class GFClient
|
7
|
+
|
8
|
+
attr_reader :account_details, :is_guest
|
9
|
+
# Creates a new instance of the GFClient class.
|
10
|
+
# @param [String] token The API token for your GoFile account
|
11
|
+
# @param [Boolean] guest A boolean value indicating whether or not guest mode should be enabled
|
12
|
+
def initialize(token:nil, guest:false)
|
13
|
+
# The GoFile API token, defaults to nil if none is provided.
|
14
|
+
@token = token
|
15
|
+
# A GFClient instance that is in guest mode (where no token is provided) will set @has_token to false, and @is_guest to true.
|
16
|
+
# The @has_token instance variable will be set to true after the user acquires a guest account token by uploading a file in guest mode.
|
17
|
+
@has_token = !@token.nil?
|
18
|
+
# Instance variable for tracking if the client is using a guest account or not
|
19
|
+
@is_guest = guest
|
20
|
+
|
21
|
+
# Account details, initially set to `nil` until the user calls the `#authenticate` method
|
22
|
+
@account_details = nil
|
23
|
+
|
24
|
+
# The root folder returned by the `#upload_file` method when called in guest mode (without a token).
|
25
|
+
# Gets set after a guest account uploads their first file.
|
26
|
+
# Is used only when uploading files as a guest.
|
27
|
+
@guest_upload_destination = nil
|
28
|
+
# Final checks to ensure the user doesn't try anything odd. (Eg. passing in a token while also setting guest mode to true)
|
29
|
+
validate_guest_mode
|
30
|
+
end
|
31
|
+
|
32
|
+
# Retreives the best available server for uploading files
|
33
|
+
#
|
34
|
+
# Example response:
|
35
|
+
#
|
36
|
+
# "status": "ok",
|
37
|
+
# "data": {
|
38
|
+
# "server": "store1"
|
39
|
+
# }
|
40
|
+
#
|
41
|
+
# @return [Hash] response The response object.
|
42
|
+
def get_server
|
43
|
+
server_url = "https://api.gofile.io/getServer"
|
44
|
+
HTTPHelper.get(server_url)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Uploads a file to the given destination folder.
|
48
|
+
#
|
49
|
+
# If using guest mode, you cannot specify a folder ID when uploading your first file.
|
50
|
+
#
|
51
|
+
# If you're uploading multiple files, you have to use the parent ID along with the token from the response object in your subsequent uploads.
|
52
|
+
#
|
53
|
+
# To get around this issue, gofile_ruby saves the newly returned token and parent ID after your first upload.
|
54
|
+
#
|
55
|
+
# This means that you can call the #upload_file method multiple times without having to deal with authentication.
|
56
|
+
#
|
57
|
+
# Example response:
|
58
|
+
# "status": "ok",
|
59
|
+
# "data": {
|
60
|
+
# "guestToken": "a939kv5b43c03192imatoken2949" (If uploaded without a token)
|
61
|
+
# "downloadPage": "https://gofile.io/d/Z19n9a",
|
62
|
+
# "code": "Z19n9a",
|
63
|
+
# "parentFolder": "3dbc2f87-4c1e-4a81-badc-af004e61a5b4",
|
64
|
+
# "fileId": "4991e6d7-5217-46ae-af3d-c9174adae924",
|
65
|
+
# "fileName": "example.mp4",
|
66
|
+
# "md5": "10c918b1d01aea85864ee65d9e0c2305"
|
67
|
+
# }
|
68
|
+
# @param [File] file The file that will be uploaded to GoFile
|
69
|
+
# @param [String] folder_id The ID for the parent folder. Will default to the root folder if none is provided.
|
70
|
+
# @return [Hash] response The response object.
|
71
|
+
def upload_file(file:, folder_id: nil)
|
72
|
+
raise "Guests cannot specify folder ID before their first upload!" if folder_id && @is_guest
|
73
|
+
|
74
|
+
best_server = get_server()["data"]["server"]
|
75
|
+
upload_url = "https://#{best_server}.gofile.io/uploadFile"
|
76
|
+
|
77
|
+
body = [["file", file]]
|
78
|
+
body << ["token", @token] if @has_token
|
79
|
+
|
80
|
+
# If user inputs a folder_id while they have a token
|
81
|
+
if folder_id && @has_token
|
82
|
+
# add the ID to the body of the request
|
83
|
+
body << ["folderId", folder_id]
|
84
|
+
# If the user has uploaded a file as a guest, and a folder id hasn't been provided, use the folder ID returned from the first file upload
|
85
|
+
elsif @guest_upload_destination && !folder_id
|
86
|
+
body << ["folderId", @guest_upload_destination]
|
87
|
+
end
|
88
|
+
|
89
|
+
ret = HTTPHelper.post_multipart_data(upload_url, body)
|
90
|
+
save_guest_acc_details(ret) if @has_token
|
91
|
+
|
92
|
+
ret
|
93
|
+
end
|
94
|
+
|
95
|
+
# Creates a folder with the given folder name and parent ID.
|
96
|
+
# If a parent ID is not provided, it default to the root folder.
|
97
|
+
#
|
98
|
+
# When using guest mode, you cannot call this method until you've uploaded a file first, as the guest token and root folder ID won't be available.
|
99
|
+
#
|
100
|
+
# Example response:
|
101
|
+
# "status": "ok",
|
102
|
+
# "data": {
|
103
|
+
#
|
104
|
+
# }
|
105
|
+
# @param [String] parent_id The ID of the parent folder
|
106
|
+
# @param [String] folder_name The name of the folder that will be created
|
107
|
+
# @return [Hash] response The response object.
|
108
|
+
def create_folder(parent_id:nil, folder_name:)
|
109
|
+
raise "Cannot create folders without a token! Please upload a file first!" unless @has_token
|
110
|
+
raise "Cannot use root folder without authenticating first" unless @account_details
|
111
|
+
|
112
|
+
post_folder_url = "https://api.gofile.io/createFolder"
|
113
|
+
|
114
|
+
parent_id = @account_details["data"]["rootFolder"] unless parent_id
|
115
|
+
folder_data = {
|
116
|
+
"parentFolderId" => parent_id,
|
117
|
+
"folderName" => folder_name,
|
118
|
+
"token" => @token
|
119
|
+
}
|
120
|
+
|
121
|
+
ret = HTTPHelper.put(post_folder_url, folder_data)
|
122
|
+
|
123
|
+
ret
|
124
|
+
end
|
125
|
+
|
126
|
+
# Gets the children of a specific folder.
|
127
|
+
#
|
128
|
+
# Defaults to root folder if a parent ID is not provided.
|
129
|
+
#
|
130
|
+
# Response example:
|
131
|
+
# "status": "ok",
|
132
|
+
# "data": {
|
133
|
+
# "isOwner": true,
|
134
|
+
# "id": "3dbc2f87-4c1e-4a81-badc-af004e61a5b4",
|
135
|
+
# "type": "folder",
|
136
|
+
# "name": "Z19n9a",
|
137
|
+
# "parentFolder": "3241d27a-f7e1-4158-bc75-73d057eff5fa",
|
138
|
+
# "code": "Z19n9a",
|
139
|
+
# "createTime": 1648229689,
|
140
|
+
# "public": true,
|
141
|
+
# "childs": [
|
142
|
+
# "4991e6d7-5217-46ae-af3d-c9174adae924"
|
143
|
+
# ],
|
144
|
+
# "totalDownloadCount": 0,
|
145
|
+
# "totalSize": 9840497,
|
146
|
+
# "contents": {
|
147
|
+
# "4991e6d7-5217-46ae-af3d-c9174adae924": {
|
148
|
+
# "id": "4991e6d7-5217-46ae-af3d-c9174adae924",
|
149
|
+
# "type": "file",
|
150
|
+
# "name": "example.mp4",
|
151
|
+
# "parentFolder": "3dbc2f87-4c1e-4a81-badc-af004e61a5b4",
|
152
|
+
# "createTime": 1648229689,
|
153
|
+
# "size": 9840497,
|
154
|
+
# "downloadCount": 0,
|
155
|
+
# "md5": "10c918b1d01aea85864ee65d9e0c2305",
|
156
|
+
# "mimetype": "video/mp4",
|
157
|
+
# "serverChoosen": "store4",
|
158
|
+
# "directLink": "https://store4.gofile.io/download/direct/4991e6d7-5217-46ae-af3d-c9174adae924/example.mp4",
|
159
|
+
# "link": "https://store4.gofile.io/download/4991e6d7-5217-46ae-af3d-c9174adae924/example.mp4"
|
160
|
+
# }
|
161
|
+
# }
|
162
|
+
# }
|
163
|
+
# @param [String] parent_id The ID of the parent folder.
|
164
|
+
# @return [Hash] response The response object.
|
165
|
+
# @note This method is premium only! You will not be able to use it unless you have a premium account!
|
166
|
+
# @todo This method will be tested at a later time due to it being a premium-only endpoint.
|
167
|
+
def get_children(parent_id:nil)
|
168
|
+
raise "Cannot use the #get_children method without a token!" if !@has_token
|
169
|
+
|
170
|
+
parent = @account_details["data"]["rootFolder"] if !parent
|
171
|
+
|
172
|
+
content_url = "https://api.gofile.io/getContent?contentId=#{parent}&token=#{@token}"
|
173
|
+
ret = HTTPHelper.get(content_url)
|
174
|
+
|
175
|
+
ret
|
176
|
+
end
|
177
|
+
|
178
|
+
# Sets the options for a specific folder.
|
179
|
+
#
|
180
|
+
# The expected option and value types are listed below.
|
181
|
+
#
|
182
|
+
# public: Boolean
|
183
|
+
#
|
184
|
+
# password: String
|
185
|
+
#
|
186
|
+
# description: String
|
187
|
+
#
|
188
|
+
# expire: Unix Timestamp
|
189
|
+
#
|
190
|
+
# tags: String (String of comma separated tags, Eg. "tag1,tag2,tag3")
|
191
|
+
#
|
192
|
+
# Response example:
|
193
|
+
# "status": "ok",
|
194
|
+
# "data": {}
|
195
|
+
# @param [String] folder_id The ID of the target folder.
|
196
|
+
# @param [String] option The option that you wish to set. Can be "public", "password", "description", "expire" or "tags"
|
197
|
+
# @param [String] value The matching value for the option parameter
|
198
|
+
# @return [Hash] response The response object.
|
199
|
+
def set_folder_option(folder_id:, option:, value:)
|
200
|
+
options_url = "https://api.gofile.io/setFolderOption"
|
201
|
+
|
202
|
+
body = {
|
203
|
+
"option": option,
|
204
|
+
"value": value,
|
205
|
+
"folderId": folder_id,
|
206
|
+
"token": @token
|
207
|
+
}
|
208
|
+
ret = HTTPHelper.put(options_url, body)
|
209
|
+
|
210
|
+
ret
|
211
|
+
end
|
212
|
+
|
213
|
+
# Helper function for #set_folder_option
|
214
|
+
#
|
215
|
+
# @param [String] folder_id The ID of the target folder.
|
216
|
+
# @param [Hash] options_hash A Hash containing options and values as key-value pairs.
|
217
|
+
# @yield [Hash] response The response object for each option-value pair.
|
218
|
+
def set_options_hash(folder_id:, options_hash:, &block)
|
219
|
+
options_hash.each do |k, v|
|
220
|
+
res = set_folder_option(folder_id: folder_id, option: k, value: v)
|
221
|
+
yield res
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
# Copies one or multiple contents to destination folder.
|
226
|
+
#
|
227
|
+
# Destination ID: String
|
228
|
+
#
|
229
|
+
# Contents ID: String A string of comma separated content ID's. ("id1,id2,id3")
|
230
|
+
# Response example:
|
231
|
+
#
|
232
|
+
# "status": "ok",
|
233
|
+
# "data": {}
|
234
|
+
# @param [String] destination_id The ID for the folder where the contents will be copied to.
|
235
|
+
# @param [String] contents_id: A string of comma separated content ID's. ("id1,id2,id3")
|
236
|
+
# @return [Hash] response The response object.
|
237
|
+
# @note This method is premium only! You will not be able to use it unless you have a premium account!
|
238
|
+
# @todo This method will be tested at a later time due to it being a premium-only endpoint.
|
239
|
+
def copy_content(contents_id:, destination_id:)
|
240
|
+
copy_url = "https://api.gofile.io/copyContent"
|
241
|
+
|
242
|
+
body = {
|
243
|
+
"contentsId": contents_id,
|
244
|
+
"folderIdDest": destination_id,
|
245
|
+
"token": @token
|
246
|
+
}
|
247
|
+
|
248
|
+
ret = HTTPHelper.put(copy_url, body)
|
249
|
+
|
250
|
+
ret
|
251
|
+
end
|
252
|
+
|
253
|
+
# Delete one or multiple contents.
|
254
|
+
#
|
255
|
+
# Response example:
|
256
|
+
# "status": "ok",
|
257
|
+
# "data": {}
|
258
|
+
# @param [String] contents_id A string of comma separated content ID's. ("id1,id2,id3")
|
259
|
+
# @return [Hash] response The response object.
|
260
|
+
def delete_content(contents_id:)
|
261
|
+
delete_url = "https://api.gofile.io/deleteContent"
|
262
|
+
|
263
|
+
body = {
|
264
|
+
"contentsId": contents_id,
|
265
|
+
"token": @token
|
266
|
+
}
|
267
|
+
|
268
|
+
ret = HTTPHelper.delete(delete_url, body)
|
269
|
+
|
270
|
+
ret
|
271
|
+
end
|
272
|
+
|
273
|
+
# Will return the details of the current account.
|
274
|
+
#
|
275
|
+
# Response example:
|
276
|
+
# "status": "ok",
|
277
|
+
# "data": {
|
278
|
+
# "token": "ivlW1ZSGn2Y4AoADbCHUjllj2cO9m3WM",
|
279
|
+
# "email": "email@domain.tld",
|
280
|
+
# "tier": "standard",
|
281
|
+
# "rootFolder": "2aecea58-84e6-420d-b2b9-68b4add8418d",
|
282
|
+
# "foldersCount": 4,
|
283
|
+
# "filesCount": 20,
|
284
|
+
# "totalSize": 67653500,
|
285
|
+
# "totalDownloadCount": 1
|
286
|
+
# }
|
287
|
+
# @return [Hash] response The response object.
|
288
|
+
def get_account_details
|
289
|
+
account_details_url = "https://api.gofile.io/getAccountDetails?token=#{@token}"
|
290
|
+
details = HTTPHelper.get(account_details_url)
|
291
|
+
|
292
|
+
details
|
293
|
+
end
|
294
|
+
|
295
|
+
# Calls the #get_account_details method and saves it to the @account_details instance variable
|
296
|
+
#
|
297
|
+
# Response is same as #get_account_details method
|
298
|
+
#
|
299
|
+
# @return [Hash] response The response object.
|
300
|
+
def authenticate
|
301
|
+
acc_deatils = get_account_details
|
302
|
+
@account_details = acc_deatils
|
303
|
+
end
|
304
|
+
|
305
|
+
# Alias for getter method.
|
306
|
+
#
|
307
|
+
# @return [Boolean] is_guest Boolean value indicating whether current instance is in guest mode or not.
|
308
|
+
def is_guest?
|
309
|
+
@is_guest
|
310
|
+
end
|
311
|
+
|
312
|
+
private
|
313
|
+
|
314
|
+
# Takes the response object from a upload and saves the new guest accounts details for further use
|
315
|
+
def save_guest_acc_details(uploadResponse)
|
316
|
+
# If user is a guest,
|
317
|
+
# After uploading, take the newly returned guest token
|
318
|
+
guest_token = uploadResponse["data"]["guestToken"]
|
319
|
+
# And the newly created root folder,
|
320
|
+
new_root_folder = uploadResponse["data"]["parentFolder"]
|
321
|
+
@has_token = false
|
322
|
+
@guest_upload_destination = new_root_folder
|
323
|
+
@token = guest_token
|
324
|
+
# And check the tokens validity, saving the users details into @account_details afterwards
|
325
|
+
get_account_details
|
326
|
+
end
|
327
|
+
|
328
|
+
def validate_guest_mode
|
329
|
+
# Automatically set guest mode if user doesn't provide any input
|
330
|
+
if !@has_token && !@is_guest
|
331
|
+
@is_guest = true
|
332
|
+
end
|
333
|
+
# If user tries inputting a token while also enabling guest mode, switch guest mode off
|
334
|
+
if @has_token && @is_guest
|
335
|
+
@token = nil
|
336
|
+
@has_token = false
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|
metadata
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gofile_ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Eray Alkış
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-03-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.0'
|
27
|
+
description: A Ruby wrapper for the GoFile API
|
28
|
+
email:
|
29
|
+
executables: []
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- lib/gofile_ruby.rb
|
34
|
+
- lib/gofile_ruby/http_helper.rb
|
35
|
+
homepage: https://github.com/erayalkis/gofile_ruby
|
36
|
+
licenses:
|
37
|
+
- MIT
|
38
|
+
metadata: {}
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options: []
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
requirements: []
|
54
|
+
rubygems_version: 3.4.6
|
55
|
+
signing_key:
|
56
|
+
specification_version: 4
|
57
|
+
summary: GoFile API wrapper for Ruby
|
58
|
+
test_files: []
|