zoom_launcher 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c4ca63f84f5c8da5810082955ee23f085a2e4848
4
+ data.tar.gz: 2390d29c2430bdc57809cdf326a2437c69659c46
5
+ SHA512:
6
+ metadata.gz: e4b9a62f6e889891e5d38efea74ee9aee274ea1813a95974d551930e5f626035fb961e476782f0bec6e9a3f39549967958fc1321095af5305bdd5685c4c5c4bc
7
+ data.tar.gz: 7a03a9247007aa4bdd2b366649a1dec3ccd2f7426f46aa2b6e8e38266f7009b3de3261dea56b771146c87fa1c4e0366e3a1c95a4d7cd20104cbdc98870d1f861
@@ -0,0 +1,4 @@
1
+ .env
2
+ Gemfile.lock
3
+ spec/examples.txt
4
+ *.gem
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1,20 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.3
3
+
4
+ Security/Eval:
5
+ Enabled: false
6
+
7
+ Style/Documentation:
8
+ Enabled: false
9
+
10
+ Metrics/LineLength:
11
+ Enabled: false
12
+
13
+ Metrics/BlockLength:
14
+ Enabled: false
15
+
16
+ Metrics/AbcSize:
17
+ Enabled: false
18
+
19
+ Metrics/MethodLength:
20
+ Enabled: false
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Ben Balter
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,28 @@
1
+ # Zoom Launcher
2
+
3
+ A command line tool for joining your next Zoom meeting.
4
+
5
+ ## Usage
6
+
7
+ ```
8
+ $ zoom
9
+ Your next Zoom meeting is "Some important meeting".
10
+ It is scheduled to start in 3 minutes.
11
+
12
+ Opening https://github.zoom.us/j/XXX...
13
+ Oh, and here's the URL in case you need it: https://www.google.com/calendar/event?eid=XXX
14
+ ```
15
+
16
+ ## Installation
17
+
18
+ `gem install zoom_launcher`
19
+
20
+ ## Setup
21
+
22
+ In order to use Zoom Launcher, you need to create an OAuth app and authorize it to access your calendar:
23
+
24
+ 1. Go to https://console.developers.google.com and create a new project
25
+ 2. Click "Credentials on the left size and create a new credential for that project"
26
+ 3. Create a new OAuth credential, and download the resulting JSON file
27
+ 4. Move the file to `~/.config/google/client_secrets.json`
28
+ 5. Run `zoom auth` and follow the instructions to authorize the app
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative '../lib/zoom_launcher'
5
+
6
+ Dotenv.load
7
+ ZoomLauncher::CLI.start(ARGV)
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Google
4
+ module Apis
5
+ module CalendarV3
6
+ class Event
7
+ MEETING_URL_REGEX = %r{https://.*\.zoom\.us/j/\d+}
8
+ include ActionView::Helpers::DateHelper
9
+
10
+ def meeting_url
11
+ matches = (location + description).match(MEETING_URL_REGEX)
12
+ matches[0] if matches
13
+ end
14
+
15
+ def already_started?
16
+ start.date_time <= DateTime.now
17
+ end
18
+
19
+ def more_than_five_minutes_from_now?
20
+ start.date_time.to_time >= (DateTime.now.to_time + 5 * 60)
21
+ end
22
+
23
+ def start_time_in_words
24
+ distance = time_ago_in_words(start.date_time)
25
+ if already_started?
26
+ "#{distance} ago".bold.red
27
+ else
28
+ "in #{distance}".bold
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dotenv'
4
+ require 'google/apis/calendar_v3'
5
+ require 'action_view'
6
+ require 'action_view/helpers'
7
+ require 'colored'
8
+ require 'googleauth'
9
+ require 'googleauth/stores/file_token_store'
10
+ require 'fileutils'
11
+ require 'thor'
12
+ require 'os'
13
+
14
+ require_relative 'google/apis/calendar_v3/event'
15
+
16
+ module ZoomLauncher
17
+ autoload :CLI, 'zoom_launcher/cli'
18
+ autoload :GoogleAuth, 'zoom_launcher/google_auth'
19
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ZoomLauncher
4
+ class CLI < GoogleAuth
5
+ CALENDAR = 'primary'
6
+ ARGUMENTS = {
7
+ single_events: true,
8
+ order_by: 'startTime',
9
+ time_min: Time.now.iso8601,
10
+ q: 'zoom.us',
11
+ max_results: 5
12
+ }.freeze
13
+ default_task :launch
14
+
15
+ desc 'launch', 'Launch your next zoom meeting'
16
+ def launch
17
+ auth
18
+ if next_event.meeting_url
19
+ puts "Your next Zoom meeting is \"#{next_event.summary.bold}\"."
20
+ is_was = next_event.already_started? ? 'was' : 'is'
21
+ puts "It #{is_was} scheduled to start #{next_event.start_time_in_words}."
22
+ puts
23
+
24
+ if next_event.more_than_five_minutes_from_now?
25
+ puts "Here's the Zoom URL: #{next_event.meeting_url.bold}"
26
+ else
27
+ puts "Opening #{next_event.meeting_url.bold}..."
28
+ `open #{next_event.meeting_url}`
29
+
30
+ end
31
+ puts "Oh, and here's the URL in case you need it: #{next_event.html_link}"
32
+ else
33
+ puts "Can't find any upcomming Zoom meetings"
34
+ end
35
+ end
36
+
37
+ desc 'auth', 'authorize CLI with Google Calendar'
38
+ def auth
39
+ calendar.authorization = user_credentials_for(
40
+ Google::Apis::CalendarV3::AUTH_CALENDAR
41
+ )
42
+ end
43
+
44
+ desc 'logout', 'Deauthorize this computer from accessing your calendar'
45
+ def logout
46
+ FileUtils.rm_rf token_store_path
47
+ end
48
+
49
+ no_commands do
50
+ def calendar
51
+ @calendar ||= Google::Apis::CalendarV3::CalendarService.new
52
+ end
53
+
54
+ def events
55
+ @events ||= calendar.list_events(CALENDAR, ARGUMENTS)
56
+ end
57
+
58
+ def next_event
59
+ @next_event ||= events.items.first
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2016 Google Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ # Base command line module for samples. Provides authorization support,
18
+ # either using application default credentials or user authorization
19
+ # depending on the use case.
20
+ module ZoomLauncher
21
+ class GoogleAuth < Thor
22
+ include Thor::Actions
23
+
24
+ OOB_URI = 'urn:ietf:wg:oauth:2.0:oob'
25
+
26
+ class_option :user, type: :string
27
+ class_option :api_key, type: :string
28
+
29
+ no_commands do
30
+ # Returns the path to the client_secrets.json file.
31
+ def client_secrets_path
32
+ return ENV['GOOGLE_CLIENT_SECRETS'] if ENV.key?('GOOGLE_CLIENT_SECRETS')
33
+ well_known_path_for('client_secrets.json')
34
+ end
35
+
36
+ # Returns the path to the token store.
37
+ def token_store_path
38
+ return ENV['GOOGLE_CREDENTIAL_STORE'] if ENV.key?('GOOGLE_CREDENTIAL_STORE')
39
+ well_known_path_for('credentials.yaml')
40
+ end
41
+
42
+ # Builds a path to a file in $HOME/.config/google (or %APPDATA%/google,
43
+ # on Windows)
44
+ def well_known_path_for(file)
45
+ if OS.windows?
46
+ dir = ENV.fetch('HOME') { ENV['APPDATA'] }
47
+ File.join(dir, 'google', file)
48
+ else
49
+ File.join(ENV['HOME'], '.config', 'google', file)
50
+ end
51
+ end
52
+
53
+ # Returns application credentials for the given scope.
54
+ def application_credentials_for(scope)
55
+ Google::Auth.get_application_default(scope)
56
+ end
57
+
58
+ # Returns user credentials for the given scope. Requests authorization
59
+ # if requrired.
60
+ def user_credentials_for(scope)
61
+ FileUtils.mkdir_p(File.dirname(token_store_path))
62
+
63
+ client_id = if ENV['GOOGLE_CLIENT_ID']
64
+ Google::Auth::ClientId.new(ENV['GOOGLE_CLIENT_ID'], ENV['GOOGLE_CLIENT_SECRET'])
65
+ else
66
+ Google::Auth::ClientId.from_file(client_secrets_path)
67
+ end
68
+ token_store = Google::Auth::Stores::FileTokenStore.new(file: token_store_path)
69
+ authorizer = Google::Auth::UserAuthorizer.new(client_id, scope, token_store)
70
+
71
+ user_id = options[:user] || 'default'
72
+
73
+ credentials = authorizer.get_credentials(user_id)
74
+ if credentials.nil?
75
+ url = authorizer.get_authorization_url(base_url: OOB_URI)
76
+ `open #{url}`
77
+ code = ask 'Enter the authorization code:'
78
+ credentials = authorizer.get_and_store_credentials_from_code(
79
+ user_id: user_id, code: code, base_url: OOB_URI
80
+ )
81
+ end
82
+ credentials
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ZoomLauncher
4
+ VERSION = '0.1.0'
5
+ end
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+
3
+ bundle install
@@ -0,0 +1,7 @@
1
+ #!/bin/sh
2
+
3
+ set -e
4
+
5
+ bundle exec rspec
6
+ bundle exec rubocop -S -D
7
+ bundle exec gem build zoom_launcher.gemspec
@@ -0,0 +1,4 @@
1
+ #!/bin/sh
2
+
3
+ script/bootstrap
4
+ bin/zoom auth
@@ -0,0 +1,37 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ lib = File.expand_path('../lib', __FILE__)
5
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
+ require 'zoom_launcher/version'
7
+
8
+ Gem::Specification.new do |spec|
9
+ spec.name = 'zoom_launcher'
10
+ spec.version = ZoomLauncher::VERSION
11
+ spec.authors = ['Ben Balter']
12
+ spec.email = ['ben.balter@github.com']
13
+
14
+ spec.summary = 'A command line tool for joining your next Zoom meeting'
15
+ spec.homepage = "https://github.com/benbalter/zoom-launcher"
16
+ spec.license = 'MIT'
17
+
18
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
19
+ f.match(%r{^(test|spec|features)/})
20
+ end
21
+ spec.bindir = 'bin'
22
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
23
+ spec.require_paths = ['lib']
24
+
25
+ spec.add_dependency 'actionview', '~> 5.0'
26
+ spec.add_dependency 'colored', '~> 1.2'
27
+ spec.add_dependency 'dotenv', '~> 2.2'
28
+ spec.add_dependency 'google-api-client', '~> 0.10'
29
+ spec.add_dependency 'os', '~> 0.9'
30
+ spec.add_dependency 'thor', '~> 0.19'
31
+ spec.add_development_dependency 'bundler', '~> 1.14'
32
+ spec.add_development_dependency 'rake', '~> 10.0'
33
+ spec.add_development_dependency 'rspec', '~> 3.0'
34
+ spec.add_development_dependency 'rubocop', '~> 0.48'
35
+ spec.add_development_dependency 'webmock', '~> 2.3'
36
+ spec.add_development_dependency 'timecop', '~> 0.8'
37
+ end
metadata ADDED
@@ -0,0 +1,229 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: zoom_launcher
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ben Balter
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-03-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: actionview
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '5.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '5.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: colored
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: dotenv
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.2'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: google-api-client
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.10'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.10'
69
+ - !ruby/object:Gem::Dependency
70
+ name: os
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.9'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.9'
83
+ - !ruby/object:Gem::Dependency
84
+ name: thor
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.19'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.19'
97
+ - !ruby/object:Gem::Dependency
98
+ name: bundler
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.14'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.14'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '10.0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '10.0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rspec
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '3.0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '3.0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rubocop
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '0.48'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '0.48'
153
+ - !ruby/object:Gem::Dependency
154
+ name: webmock
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '2.3'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '2.3'
167
+ - !ruby/object:Gem::Dependency
168
+ name: timecop
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '0.8'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: '0.8'
181
+ description:
182
+ email:
183
+ - ben.balter@github.com
184
+ executables:
185
+ - zoom
186
+ extensions: []
187
+ extra_rdoc_files: []
188
+ files:
189
+ - ".gitignore"
190
+ - ".rspec"
191
+ - ".rubocop.yml"
192
+ - Gemfile
193
+ - LICENSE.md
194
+ - README.md
195
+ - bin/zoom
196
+ - lib/google/apis/calendar_v3/event.rb
197
+ - lib/zoom_launcher.rb
198
+ - lib/zoom_launcher/cli.rb
199
+ - lib/zoom_launcher/google_auth.rb
200
+ - lib/zoom_launcher/version.rb
201
+ - script/bootstrap
202
+ - script/cibuild
203
+ - script/setup
204
+ - zoom_launcher.gemspec
205
+ homepage: https://github.com/benbalter/zoom-launcher
206
+ licenses:
207
+ - MIT
208
+ metadata: {}
209
+ post_install_message:
210
+ rdoc_options: []
211
+ require_paths:
212
+ - lib
213
+ required_ruby_version: !ruby/object:Gem::Requirement
214
+ requirements:
215
+ - - ">="
216
+ - !ruby/object:Gem::Version
217
+ version: '0'
218
+ required_rubygems_version: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - ">="
221
+ - !ruby/object:Gem::Version
222
+ version: '0'
223
+ requirements: []
224
+ rubyforge_project:
225
+ rubygems_version: 2.6.11
226
+ signing_key:
227
+ specification_version: 4
228
+ summary: A command line tool for joining your next Zoom meeting
229
+ test_files: []