checkoff 0.161.0 → 0.162.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f83187f80678558975069a3181a34814c3859b81a9a19f0d29606e9ba37e62c4
4
- data.tar.gz: 8e53186cd5ac43fa6b2fb6f9f4f13a4da3259ab75d8792a43459657e8dcaf8bc
3
+ metadata.gz: 79b74e311c0a9146b3dd2d501940eee17ff14519bdf422ae031808cdd64afef9
4
+ data.tar.gz: 2b464f0fc470ac543a24683dc6d58f2b7131cf6094ab8a9f84813dbae0726d04
5
5
  SHA512:
6
- metadata.gz: 4e4415a477513de35f11579dd45544071ca1b223a5b7a646c2bba0adb2b3becddf7409d4bd69cf0c14d2f0e8fcf55b10014f7d1b90f33d0b667b442aa25dba63
7
- data.tar.gz: 823f046f8f55e05be6d3368cd878abbb02e9632c9bdc7bf5ca5e46160155bee5845ff742550579c55cd1c5013de7e632c828e84c3861ada4998feca0ef29c34a
6
+ metadata.gz: cc73effc84d1d49b688a494ff729b07507d94b29bb8647a96f207cde22d72a39006d9e756e6a35bc218eb603d2736de578914c90871fef595f4301fad193a0ed
7
+ data.tar.gz: 9825765f922b7ceac77884761cef8e937eb39313ff8daf9daed4d478c3a6b63ea497eb0aa9e3f9727483c6657307d85317c03e22d08e36b71d5dd971f6487916
data/Gemfile.lock CHANGED
@@ -12,12 +12,13 @@ GIT
12
12
  PATH
13
13
  remote: .
14
14
  specs:
15
- checkoff (0.161.0)
15
+ checkoff (0.162.0)
16
16
  activesupport
17
17
  asana (> 0.10.0)
18
18
  cache_method
19
19
  dalli
20
20
  gli
21
+ mime-types
21
22
 
22
23
  GEM
23
24
  remote: https://rubygems.org/
@@ -110,6 +111,9 @@ GEM
110
111
  mixlib-config (>= 2.2.1, < 4)
111
112
  mixlib-shellout
112
113
  method_source (1.0.0)
114
+ mime-types (3.5.1)
115
+ mime-types-data (~> 3.2015)
116
+ mime-types-data (3.2023.1205)
113
117
  minitest (5.20.0)
114
118
  minitest-profile (0.0.2)
115
119
  minitest-reporters (1.6.1)
data/Makefile CHANGED
@@ -49,7 +49,6 @@ clear_metrics: ## remove or reset result artifacts created by tests and quality
49
49
 
50
50
  clean: clear_metrics ## remove all built artifacts
51
51
 
52
-
53
52
  citest: test ## Run unit tests from CircleCI
54
53
 
55
54
  overcommit: ## run precommit quality checks
@@ -69,6 +68,14 @@ repl: ## Load up checkoff in pry
69
68
  clean-coverage:
70
69
  @bundle exec rake clear_metrics
71
70
 
71
+ clean-typecheck: ## Refresh information that type checking depends on
72
+ bundle install
73
+ bundle exec solargraph clear
74
+ rm -fr .yardoc/
75
+ bundle exec yard gems
76
+ bundle exec solargraph scan
77
+ echo all clear
78
+
72
79
  coverage: test report-coverage ## check code coverage
73
80
  @bundle exec rake undercover
74
81
 
data/checkoff.gemspec CHANGED
@@ -29,6 +29,7 @@ Gem::Specification.new do |spec|
29
29
  spec.add_runtime_dependency 'cache_method'
30
30
  spec.add_runtime_dependency 'dalli'
31
31
  spec.add_runtime_dependency 'gli'
32
+ spec.add_runtime_dependency 'mime-types'
32
33
 
33
34
  spec.metadata = {
34
35
  'rubygems_mfa_required' => 'false',
@@ -0,0 +1,203 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # frozen_string_literal: true
4
+
5
+ require 'faraday'
6
+ require 'faraday/multipart'
7
+ require 'forwardable'
8
+ require 'cache_method'
9
+ require 'mime/types'
10
+ require 'net/http'
11
+ require 'net/http/response'
12
+ require 'net/http/responses'
13
+ require 'tempfile'
14
+ require_relative 'internal/config_loader'
15
+ require_relative 'internal/logging'
16
+ require_relative 'workspaces'
17
+ require_relative 'tasks'
18
+ require_relative 'clients'
19
+
20
+ # https://developers.asana.com/reference/attachments
21
+
22
+ module Checkoff
23
+ # Manage attachments in Asana
24
+ class Attachments
25
+ # @!parse
26
+ # extend CacheMethod::ClassMethods
27
+
28
+ include Logging
29
+
30
+ MINUTE = 60
31
+ private_constant :MINUTE
32
+ HOUR = MINUTE * 60
33
+ private_constant :HOUR
34
+ DAY = 24 * HOUR
35
+ private_constant :DAY
36
+ REALLY_LONG_CACHE_TIME = HOUR * 1
37
+ private_constant :REALLY_LONG_CACHE_TIME
38
+ LONG_CACHE_TIME = MINUTE * 15
39
+ private_constant :LONG_CACHE_TIME
40
+ SHORT_CACHE_TIME = MINUTE
41
+ private_constant :SHORT_CACHE_TIME
42
+
43
+ # @param config [Hash]
44
+ # @param workspaces [Checkoff::Workspaces]
45
+ # @param clients [Checkoff::Clients]
46
+ # @param client [Asana::Client]
47
+ def initialize(config: Checkoff::Internal::ConfigLoader.load(:asana),
48
+ workspaces: Checkoff::Workspaces.new(config: config),
49
+ clients: Checkoff::Clients.new(config: config),
50
+ client: clients.client)
51
+ @workspaces = workspaces
52
+ @client = client
53
+ end
54
+
55
+ # @param url [String]
56
+ # @param resource [Asana::Resources::Resource]
57
+ # @param attachment_name [String,nil]
58
+ # @param just_the_url [Boolean]
59
+ #
60
+ # @return [Asana::Resources::Attachment]
61
+ def create_attachment_from_url!(url,
62
+ resource,
63
+ attachment_name: nil,
64
+ just_the_url: false)
65
+ if just_the_url
66
+ create_attachment_from_url_alone!(url, resource, attachment_name: attachment_name)
67
+ else
68
+ create_attachment_from_downloaded_url!(url, resource, attachment_name: attachment_name)
69
+ end
70
+ end
71
+
72
+ # Writes contents of URL to a temporary file with the same
73
+ # extension as the URL using Net::HTTP, raising an exception if
74
+ # not succesful
75
+ #
76
+ # @param uri [URI]
77
+ #
78
+ # @return [Object]
79
+ # @sg-ignore
80
+ def download_uri(uri, &block)
81
+ Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
82
+ # @sg-ignore
83
+ request = Net::HTTP::Get.new(uri)
84
+ http.request(request) do |response|
85
+ # use a block to ensure the file is closed after we're done with it
86
+ raise("Unexpected response code: #{response.code}") unless response.code == '200'
87
+
88
+ write_tempfile_from_response(response) do |tempfile|
89
+ block.yield tempfile
90
+ end
91
+ end
92
+ end
93
+ end
94
+
95
+ # @sg-ignore
96
+ # @param response [Net::HTTPResponse]
97
+ #
98
+ # @yields [IO]
99
+ #
100
+ # @return [Object]
101
+ def write_tempfile_from_response(response)
102
+ Tempfile.create('checkoff') do |tempfile|
103
+ tempfile.binmode
104
+ # @sg-ignore
105
+ response.read_body do |chunk|
106
+ tempfile.write(chunk)
107
+ end
108
+ tempfile.rewind
109
+
110
+ yield tempfile
111
+ end
112
+ end
113
+
114
+ # @param url [String]
115
+ # @param resource [Asana::Resources::Resource]
116
+ # @param attachment_name [String,nil]
117
+ #
118
+ # @return [Asana::Resources::Attachment]
119
+ def create_attachment_from_downloaded_url!(url, resource, attachment_name:)
120
+ uri = URI(url)
121
+ attachment_name ||= File.basename(uri.path)
122
+ download_uri(uri) do |tempfile|
123
+ content_type ||= content_type_from_filename(attachment_name)
124
+ content_type ||= content_type_from_filename(uri.path)
125
+
126
+ resource.attach(filename: attachment_name, mime: content_type,
127
+ io: tempfile)
128
+ end
129
+ end
130
+
131
+ private
132
+
133
+ # @param url [String]
134
+ # @param resource [Asana::Resources::Resource]
135
+ # @param attachment_name [String,nil]
136
+ #
137
+ # @return [Asana::Resources::Attachment,nil]
138
+ def create_attachment_from_url_alone!(url, resource, attachment_name:)
139
+ with_params = {
140
+ 'parent' => resource.gid,
141
+ 'url' => url,
142
+ 'resource_subtype' => 'external',
143
+ 'name' => attachment_name,
144
+ }
145
+ options = {}
146
+ Asana::Resource.new(parse(client.post('/attachments', body: with_params, options: options)).first,
147
+ client: client)
148
+ end
149
+
150
+ # @param filename [String]
151
+ #
152
+ # @return [String,nil]
153
+ # @sg-ignore
154
+ def content_type_from_filename(filename)
155
+ # @sg-ignore
156
+ MIME::Types.type_for(filename)&.first&.content_type
157
+ end
158
+
159
+ # https://github.com/Asana/ruby-asana/blob/master/lib/asana/resource_includes/response_helper.rb#L7
160
+ # @param response [Faraday::Response]
161
+ #
162
+ # @return [Array<Hash, Hash>]
163
+ def parse(response)
164
+ data = response.body.fetch('data') do
165
+ raise("Unexpected response body: #{response.body}")
166
+ end
167
+ extra = response.body.except('data')
168
+ [data, extra]
169
+ end
170
+
171
+ # @return [Checkoff::Workspaces]
172
+ attr_reader :workspaces
173
+
174
+ # @return [Asana::Client]
175
+ attr_reader :client
176
+
177
+ # bundle exec ./attachments.rb
178
+ # :nocov:
179
+ class << self
180
+ # @return [void]
181
+ def run
182
+ # @sg-ignore
183
+ # @type [String]
184
+ gid = ARGV[0] || raise('Please pass task gid as first argument')
185
+ # @sg-ignore
186
+ # @type [String]
187
+ url = ARGV[1] || raise('Please pass attachment URL as second argument')
188
+
189
+ tasks = Checkoff::Tasks.new
190
+ attachments = Checkoff::Attachments.new
191
+ task = tasks.task_by_gid(gid)
192
+ attachment = attachments.create_attachment_from_url!(url, task)
193
+ puts "Results: #{attachment.inspect}"
194
+ end
195
+ end
196
+ # :nocov:
197
+ end
198
+ end
199
+
200
+ # :nocov:
201
+ abs_program_name = File.expand_path($PROGRAM_NAME)
202
+ Checkoff::Attachments.run if abs_program_name == File.expand_path(__FILE__)
203
+ # :nocov:
@@ -3,5 +3,5 @@
3
3
  # Command-line and gem client for Asana (unofficial)
4
4
  module Checkoff
5
5
  # Version of library
6
- VERSION = '0.161.0'
6
+ VERSION = '0.162.0'
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: checkoff
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.161.0
4
+ version: 0.162.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vince Broz
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: mime-types
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  description:
84
98
  email:
85
99
  - vince@broz.cc
@@ -129,6 +143,7 @@ files:
129
143
  - exe/checkoff
130
144
  - fix.sh
131
145
  - lib/checkoff.rb
146
+ - lib/checkoff/attachments.rb
132
147
  - lib/checkoff/cli.rb
133
148
  - lib/checkoff/clients.rb
134
149
  - lib/checkoff/create-entity.sh