-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
meet.cr
198 lines (181 loc) · 6.39 KB
/
meet.cr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# meet -- start a meeting quickly.
# Copyright © 2020 Yana Chen <[email protected]>
# Copyright © 2020 - 2022 Ryan Prior <[email protected]>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <https://www.gnu.org/licenses/>.
require "option_parser"
require "colorize"
require "yaml"
require "readline"
require "./base58"
config_home = ENV.fetch("XDG_CONFIG_HOME", %Q[#{ENV["HOME"]}/.config])
meet_dir = "#{config_home}/meet"
settings_file = "#{meet_dir}/settings.yml"
settings = if File.exists?(settings_file)
YAML.parse(File.read(settings_file)).as_h
else Hash(String, YAML::Any).new end
base_url = settings.fetch("base_url", YAML::Any.new "meet.jit.si").as_s
secure_name = settings.fetch("secure_name", YAML::Any.new true).as_bool
open_link = false
open_immediate = false
keybase_recipient : String? = nil
copy_link = false
meeting_name = ["meeting"]
enum TitleStyle
SnakeCase
Dash
TitleCase
ScreamCase
Heart
Custom
end
name_style = TitleStyle::TitleCase
custom_text = ""
def title(style, words, custom_text="")
omit_chars = "/#?"
words = words.map &.tr(omit_chars, ".")
case style
when TitleStyle::SnakeCase
words.join "_"
when TitleStyle::Dash
words.join "-"
when TitleStyle::TitleCase
words.map(&.capitalize).join
when TitleStyle::ScreamCase
words.map(&.upcase).join("👏️") + "🗯️"
when TitleStyle::Heart
"❣️" + words.join("❤️") + "❣️"
when TitleStyle::Custom
words.join(custom_text)
else raise "unknown title style"
end
end
OptionParser.parse do |parser|
parser.banner = "Usage: meet [arguments] [meeting name]"
parser.on("-s", "--snake", "use snake_case for meeting title") {
name_style = TitleStyle::SnakeCase
}
parser.on("-d", "--dash", "use dashes for meeting title") {
name_style = TitleStyle::Dash
}
parser.on("-t", "--title", "use TitleCase for meeting title") {
name_style = TitleStyle::TitleCase
}
parser.on("-S", "--shout", "use SHOUT👏️CASE🗯️ for meeting title") {
name_style = TitleStyle::ScreamCase
}
parser.on("-3", "--heart", "use ❣️heart❤️style❣️ for meeting title") {
name_style = TitleStyle::Heart
}
parser.on("-j TEXT", "--emoji=TEXT", "put TEXT between words of meeting title") do |text|
name_style = TitleStyle::Custom
custom_text = text
end
parser.on("-o", "--open", "open URL in your browser after a short pause") {
open_link = true
}
parser.on("-O", "--open-immediate", "open URL in your browser immediately") {
open_link = true
open_immediate = true
}
parser.on("-c", "--copy", "copy URL to clipboard using xsel") {
copy_link = true
}
parser.on("-k USER", "--send-kb=USER", "send URL to USER on Keybase") do |user|
keybase_recipient = user
end
parser.on("-u URL", "--use=URL", "url to use") do |url|
base_url = url
end
parser.on("-i", "--insecure", "omit secure-random portion of meeting URL") {
secure_name = false
}
parser.on("", "--secure", "include secure-random portion of meeting URL") {
secure_name = true
}
parser.on("-v", "--version", "show version information") do
version = {{read_file("./shard.yml")
.lines
.select(&.starts_with? "version")
.first
}}.split(/: */).last
git = {{"#{`git rev-parse HEAD`}".strip}}
puts "meet version #{version} (#{git})"
exit
end
parser.on("", "--init", "⚙️ initialize meet settings") do
Dir.mkdir_p(meet_dir)
new_settings = Hash(String, String | Bool).new
input = Readline.readline("Base url (#{base_url}): ")
new_settings["base_url"] = case input
when Nil
base_url
when String
input.empty? ? base_url : input.strip
else raise "unexpected input"
end
input = Readline.readline("Add random letters to URL for security? (Y/n): ")
new_settings["secure_name"] = case input
when Nil
true
when String
case input
when ""
true
when /^(([yY](es)?)|([tT](rue)?))$/
true
when /^(([nN]o?)|([fF](alse)?))$/
false
else
STDERR.puts "meet: fatal: expected y/n, got: #{input}"
exit 1
end
else raise "unexpected input"
end
File.open("#{settings_file}", "w") do |f|
f.puts(new_settings.to_yaml)
end
STDERR.puts "📝 wrote config to #{settings_file}"
exit
end
parser.on("-h", "--help", "show this help") do
puts parser
exit
end
parser.unknown_args do |args|
meeting_name = args unless args.empty?
end
end
def super_secure_string
Base58.random(6)
end
title_text = title(name_style, meeting_name, custom_text)
link = ["https:/", base_url, secure_name ? super_secure_string : nil, title_text].compact.join '/'
puts link.colorize :blue
if copy_link
`echo -n "#{link}" | xsel -bi`
c = "c".colorize.mode :underline
puts "🚀️ #{c}opied to clipboard!"
end
if keybase_recipient
`keybase chat send --private "#{keybase_recipient}" "#{link}"`
k = "k".colorize.mode :underline
whom = keybase_recipient.colorize :light_yellow
puts "📨️ sent lin#{k} to #{whom} on Keybase!"
end
if open_link
o = "o".colorize.mode :underline
puts "🌍️ #{o}pening in your browser…"
sleep(0.5.seconds) unless open_immediate
`xdg-open #{link}`
end