timely-app 1.0.1 → 1.0.4
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 +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +6 -0
- data/bin/timely-app +181 -0
- data/lib/timely-app/client.rb +6 -1
- data/lib/timely-app/version.rb +1 -1
- data/timely-app.gemspec +24 -15
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5fc2e1df8e95c1af4f14f67e40bd7849218fa6a25a7012b91d6c6bedba49875b
|
4
|
+
data.tar.gz: f10ba288aa8074824ee6cd2508e509564575ea0519c8502220e9b13bfd02cee9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e05a47853c2dfb6233e8ddca0bbb3f1250ebdc1618328f5694370e0128b0ae52606385ed8886230eb0a9df0a8ba7a620c01c4c258ca3f8ab57db3b8fcf33df5d
|
7
|
+
data.tar.gz: 9e384734bc8a02b3778927cad38cb4e667c40fbf7e91cb048007b0041818aa79c88c4e1831e86ce4c94cc6dd87bc1b2476ec5ff8b8763a59e841978f366b01e8
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -4,6 +4,8 @@
|
|
4
4
|
|
5
5
|
Ruby client for the [Timely API](https://dev.timelyapp.com).
|
6
6
|
|
7
|
+
Sponsored by [Kisko Labs](https://www.kiskolabs.com).
|
8
|
+
|
7
9
|
## Install
|
8
10
|
|
9
11
|
Using Bundler:
|
@@ -79,6 +81,10 @@ You can use [localhost.run](https://localhost.run/) to test callbacks locally.
|
|
79
81
|
|
80
82
|
There are large list of available tools for tunneling: [awesome-tunneling](https://github.com/anderspitman/awesome-tunneling)
|
81
83
|
|
84
|
+
## Acknowledgment
|
85
|
+
|
86
|
+
- thanks to [timcraft](https://github.com/timcraft) and the team for [Noko API client](https://github.com/timcraft/noko) that was used as starting point
|
87
|
+
|
82
88
|
## Contributing
|
83
89
|
|
84
90
|
Bug reports and pull requests are welcome on GitHub at https://github.com/amkisko/timely-app
|
data/bin/timely-app
ADDED
@@ -0,0 +1,181 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "yaml"
|
4
|
+
require "optparse"
|
5
|
+
require "timely-app"
|
6
|
+
|
7
|
+
module TimelyApp
|
8
|
+
class CLI
|
9
|
+
attr_reader :options, :client
|
10
|
+
|
11
|
+
def initialize(options = {})
|
12
|
+
@options = options
|
13
|
+
@client = TimelyApp::Client.new(
|
14
|
+
access_token: options[:access_token] || fetch_access_token,
|
15
|
+
account_id: options[:account_id] || fetch_account_id,
|
16
|
+
verbose: options[:verbose]
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_config(key)
|
21
|
+
read_config_file&.fetch(key, nil)
|
22
|
+
end
|
23
|
+
|
24
|
+
def set_config(key, value)
|
25
|
+
save_config_file(key => value)
|
26
|
+
end
|
27
|
+
|
28
|
+
def command_exists?(cmd)
|
29
|
+
return false if cmd.nil? || cmd.empty?
|
30
|
+
|
31
|
+
client.respond_to?(cmd)
|
32
|
+
end
|
33
|
+
|
34
|
+
def call(cmd, *args)
|
35
|
+
client.send(cmd, *args)
|
36
|
+
end
|
37
|
+
|
38
|
+
def auth(client_id, client_secret)
|
39
|
+
if !client_id || !client_secret
|
40
|
+
puts "Usage: timely-app auth CLIENT_ID CLIENT_SECRET"
|
41
|
+
exit 1
|
42
|
+
end
|
43
|
+
|
44
|
+
auth_client = TimelyApp::Client.new(verbose: options[:verbose])
|
45
|
+
auth_url = auth_client.get_oauth_authorize_url(
|
46
|
+
client_id: client_id,
|
47
|
+
redirect_uri: "urn:ietf:wg:oauth:2.0:oob"
|
48
|
+
)
|
49
|
+
puts "Visit this URL in your browser:"
|
50
|
+
puts auth_url
|
51
|
+
puts "\nEnter authorization code here:"
|
52
|
+
code = gets.chomp
|
53
|
+
begin
|
54
|
+
token = auth_client.post_oauth_token(
|
55
|
+
client_id: client_id,
|
56
|
+
client_secret: client_secret,
|
57
|
+
code: code,
|
58
|
+
redirect_uri: "urn:ietf:wg:oauth:2.0:oob",
|
59
|
+
grant_type: "authorization_code"
|
60
|
+
)
|
61
|
+
if options[:save]
|
62
|
+
save_config_file(
|
63
|
+
access_token: token.access_token,
|
64
|
+
refresh_token: token.refresh_token,
|
65
|
+
created_at: token.created_at
|
66
|
+
)
|
67
|
+
else
|
68
|
+
puts "\nAccess token:\n#{token.access_token}\n"
|
69
|
+
end
|
70
|
+
if options[:verbose]
|
71
|
+
puts "Token details: #{token.to_h}"
|
72
|
+
end
|
73
|
+
rescue TimelyApp::Error => e
|
74
|
+
puts "Authentication failed"
|
75
|
+
if options[:verbose]
|
76
|
+
puts "Code: #{code}"
|
77
|
+
puts "Response code: #{e.response.code}"
|
78
|
+
puts "Response: #{e.response.body}"
|
79
|
+
end
|
80
|
+
exit 1
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def config_file_path
|
87
|
+
Dir.home + "/.timelyrc"
|
88
|
+
end
|
89
|
+
|
90
|
+
def read_config_file
|
91
|
+
if File.exist?(config_file_path)
|
92
|
+
YAML.load_file(config_file_path)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def fetch_account_id
|
97
|
+
read_config_file&.fetch("account_id", nil)
|
98
|
+
end
|
99
|
+
|
100
|
+
def fetch_access_token
|
101
|
+
read_config_file&.fetch("access_token", nil)
|
102
|
+
end
|
103
|
+
|
104
|
+
def check_access_token
|
105
|
+
if !fetch_access_token
|
106
|
+
puts "No access token found. Run `timely-app auth` to get one."
|
107
|
+
exit 1
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def save_config_file(**options)
|
112
|
+
config = read_config_file || {}
|
113
|
+
config.merge!(options)
|
114
|
+
File.open(config_file_path, "w") do |f|
|
115
|
+
f.write(config.to_yaml)
|
116
|
+
end
|
117
|
+
puts "Saved to #{config_file_path}"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
options = {}
|
123
|
+
OptionParser.new do |opts|
|
124
|
+
opts.banner = "Usage: timely-app [command] [options]"
|
125
|
+
|
126
|
+
opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
|
127
|
+
options[:verbose] = v
|
128
|
+
end
|
129
|
+
|
130
|
+
opts.on("-a", "--account ACCOUNT", "Account name") do |a|
|
131
|
+
options[:account] = a
|
132
|
+
end
|
133
|
+
|
134
|
+
opts.on("-s", "--save", "Save changes to file") do |s|
|
135
|
+
options[:save] = s
|
136
|
+
end
|
137
|
+
end.parse!
|
138
|
+
|
139
|
+
cli = TimelyApp::CLI.new(options)
|
140
|
+
|
141
|
+
cmd = ARGV.shift
|
142
|
+
case cmd
|
143
|
+
when "auth"
|
144
|
+
client_id = ARGV.shift || ENV.fetch('TIMELY_CLIENT_ID')
|
145
|
+
client_secret = ARGV.shift || ENV.fetch('TIMELY_CLIENT_SECRET')
|
146
|
+
ARGV.clear
|
147
|
+
if client_id && client_secret
|
148
|
+
cli.auth(client_id, client_secret)
|
149
|
+
else
|
150
|
+
puts "Usage: timely-app auth CLIENT_ID CLIENT_SECRET"
|
151
|
+
exit 1
|
152
|
+
end
|
153
|
+
when "config"
|
154
|
+
if ARGV.length == 1
|
155
|
+
puts cli.get_config(ARGV.shift)
|
156
|
+
elsif ARGV.length == 2
|
157
|
+
cli.set_config(ARGV.shift, ARGV.shift)
|
158
|
+
else
|
159
|
+
puts "Usage: timely-app config [key] [value]"
|
160
|
+
exit 1
|
161
|
+
end
|
162
|
+
else
|
163
|
+
if cli.command_exists?(cmd)
|
164
|
+
args = ARGV.reduce({}){ |h, arg| k, v = arg.split("="); h[k] = v; h }
|
165
|
+
ARGV.clear
|
166
|
+
response = cli.call(cmd, *args)
|
167
|
+
case response
|
168
|
+
when Array
|
169
|
+
response.each do |r|
|
170
|
+
puts r.to_h
|
171
|
+
end
|
172
|
+
when TimelyApp::Record
|
173
|
+
puts response.to_h
|
174
|
+
else
|
175
|
+
puts response
|
176
|
+
end
|
177
|
+
else
|
178
|
+
puts "Unknown command: #{cmd}"
|
179
|
+
exit 1
|
180
|
+
end
|
181
|
+
end
|
data/lib/timely-app/client.rb
CHANGED
@@ -22,6 +22,7 @@ module TimelyApp
|
|
22
22
|
@http.use_ssl = true
|
23
23
|
|
24
24
|
@account_id = options[:account_id]
|
25
|
+
@verbose = options[:verbose] || ENV['VERBOSE'] || false
|
25
26
|
end
|
26
27
|
|
27
28
|
def get(path, params = nil)
|
@@ -30,6 +31,10 @@ module TimelyApp
|
|
30
31
|
|
31
32
|
private
|
32
33
|
|
34
|
+
def verbose?
|
35
|
+
!@verbose.nil?
|
36
|
+
end
|
37
|
+
|
33
38
|
def host_uri_join(path, params)
|
34
39
|
URI::join("https://#{@host}", Params.join(path, params)).to_s
|
35
40
|
end
|
@@ -57,7 +62,7 @@ module TimelyApp
|
|
57
62
|
|
58
63
|
response = @http.request(http_request)
|
59
64
|
|
60
|
-
if
|
65
|
+
if verbose?
|
61
66
|
puts ">> request: #{http_request.method} #{http_request.path} #{http_request.body}"
|
62
67
|
puts "<< response: #{http_request.method} #{http_request.path} #{response.code} #{response.body}"
|
63
68
|
end
|
data/lib/timely-app/version.rb
CHANGED
data/timely-app.gemspec
CHANGED
@@ -1,20 +1,29 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
|
-
s.name =
|
3
|
-
s.version =
|
4
|
-
|
2
|
+
s.name = "timely-app"
|
3
|
+
s.version = "1.0.4"
|
4
|
+
|
5
|
+
s.license = "MIT"
|
6
|
+
|
5
7
|
s.platform = Gem::Platform::RUBY
|
6
|
-
|
7
|
-
s.
|
8
|
-
s.
|
9
|
-
s.
|
10
|
-
s.
|
11
|
-
s.
|
12
|
-
s.required_ruby_version = '>= 1.9.3'
|
13
|
-
s.require_path = 'lib'
|
8
|
+
|
9
|
+
s.authors = ["Andrei Makarov"]
|
10
|
+
s.email = ["andrei@kiskolabs.com"]
|
11
|
+
s.homepage = "https://github.com/amkisko/timely-app"
|
12
|
+
s.description = "Ruby client for the Timely API"
|
13
|
+
s.summary = "See description"
|
14
14
|
s.metadata = {
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
"homepage" => "https://github.com/amkisko/timely-app",
|
16
|
+
"source_code_uri" => "https://github.com/amkisko/timely-app",
|
17
|
+
"bug_tracker_uri" => "https://github.com/amkisko/timely-app/issues",
|
18
|
+
"changelog_uri" => "https://github.com/amkisko/timely-app/blob/main/CHANGELOG.md",
|
19
|
+
"rubygems_mfa_required" => "true"
|
19
20
|
}
|
21
|
+
|
22
|
+
s.files = Dir.glob("lib/**/*.rb") + Dir.glob("bin/**/*") + %w(CHANGELOG.md LICENSE.md README.md timely-app.gemspec)
|
23
|
+
|
24
|
+
s.bindir = "bin"
|
25
|
+
s.executables = ["timely-app"]
|
26
|
+
|
27
|
+
s.required_ruby_version = ">= 1.9.3"
|
28
|
+
s.require_path = "lib"
|
20
29
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: timely-app
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrei Makarov
|
@@ -13,13 +13,15 @@ dependencies: []
|
|
13
13
|
description: Ruby client for the Timely API
|
14
14
|
email:
|
15
15
|
- andrei@kiskolabs.com
|
16
|
-
executables:
|
16
|
+
executables:
|
17
|
+
- timely-app
|
17
18
|
extensions: []
|
18
19
|
extra_rdoc_files: []
|
19
20
|
files:
|
20
21
|
- CHANGELOG.md
|
21
22
|
- LICENSE.md
|
22
23
|
- README.md
|
24
|
+
- bin/timely-app
|
23
25
|
- lib/timely-app.rb
|
24
26
|
- lib/timely-app/client.rb
|
25
27
|
- lib/timely-app/client/accounts.rb
|
@@ -50,7 +52,8 @@ metadata:
|
|
50
52
|
homepage: https://github.com/amkisko/timely-app
|
51
53
|
source_code_uri: https://github.com/amkisko/timely-app
|
52
54
|
bug_tracker_uri: https://github.com/amkisko/timely-app/issues
|
53
|
-
changelog_uri: https://github.com/amkisko/timely-app/blob/main/
|
55
|
+
changelog_uri: https://github.com/amkisko/timely-app/blob/main/CHANGELOG.md
|
56
|
+
rubygems_mfa_required: 'true'
|
54
57
|
post_install_message:
|
55
58
|
rdoc_options: []
|
56
59
|
require_paths:
|