figshare_api_v2 0.9.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3b830ddd5bc2ff58ce03dc8c96f2029fe21e7913c9ce360cd09078b19c446277
4
+ data.tar.gz: 682588604c24ee90a212f854815e4da68edb68f33230d7d4d019b8dd3ed50b8e
5
+ SHA512:
6
+ metadata.gz: bf62ed1ab2f35779259c09c0beee9c04d1b0caa7a06d5186de7c2d9d4010e4bcf4c24af83c06215d512e35ff9e63bd4318b3a412fc64b5c369d93465835ccc03
7
+ data.tar.gz: fde9f1ee7a1d052e25553175412d813d9ffc7dca198d05c715693e9d7601ef14cc84ba6b1976416a61a90ac052ab220e9b268db4895c4f87306c3027cbf0539c
@@ -0,0 +1,58 @@
1
+ robertburrowes Thu Nov 5 11:09:37 2020 +1300
2
+ bump version
3
+ robertburrowes Thu Nov 5 11:09:10 2020 +1300
4
+ bump version
5
+ robertburrowes Thu Nov 5 11:08:53 2020 +1300
6
+ Upload test of directory
7
+ robertburrowes Thu Nov 5 11:08:30 2020 +1300
8
+ Trying real world examples
9
+ robertburrowes Thu Nov 5 11:08:02 2020 +1300
10
+ dependency on WIKK::dir_r gem
11
+ robertburrowes Thu Nov 5 11:07:41 2020 +1300
12
+ Fixes, after tests. Added upload_dir
13
+ robertburrowes Fri Oct 30 15:07:02 2020 +1300
14
+ playing with more tests
15
+ robertburrowes Fri Oct 30 15:06:45 2020 +1300
16
+ minor tidy up. This version successfully uploaded files
17
+ robertburrowes Fri Oct 30 15:05:32 2020 +1300
18
+ check response content type, and only parse json, when json
19
+ robertburrowes Fri Oct 30 09:41:42 2020 +1300
20
+ More testing
21
+ robertburrowes Fri Oct 30 09:41:31 2020 +1300
22
+ Added trace code to upload.
23
+ robertburrowes Fri Oct 30 09:40:43 2020 +1300
24
+ Name conflict with delete. Use explicit name
25
+ robertburrowes Fri Oct 30 09:39:36 2020 +1300
26
+ Ignore test data
27
+ robertburrowes Fri Oct 30 09:06:18 2020 +1300
28
+ Init class test
29
+ robertburrowes Fri Oct 30 09:05:27 2020 +1300
30
+ Init class test
31
+ robertburrowes Fri Oct 30 09:05:17 2020 +1300
32
+ Example code
33
+ robertburrowes Fri Oct 30 09:05:03 2020 +1300
34
+ include the OAI PMH stub
35
+ robertburrowes Fri Oct 30 09:04:47 2020 +1300
36
+ Changed to use Figshare::Base calls
37
+ robertburrowes Fri Oct 30 09:03:58 2020 +1300
38
+ Stub for Stats class
39
+ robertburrowes Fri Oct 30 09:03:42 2020 +1300
40
+ stub for OAI PMH class
41
+ robertburrowes Fri Oct 30 09:03:22 2020 +1300
42
+ comment aligned with Init class initialize
43
+ robertburrowes Fri Oct 30 09:03:00 2020 +1300
44
+ Added an Init class to dynamically create subclasses
45
+ robertburrowes Thu Oct 29 19:23:55 2020 +1300
46
+ playing with tests
47
+ robertburrowes Thu Oct 29 19:23:40 2020 +1300
48
+ Update
49
+ robertburrowes Thu Oct 29 19:23:29 2020 +1300
50
+ Added in missing api calls
51
+ robertburrowes Thu Oct 29 18:13:47 2020 +1300
52
+ mode change only
53
+ robertburrowes Thu Oct 29 17:59:56 2020 +1300
54
+ Changes to build files to get first pkg created
55
+ robertburrowes Thu Oct 29 17:32:27 2020 +1300
56
+ initial version. Not tested yet
57
+ Rob Burrowes Mon Oct 19 09:52:15 2020 +1300
58
+ Initial commit
@@ -0,0 +1,18 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.md
4
+ Rakefile
5
+ lib/authors.rb
6
+ lib/base.rb
7
+ lib/figshare_api_v2.rb
8
+ lib/institutions.rb
9
+ lib/oai_pmh.rb
10
+ lib/other.rb
11
+ lib/private_articles.rb
12
+ lib/private_collections.rb
13
+ lib/private_projects.rb
14
+ lib/public_articles.rb
15
+ lib/public_collections.rb
16
+ lib/public_projects.rb
17
+ lib/stats.rb
18
+ lib/upload.rb
@@ -0,0 +1,74 @@
1
+ # figshare_api_v2
2
+
3
+ * Docs :: https://UoA-eResearch.github.io/figshare_api_v2/
4
+ * Source :: https://github.com/UoA-eResearch/figshare_api_v2
5
+ * Gem :: https://rubygems.org/gems/figshare_api_v2
6
+ * Figshare :: https://docs.figshare.com/
7
+
8
+ ## DESCRIPTION:
9
+
10
+ Figshare version 2 API.
11
+
12
+ ## FEATURES/PROBLEMS:
13
+
14
+ * Stats API not implemented.
15
+ * oai pmh api not implemented.
16
+ * Need to build a test suite
17
+ * impersonate option, for PrivateArticles, PrivateCollections and PrivateProjects ignored for DELETE, and non-json POST and PUT.
18
+
19
+ ## SYNOPSIS:
20
+
21
+ ```
22
+ require 'figshare_api_v2'
23
+
24
+ # Either initialize once, and call @figshare.authors.x @figshare.institutions.x, ...
25
+ @figshare = Figshare::Init.new(figshare_user: 'figshare_admin', conf_dir: "#{__dir__}/conf")
26
+
27
+ @figshare.authors.detail(author_id: 12345) { |a| puts a }
28
+ @figshare.institutions.private_articles { |article| puts article }
29
+ #...
30
+
31
+ # Or initialize each class individually
32
+ @authors = Figshare::Authors.new(figshare_user: 'figshare_admin', conf_dir: "#{__dir__}/conf")
33
+ @institutions = Figshare::Institutions.new(figshare_user: 'figshare_admin', conf_dir: "#{__dir__}/conf")
34
+
35
+ @authors.detail(author_id: 12345) { |a| puts a }
36
+ @institutions.private_articles { |article| puts article }
37
+
38
+ #...
39
+ ````
40
+
41
+ ## REQUIREMENTS:
42
+
43
+ * depends on 'wikk_webbrowser' gem
44
+ * depends on 'wikk_json' gem (beware: adds to_j to the base classes)
45
+
46
+ ## INSTALL:
47
+
48
+ * sudo gem install figshare_api_v2
49
+
50
+ ## LICENSE:
51
+
52
+ The MIT License
53
+
54
+ Copyright (c) 2020
55
+
56
+ Permission is hereby granted, free of charge, to any person obtaining
57
+ a copy of this software and associated documentation files (the
58
+ 'Software'), to deal in the Software without restriction, including
59
+ without limitation the rights to use, copy, modify, merge, publish,
60
+ distribute, sublicense, and/or sell copies of the Software, and to
61
+ permit persons to whom the Software is furnished to do so, subject to
62
+ the following conditions:
63
+
64
+ The above copyright notice and this permission notice shall be
65
+ included in all copies or substantial portions of the Software.
66
+
67
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
68
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
69
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
70
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
71
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
72
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
73
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
74
+
@@ -0,0 +1,31 @@
1
+ # -*- ruby -*-
2
+ require 'rubygems'
3
+ require 'hoe'
4
+ Hoe.plugin :yard
5
+ load "#{__dir__}/version"
6
+
7
+ Hoe.spec PROJECT do
8
+ self.readme_file = "README.md"
9
+ self.developer( "Rob Burrowes","r.burrowes@auckland.ac.nz")
10
+ remote_rdoc_dir = '' # Release to root
11
+
12
+ self.yard_title = PROJECT
13
+ self.yard_options = ['--markup', 'markdown', '--protected']
14
+
15
+ self.dependency "wikk_json", "~> 0.1.2"
16
+ self.dependency "wikk_webbrowser", "~> 0.9.0"
17
+ self.dependency "dir_r", "~> 1.0.0"
18
+ end
19
+
20
+
21
+ #Validate manfest.txt
22
+ #rake check_manifest
23
+
24
+ #Local checking. Creates pkg/
25
+ #rake gem
26
+
27
+ #create doc/
28
+ #rake docs
29
+
30
+ #Copy up to rubygem.org
31
+ #rake release VERSION=1.0.1
@@ -0,0 +1,41 @@
1
+ module Figshare
2
+ # Figshare Author APIs
3
+ #
4
+ class Authors < Base
5
+ # Search authors
6
+ #
7
+ # @param institution [Boolean] Just our institution
8
+ # @param group_id [Integer] Only return this group's collections
9
+ # @param orcid [String] Matches this orcid
10
+ # @param is_active [Boolean]
11
+ # @param is_public [Boolean]
12
+ # @param order [String] "published_date" Default, "modified_date", "views", "cites", "shares"
13
+ # @param order_direction [String] "desc" Default, "asc"
14
+ # @yield [Hash] {id, first_name, last_name, full_name, url_name, is_active, is_public, orcid_id, institution_id, group_id, job_title}
15
+ def search(institute: false, group_id: nil, orcid: nil,
16
+ is_active: true, is_public: true,
17
+ order: 'published_date', order_direction: 'desc',
18
+ search_for:,
19
+ &block
20
+ )
21
+ args = { 'search_for' => search_for }
22
+ args['institution'] = @institute_id if ! institute.nil?
23
+ args['group_id'] = group_id if ! group_id.nil?
24
+ args['is_active'] = is_active if ! is_active.nil?
25
+ args['is_public'] = is_public if ! is_public.nil?
26
+ args['orcid'] = orcid if ! orcid.nil?
27
+ args['order'] = order if ! order.nil?
28
+ args['order_direction'] = order_direction if ! order_direction.nil?
29
+ post(api_query: 'account/authors/search', args: args, &block)
30
+ end
31
+
32
+ # Get an authors details
33
+ #
34
+ # @param author_id [Integer] Figshare Author ID
35
+ # @yield [Hash] {id, first_name, last_name, full_name, url_name, is_active, is_public, orcid_id, institution_id, group_id, job_title}
36
+ def detail(author_id:, &block)
37
+ get(api_query: "account/authors/#{author_id}", &block)
38
+ end
39
+ end
40
+
41
+ end
@@ -0,0 +1,262 @@
1
+ module Figshare
2
+ require "wikk_webbrowser"
3
+ require "wikk_json"
4
+ require 'Time'
5
+
6
+ # Supporting web calls to the API
7
+ #
8
+ class Base
9
+ attr_accessor :auth_token
10
+ attr_accessor :base_dir
11
+ attr_accessor :article_index_file
12
+ attr_accessor :hostname
13
+ attr_accessor :api_url
14
+ attr_accessor :institute_id
15
+
16
+ # Init reads the Json configuration files, setting @course_codes_to_faculty and @academic_department_code_to_faculty
17
+ # Opens a connection to the LDAP server, setting @ldap for other methods to use.
18
+ #
19
+ # @param figshare_user [String] figshare user, in the figshare_keys.json
20
+ # @param conf_dir [String] directory for figshare_keys.json and figshare_site_params.json
21
+ def initialize(figshare_user:, conf_dir:)
22
+ figshare_token = load_json_file("#{conf_dir}/figshare_keys.json")
23
+ @auth_token = figshare_token[figshare_user]
24
+
25
+ figshare_site_params = load_json_file("#{conf_dir}/figshare_site_params.json")
26
+
27
+ @hostname = figshare_site_params['host']
28
+ @api_url = figshare_site_params['api_url']
29
+ @institute_id = figshare_site_params['institute_id']
30
+ end
31
+
32
+ # Parse the config file
33
+ #
34
+ # @param filename [String] config file name to parse
35
+ # @return [Hash|Array] parsed json configuration file.
36
+ private def load_json_file(filename)
37
+ JSON.parse(File.read(filename))
38
+ end
39
+
40
+ # get iterates through the API response, yielding each value to the passed block
41
+ # When Figshare API usually has no paging option.
42
+ # If there is no block, then the results are printed (useful for debugging)
43
+ #
44
+ # @param api_query [String] base figshare api call, to which we add parameters defined in args
45
+ # @param args [Hash] Key, value pairs which get converted to ?key=arg&key=arg...
46
+ # @param debug [Boolean] print result to stdout
47
+ # @yield [String] if given a block, iterates through the result from figshare
48
+ # @return [Integer] number of results.
49
+ private def get(api_query:, args: {}, debug: false, &block)
50
+ content_type = response = nil
51
+ WIKK::WebBrowser.https_session( host: @hostname, verify_cert: false ) do |ws|
52
+ response = ws.get_page( query: "#{@api_url}#{api_query}",
53
+ authorization: "token #{@auth_token}",
54
+ form_values: args
55
+ )
56
+ content_type = ws.header_value(key: 'Content-Type')
57
+ end
58
+ return iterate_json_response(response: response, content_type: content_type, debug: debug, &block)
59
+ end
60
+
61
+ # get_paginate iterates through the API response, yielding each value to the passed block, fetching new pages ,as needed.
62
+ # Figshare API usually has the option of page and page_size parameters, to help with large downloads.
63
+ # If there is no block, then the results are printed (useful for debugging)
64
+ #
65
+ # @param api_query [String] base figshare api call, to which we add parameters defined in args
66
+ # @param args [Hash] Key, value pairs which get converted to ?key=arg&key=arg...
67
+ # @param debug [Boolean] print result to stdout
68
+ # @param by_offset [Boolean] use offset/limit rather than page/page_size in API calls
69
+ # @yield [String] if given a block, iterates through the result from figshare
70
+ # @return [Integer] number of results.
71
+ private def get_paginate(api_query:, args: {}, debug: false, by_offset: false, &block)
72
+ args = {} if args.nil?
73
+ if ! args.is_a?(Hash)
74
+ raise "get_paginate(): Expecting args to be a Hash"
75
+ end
76
+
77
+ offset = 0
78
+ page = 1
79
+ limit = page_size = 100
80
+ result_count = 0
81
+ loop do
82
+ content_type = response = nil
83
+ form_args = by_offset ? {"limit"=>limit, "offset"=>offset} : {"page_size"=>page_size, "page"=>page}
84
+ WIKK::WebBrowser.https_session( host: @hostname, verify_cert: false ) do |ws|
85
+ response = ws.get_page( query: "#{@api_url}#{api_query}",
86
+ authorization: "token #{@auth_token}",
87
+ form_values: form_args.merge(args)
88
+ )
89
+ content_type = ws.header_value(key: 'Content-Type')
90
+ end
91
+ page_count = iterate_json_response(response: response, content_type: content_type, debug: debug, &block)
92
+ result_count += page_count
93
+ break if page_count < page_size # Got less results than we asked for, so it was the last page
94
+
95
+ page += 1 #Ready to fetch next page
96
+ offset += limit #if we use offset, then mor
97
+ end
98
+
99
+ return result_count
100
+ end
101
+
102
+ # post iterates through the API response, yielding each value to the passed block
103
+ # When Figshare API usually has no paging option.
104
+ # If there is no block, then the results are printed (useful for debugging)
105
+ #
106
+ # @param api_query [String] base figshare api call, to which we add parameters defined in args
107
+ # @param args [Hash] Key, value pairs which get converted to ?key=arg&key=arg...
108
+ # @param debug [Boolean] print result to stdout
109
+ # @param content_type [String] Assuming Json, but might need binary ('application/octet-stream')
110
+ # @yield [String] if given a block, iterates through the result from figshare
111
+ # @return [Integer] number of results.
112
+ private def post(api_query:, args: {}, data: nil, debug: false, content_type: 'application/json; charset=UTF-8', &block)
113
+ body = nil
114
+ if data.is_a?(Hash)
115
+ # Convert hash to json, and merge in additional args
116
+ body = data.merge(args).to_j
117
+ elsif data.nil? && ! args.empty?
118
+ # No data, but args, so just use the args
119
+ body = args.to_j
120
+ else
121
+ # Data isn't a Hash, so just pass it through (might be nil)
122
+ body = data
123
+ end
124
+
125
+ content_type = response = nil
126
+ WIKK::WebBrowser.https_session( host: @hostname, verify_cert: false ) do |ws|
127
+ response = ws.post_page( query: "#{@api_url}#{api_query}",
128
+ content_type: content_type,
129
+ authorization: "token #{@auth_token}",
130
+ data: body
131
+ )
132
+ content_type = ws.header_value(key: 'Content-Type')
133
+ end
134
+ return iterate_json_response(response: response, content_type: content_type, debug: debug, &block)
135
+ end
136
+
137
+ # post_paginate iterates through the API response, yielding each value to the passed block, fetching new pages ,as needed.
138
+ # Figshare API usually has the option of page and page_size parameters, to help with large downloads.
139
+ # If there is no block, then the results are printed (useful for debugging)
140
+ #
141
+ # @param api_query [String] base figshare api call, to which we add parameters defined in args
142
+ # @param args [Hash] Key, value pairs which get converted to ?key=arg&key=arg...
143
+ # @param debug [Boolean] print result to stdout
144
+ # @param by_offset [Boolean] use offset/limit rather than page/page_size in API calls
145
+ # @yield [String] if given a block, iterates through the result from figshare
146
+ # @return [Integer] number of results.
147
+ private def post_paginate(api_query:, args: {}, debug: false, by_offset: false, &block)
148
+ page = 1
149
+ offset = 0
150
+ limit = page_size = 100
151
+ result_count = 0
152
+
153
+ args = {} if args.nil?
154
+ if ! args.is_a?(Hash)
155
+ raise "post_paginate(): Expecting args to be a Hash"
156
+ end
157
+
158
+ loop do
159
+ content_type = response = nil
160
+ form_args = by_offset ? {"limit"=>limit, "offset"=>offset} : {"page_size"=>page_size, "page"=>page}
161
+ WIKK::WebBrowser.https_session( host: @hostname, verify_cert: false ) do |ws|
162
+ response = ws.post_page( query: "#{@api_url}#{api_query}",
163
+ content_type: 'application/json; charset=UTF-8',
164
+ authorization: "token #{@auth_token}",
165
+ data: args.merge(form_args).to_j
166
+ )
167
+ content_type = ws.header_value(key: 'Content-Type')
168
+ end
169
+ page_count = iterate_json_response(response: response, content_type: content_type, debug: debug, &block)
170
+ result_count += page_count
171
+ break if page_count < page_size # Got less results than we asked for, so it was the last page
172
+
173
+ page += 1 #Ready to fetch next page
174
+ offset += limit #if we use offset
175
+ end
176
+ return result_count
177
+ end
178
+
179
+ # put iterates through the API response, yielding each value to the passed block
180
+ # When Figshare API usually has no paging option.
181
+ # If there is no block, then the results are printed (useful for debugging)
182
+ #
183
+ # @param api_query [String] base figshare api call, to which we add parameters defined in args
184
+ # @param args [Hash] Key, value pairs which get converted to ?key=arg&key=arg...
185
+ # @param debug [Boolean] print result to stdout
186
+ # @param content_type [String] Assuming Json, but might need binary ('application/octet-stream')
187
+ # @yield [String] if given a block, iterates through the result from figshare
188
+ # @return [Integer] number of results
189
+ private def put(api_query:, args: {}, data: nil, debug: false, content_type: 'application/json; charset=UTF-8', &block)
190
+ body = nil
191
+ if data.is_a?(Hash)
192
+ # Convert hash to json, and merge in additional args
193
+ body = data.merge(args).to_j
194
+ elsif data.nil? && ! args.empty?
195
+ # No data, but args, so just use the args
196
+ body = args.to_j
197
+ else
198
+ # Data isn't a Hash, so just pass it through (might be nil)
199
+ body = data
200
+ end
201
+
202
+ content_type = response = nil
203
+ WIKK::WebBrowser.https_session( host: @hostname, verify_cert: false ) do |ws|
204
+ response = ws.put_page( query: "#{@api_url}#{api_query}",
205
+ content_type: content_type,
206
+ authorization: "token #{@auth_token}",
207
+ data: body
208
+ )
209
+ content_type = ws.header_value(key: 'Content-Type')
210
+ end
211
+ return iterate_json_response(response: response, content_type: content_type, debug: debug, &block)
212
+ end
213
+
214
+ # delete sends an HTML DELETE request.
215
+ # We don't expect to get a response to this call.
216
+ #
217
+ # @param api_query [String] base figshare api call
218
+ # @param debug [Boolean] print result to stdout
219
+ # @yield [Hash] Unlikely to have a result from delete calls, but if we do, we see it here
220
+ # @return [Integer] number of results (usually 0)
221
+ private def delete(api_query:, args: {}, debug: false, &block)
222
+ #ignoring args for the moment. Not sure what to do with them, if we do get them.
223
+ content_type = response = nil
224
+ WIKK::WebBrowser.https_session( host: @hostname, verify_cert: false ) do |ws|
225
+ response = ws.delete_req( query: "#{@api_url}#{api_query}",
226
+ authorization: "token #{@auth_token}"
227
+ )
228
+ content_type = ws.header_value(key: 'Content-Type')
229
+ end
230
+ return iterate_json_response(response: response, content_type: content_type, debug: debug, &block)
231
+ end
232
+
233
+ # For iterate through the api response
234
+ #
235
+ # @param response [String] response from the API call
236
+ # @param content_type [String] From html response header
237
+ # @param debug [Boolean] print result to stdout
238
+ # @yield [Hash] each array member in the response (or the entire response, if not iteratable)
239
+ private def iterate_json_response(response:, content_type:, debug: false )
240
+ return 0 if response.nil? # got no responses
241
+
242
+ if content_type =~ /application\/json/
243
+ response_array = JSON.parse(response)
244
+ #If we don't have an Array, turn the response into an Array so we can iterate over this one response.
245
+ response_array = [ response_array ] if ! (response_array.class == Array)
246
+ return 0 if response_array.empty? # got empty array of responses
247
+
248
+ count = 0
249
+ response_array.each do |r|
250
+ yield r if block_given?
251
+ p r if debug
252
+ count += 1
253
+ end
254
+
255
+ return count
256
+ else #just dump the entire response on the caller :)
257
+ yield response if block_given?
258
+ return response.length
259
+ end
260
+ end
261
+ end
262
+ end