campline 0.0.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,7 +1,8 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- gem "tinder"
3
+ gem "tinder", "1.8.0"
4
4
  gem "cli-colorize"
5
+ gem "mixlib-cli"
5
6
 
6
7
  # Add dependencies to develop your gem here.
7
8
  # Include everything needed to run rake, tests, features, etc.
@@ -2,9 +2,15 @@
2
2
 
3
3
  A tiny Campfire client.
4
4
 
5
- Usage: campline <domain> <room> <username>
5
+ Usage:
6
6
 
7
- The client will prompt for your password and that's it - you're in!
7
+ campline -d <domain> -r <room> -u <username>
8
+
9
+ OR
10
+
11
+ campline -d <domain> -r <room> -k <api_key>
12
+
13
+ The client will prompt for your password if you supply your username. And that's it - you're in!
8
14
 
9
15
  == Contributing to campline
10
16
 
@@ -16,6 +22,13 @@ The client will prompt for your password and that's it - you're in!
16
22
  * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
17
23
  * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
18
24
 
25
+ == To do/planned list
26
+
27
+ * Auto-reconnect on timeout
28
+ * Revamp command line in order to support login with api keys
29
+ * Nicer error messages
30
+ * Convert images to ascii art 8-)
31
+
19
32
  == Copyright
20
33
 
21
34
  Partially based on campfire-cli, by Petyo Ivanov. STDIN/OUT tricks by http://www.rubyquiz.com/quiz45.html (thanks @cfcosta!)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.2
1
+ 0.2.0
@@ -1,14 +1,12 @@
1
- #!/usr/bin/ruby
1
+ #!/usr/bin/env ruby
2
2
 
3
+ require 'rubygems'
4
+ require "cli_config"
3
5
  require "campline"
4
6
 
5
- if ARGV.size != 3
6
- puts "Usage: campline <domain> <room> <username>"
7
- exit 1
8
- end
9
-
10
7
  begin
11
- domain, room, username = *ARGV
8
+ config = CliConfig.new
9
+ config.load!
12
10
 
13
11
  begin
14
12
  %x{stty -echo}
@@ -18,7 +16,9 @@ begin
18
16
  %x{stty raw -echo}
19
17
  end
20
18
 
21
- Campline::Client.new(domain, room, username, password).listen!
19
+ Campline::Client.new(config.data.merge(:password => password)).listen!
20
+ rescue => e
21
+ puts e.message
22
22
  ensure
23
23
  %x{stty -raw echo}
24
24
  end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "campline"
8
- s.version = "0.0.2"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Herval Freire"]
12
- s.date = "2012-07-02"
12
+ s.date = "2012-09-17"
13
13
  s.description = "A tiny Campfire client for command line"
14
14
  s.email = "hervalfreire@gmail.com"
15
15
  s.executables = ["campline"]
@@ -28,36 +28,40 @@ Gem::Specification.new do |s|
28
28
  "bin/campline",
29
29
  "campline.gemspec",
30
30
  "lib/campline.rb",
31
+ "lib/cli_config.rb",
31
32
  "spec/campline_spec.rb",
32
33
  "spec/spec_helper.rb"
33
34
  ]
34
35
  s.homepage = "http://github.com/herval/campline"
35
36
  s.licenses = ["MIT"]
36
37
  s.require_paths = ["lib"]
37
- s.rubygems_version = "1.8.24"
38
+ s.rubygems_version = "1.8.15"
38
39
  s.summary = "A tiny Campfire client"
39
40
 
40
41
  if s.respond_to? :specification_version then
41
42
  s.specification_version = 3
42
43
 
43
44
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
44
- s.add_runtime_dependency(%q<tinder>, [">= 0"])
45
+ s.add_runtime_dependency(%q<tinder>, ["= 1.8.0"])
45
46
  s.add_runtime_dependency(%q<cli-colorize>, [">= 0"])
47
+ s.add_runtime_dependency(%q<mixlib-cli>, [">= 0"])
46
48
  s.add_development_dependency(%q<pry>, [">= 0"])
47
49
  s.add_development_dependency(%q<rspec>, ["~> 2.8.0"])
48
50
  s.add_development_dependency(%q<bundler>, [">= 0"])
49
51
  s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
50
52
  else
51
- s.add_dependency(%q<tinder>, [">= 0"])
53
+ s.add_dependency(%q<tinder>, ["= 1.8.0"])
52
54
  s.add_dependency(%q<cli-colorize>, [">= 0"])
55
+ s.add_dependency(%q<mixlib-cli>, [">= 0"])
53
56
  s.add_dependency(%q<pry>, [">= 0"])
54
57
  s.add_dependency(%q<rspec>, ["~> 2.8.0"])
55
58
  s.add_dependency(%q<bundler>, [">= 0"])
56
59
  s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
57
60
  end
58
61
  else
59
- s.add_dependency(%q<tinder>, [">= 0"])
62
+ s.add_dependency(%q<tinder>, ["= 1.8.0"])
60
63
  s.add_dependency(%q<cli-colorize>, [">= 0"])
64
+ s.add_dependency(%q<mixlib-cli>, [">= 0"])
61
65
  s.add_dependency(%q<pry>, [">= 0"])
62
66
  s.add_dependency(%q<rspec>, ["~> 2.8.0"])
63
67
  s.add_dependency(%q<bundler>, [">= 0"])
@@ -1,75 +1,123 @@
1
- require 'rubygems'
1
+ # encoding: utf-8
2
+
3
+ require 'time'
2
4
  require 'thread'
3
5
  require 'tinder'
4
6
  require 'io/wait'
5
7
  require 'yaml'
6
8
  require 'cli-colorize'
7
9
 
10
+ unless Gem::Specification::find_all_by_name('ruby-growl').empty?
11
+ require 'ruby-growl'
12
+ $growl = Growl.new "localhost", "ruby-growl", "UDP"
13
+ else
14
+ print "Install the ruby-growl to enable Growl notification support\r\n"
15
+ end
16
+
8
17
  module Campline
9
18
 
19
+ GO_BACK = "\r\e[0K" # return to beginning of line and use the ANSI clear command "\e" or "\003"
20
+
10
21
  class Client
11
22
  include Tinder
12
23
  include CLIColorize
13
24
 
14
- def initialize(domain, room, username, password)
15
- @domain = domain
16
- @room = room
17
- @username = username
18
- @password = password
19
- @user_id = nil
25
+ def initialize(options)
26
+ @config = options
27
+ @me = nil
20
28
  @room_users = []
21
29
  @output_buffer = ""
22
30
  @input_buffer = Queue.new
23
31
  end
24
32
 
25
- def print_message(msg)
26
- return if (msg[:user] && msg[:user][:id] == @user_id)
27
- case msg[:type]
28
- when "SoundMessage" then
29
- @input_buffer << "#{green(msg[:user][:name])} played some annoying sound"
30
- when "PasteMessage" then
31
- @input_buffer << "#{green(msg[:user][:name])}: #{msg[:body]}"
32
- when "TextMessage" then
33
- @input_buffer << "#{green(msg[:user][:name])}: #{msg[:body]}"
33
+ def print_message(msg, flush = true, ignore_current_user = true)
34
+ return if msg[:user].nil?
35
+
36
+ return if (msg[:user] && msg[:user][:id] == @me[:id] && ignore_current_user)
37
+ @input_buffer << case msg[:type]
38
+ when "KickMessage","LeaveMessage"
39
+ white("#{msg[:user][:name]} left the room")
40
+ when "EnterMessage"
41
+ white("#{msg[:user][:name]} joined the room")
42
+ when "SoundMessage"
43
+ "#{green(msg[:user][:name])} #{white('played some sound. Sound is for dummies.')}"
44
+ when "PasteMessage", "TextMessage", "TweetMessage"
45
+ "#{green(msg[:user][:name])}: #{msg[:body]}"
46
+ else
47
+ msg
34
48
  end
49
+ flush_input_buffer! if flush
50
+ end
51
+
52
+ def print_inline(msg)
53
+ print "#{GO_BACK}#{msg}\r\n"
54
+ show_prompt
35
55
  end
36
56
 
37
57
  def commands
38
58
  {
39
- "/help" => lambda { print "\r\nAvailable commands: /users (list users on the room), /exit (quit!)"},
40
- "/exit" => lambda { @campfire_room.leave; exit; },
41
- "/users" => lambda { list_users }
59
+ "/help" => lambda { print_inline(white("Available commands: /users (list users on the room), /exit (quit!), /log (show latest messages)")) },
60
+ "/exit" => lambda { exit! },
61
+ "/users" => lambda { list_users },
62
+ "/log" => lambda { print_transcript }
42
63
  }
43
64
  end
44
65
 
45
66
  def list_users
46
- print white("\r\nIn the room right now: #{@room_users.join(', ')}")
67
+ update_user_list
68
+ print_inline(white("In the room right now: #{@room_users.collect(&:name).join(', ')}"))
47
69
  end
48
70
 
49
- def update_user_list
50
- new_list = @campfire_room.users.collect(&:name)
51
- @room_users = new_list if @room_users.empty?
71
+ def print_transcript
72
+ update_user_list
73
+ transcript = @campfire_room.transcript(Date.today) || []
74
+
75
+ # load user names, as these don't come on the transcript...
76
+ talking_users = {}
77
+ @room_users.each do |user|
78
+ talking_users[user.id] = user
79
+ end
52
80
 
53
- new_guys = new_list - @room_users
54
- new_guys.each { |n| @input_buffer << "#{n} joined the room" }
81
+ transcript.reverse[0..15].reverse.each do |m|
82
+ print_message(m.merge(:user => talking_users[m[:user_id]], :type => "TextMessage", :body => m[:message]), false, false)
83
+ end
84
+ flush_input_buffer!
85
+ print_inline(white("Last message received at #{transcript[-1][:timestamp]}"))
86
+ end
55
87
 
56
- dead_guys = @room_users - new_list
57
- dead_guys.each { |n| @input_buffer << "#{n} left the room" }
58
- @room_users = new_list
88
+ def update_user_list
89
+ @room_users = @campfire_room.users
59
90
  end
60
91
 
61
92
  def backspace!
62
93
  @output_buffer.chop!
63
- go_back = "\r\e[0K" # return to beginning of line and use the ANSI clear command "\e" or "\003"
64
- print "#{go_back}> #{@output_buffer}"
94
+ print "#{GO_BACK}> #{@output_buffer}"
65
95
  end
66
96
 
67
97
  def show_prompt
68
- puts "\r\n"
69
- print "> #{@output_buffer}"
98
+ print "#{GO_BACK}> #{@output_buffer}"
70
99
  $stdout.flush
71
100
  end
72
101
 
102
+ def exit!
103
+ @campfire_room.leave
104
+ print "\r\nGoodbye..."
105
+ exit
106
+ end
107
+
108
+ def flush_input_buffer!
109
+ unless @input_buffer.empty? # read from server
110
+ notify_growl!
111
+ print GO_BACK
112
+ print "#{@input_buffer.shift}\r\n" until @input_buffer.empty?
113
+ show_prompt
114
+ end
115
+ end
116
+
117
+ def notify_growl!
118
+ $growl.notify("ruby-growl", "ruby-growl", "Greetings!") if $growl
119
+ end
120
+
73
121
  def blue(str)
74
122
  colorize(str, :foreground => :blue)
75
123
  end
@@ -87,74 +135,87 @@ module Campline
87
135
  end
88
136
 
89
137
  def send_line!
90
- if commands[@output_buffer]
91
- commands[@output_buffer].call
92
- else
93
- @campfire_room.speak @output_buffer
94
- end
138
+ buffer = @output_buffer
95
139
  @output_buffer = ""
140
+ if commands[buffer]
141
+ commands[buffer].call
142
+ else
143
+ return if buffer.blank?
144
+ Thread.new do
145
+ begin
146
+ print_message({ :user => @me, :type => "TextMessage", :body => buffer }, true, false)
147
+ @campfire_room.speak(buffer)
148
+ rescue => e
149
+ print_inline(white("A message could not be sent: #{buffer}"))
150
+ end
151
+ end
152
+ end
96
153
  end
97
154
 
98
- def listen!
99
- puts "Logging in...\r\n"
100
- begin
101
- campfire = Campfire.new @domain, :username => @username, :password => @password, :ssl => true
102
- rescue Tinder::AuthenticationFailed
103
- raise "There was an authentication error - check your username and password\r\n"
104
- end
105
- @user_id = campfire.me.id
106
-
107
- puts "Joining #{@room}...\r\n"
108
- @campfire_room = campfire.find_room_by_name @room
109
- raise "Can't find room named #{@room}!\r\n" if @campfire_room.nil?
110
-
111
- @campfire_room.join
112
- update_user_list
113
-
114
- puts "You're up! For a list of available commands, type #{highlight('/help')}\r\n"
115
-
116
- Thread.new(@campfire_room) do |listener|
155
+ def start_message_listener!(room)
156
+ Thread.new do
117
157
  while true
118
- listener.listen do |msg|
119
- print_message msg
158
+ begin
159
+ room.listen do |msg|
160
+ print_message(msg)
161
+ end
162
+ rescue => e
163
+ # ignore errors!
164
+ # puts e
120
165
  end
121
166
  end
122
167
  end
168
+ end
123
169
 
170
+ def start_typing_agent!
124
171
  Thread.new do
125
- while true
126
- sleep(10)
127
- update_user_list
172
+ while character = $stdin.getc
173
+ case character
174
+ when ?\C-c
175
+ exit!
176
+ when ?\r, ?\n
177
+ send_line!
178
+ show_prompt
179
+ when ?\e # arrow keys & fn keys
180
+ # do nothing
181
+ when ?\u007F, ?\b
182
+ backspace!
183
+ else
184
+ @output_buffer << character
185
+ print character.chr
186
+ $stdout.flush
187
+ end
128
188
  end
129
189
  end
190
+ end
130
191
 
131
- Thread.new do
132
- while true #msg = Readline.readline('> ', true)
133
- if $stdin.ready?
134
- character = $stdin.getc
135
- case character
136
- when ?\C-c
137
- break
138
- when ?\r, ?\n
139
- send_line!
140
- show_prompt
141
- when ?\u007F, ?\b
142
- backspace!
143
- else
144
- @output_buffer << character
145
- print character.chr
146
- $stdout.flush
147
- end
148
- end
192
+ def listen!
193
+ print "Logging in...\r\n"
194
+ begin
195
+ params = { :ssl => true }
196
+ if @config[:api_key]
197
+ params[:token] = @config[:api_key]
198
+ else
199
+ params.merge!(:username => @config[:username], :password => @config[:password])
200
+ end
201
+ campfire = Campfire.new(@config[:domain], params)
202
+ rescue Tinder::AuthenticationFailed
203
+ raise "There was an authentication error - check your login information\r\n"
204
+ end
205
+ @me = campfire.me
149
206
 
150
- unless @input_buffer.empty? # read from server
151
- puts "\r\n"
152
- puts "#{@input_buffer.shift}\r\n" until @input_buffer.empty?
153
- show_prompt
154
- end
207
+ print "Joining #{@config[:room]}...\r\n"
208
+ @campfire_room = campfire.find_room_by_name(@config[:room])
209
+ raise "Can't find room named #{@config[:room]}!\r\n" if @campfire_room.nil?
210
+
211
+ @campfire_room.join
212
+ update_user_list
213
+
214
+ print_transcript
215
+ print_inline("You're up! For a list of available commands, type #{highlight('/help')}\r\n")
155
216
 
156
- end
157
- end.join
217
+ start_message_listener!(@campfire_room)
218
+ start_typing_agent!.join
158
219
  end
159
220
  end
160
221
 
@@ -0,0 +1,52 @@
1
+ require "mixlib/cli"
2
+
3
+ class CliConfig
4
+ include Mixlib::CLI
5
+
6
+ option :room,
7
+ :short => "-r ROOM_NAME",
8
+ :long => "--room ROOM_NAME",
9
+ :description => "Use quotes if there are spaces on the room name"
10
+
11
+ option :domain,
12
+ :short => "-d DOMAIN_NAME",
13
+ :long => "--domain DOMAIN_NAME",
14
+ :description => "The subdomain of your campfire room - <domain>.campfirenow.com"
15
+
16
+
17
+ option :username,
18
+ :short => "-u USERNAME",
19
+ :long => "--user USERNAME"
20
+
21
+ option :api_key,
22
+ :short => "-k API_KEY",
23
+ :long => "--key API_KEY",
24
+ :description => "Use this to log without a username/password prompt. You can skip the -u option if you use that"
25
+
26
+ option :help,
27
+ :short => "-h",
28
+ :long => "--help",
29
+ :on => :tail,
30
+ :description => "This handy guide you're reading right now",
31
+ :boolean => true,
32
+ :show_options => true,
33
+ :exit => 0
34
+
35
+ option :version,
36
+ :short => "-v",
37
+ :long => "--version",
38
+ :proc => Proc.new { puts "Campline version #{File.open('VERSION').read}" },
39
+ :boolean => true,
40
+ :exit => 0
41
+
42
+ def load!
43
+ self.parse_options
44
+ unless self.config[:domain] && self.config[:room] && (self.config[:username] || self.config[:api_key])
45
+ raise "Missing parameters - please run 'campline --help' for help"
46
+ end
47
+ end
48
+
49
+ def data
50
+ config
51
+ end
52
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: campline
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,27 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-02 00:00:00.000000000 Z
12
+ date: 2012-09-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: tinder
16
- requirement: !ruby/object:Gem::Requirement
16
+ requirement: &2152712180 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - ! '>='
19
+ - - =
20
20
  - !ruby/object:Gem::Version
21
- version: '0'
21
+ version: 1.8.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ! '>='
28
- - !ruby/object:Gem::Version
29
- version: '0'
24
+ version_requirements: *2152712180
30
25
  - !ruby/object:Gem::Dependency
31
26
  name: cli-colorize
32
- requirement: !ruby/object:Gem::Requirement
27
+ requirement: &2152711540 !ruby/object:Gem::Requirement
33
28
  none: false
34
29
  requirements:
35
30
  - - ! '>='
@@ -37,15 +32,21 @@ dependencies:
37
32
  version: '0'
38
33
  type: :runtime
39
34
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
35
+ version_requirements: *2152711540
36
+ - !ruby/object:Gem::Dependency
37
+ name: mixlib-cli
38
+ requirement: &2152710400 !ruby/object:Gem::Requirement
41
39
  none: false
42
40
  requirements:
43
41
  - - ! '>='
44
42
  - !ruby/object:Gem::Version
45
43
  version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *2152710400
46
47
  - !ruby/object:Gem::Dependency
47
48
  name: pry
48
- requirement: !ruby/object:Gem::Requirement
49
+ requirement: &2156559220 !ruby/object:Gem::Requirement
49
50
  none: false
50
51
  requirements:
51
52
  - - ! '>='
@@ -53,15 +54,10 @@ dependencies:
53
54
  version: '0'
54
55
  type: :development
55
56
  prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
59
- - - ! '>='
60
- - !ruby/object:Gem::Version
61
- version: '0'
57
+ version_requirements: *2156559220
62
58
  - !ruby/object:Gem::Dependency
63
59
  name: rspec
64
- requirement: !ruby/object:Gem::Requirement
60
+ requirement: &2156558600 !ruby/object:Gem::Requirement
65
61
  none: false
66
62
  requirements:
67
63
  - - ~>
@@ -69,15 +65,10 @@ dependencies:
69
65
  version: 2.8.0
70
66
  type: :development
71
67
  prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
- requirements:
75
- - - ~>
76
- - !ruby/object:Gem::Version
77
- version: 2.8.0
68
+ version_requirements: *2156558600
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: bundler
80
- requirement: !ruby/object:Gem::Requirement
71
+ requirement: &2156557060 !ruby/object:Gem::Requirement
81
72
  none: false
82
73
  requirements:
83
74
  - - ! '>='
@@ -85,15 +76,10 @@ dependencies:
85
76
  version: '0'
86
77
  type: :development
87
78
  prerelease: false
88
- version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
- requirements:
91
- - - ! '>='
92
- - !ruby/object:Gem::Version
93
- version: '0'
79
+ version_requirements: *2156557060
94
80
  - !ruby/object:Gem::Dependency
95
81
  name: jeweler
96
- requirement: !ruby/object:Gem::Requirement
82
+ requirement: &2156555320 !ruby/object:Gem::Requirement
97
83
  none: false
98
84
  requirements:
99
85
  - - ~>
@@ -101,12 +87,7 @@ dependencies:
101
87
  version: 1.8.4
102
88
  type: :development
103
89
  prerelease: false
104
- version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
- requirements:
107
- - - ~>
108
- - !ruby/object:Gem::Version
109
- version: 1.8.4
90
+ version_requirements: *2156555320
110
91
  description: A tiny Campfire client for command line
111
92
  email: hervalfreire@gmail.com
112
93
  executables:
@@ -126,6 +107,7 @@ files:
126
107
  - bin/campline
127
108
  - campline.gemspec
128
109
  - lib/campline.rb
110
+ - lib/cli_config.rb
129
111
  - spec/campline_spec.rb
130
112
  - spec/spec_helper.rb
131
113
  homepage: http://github.com/herval/campline
@@ -143,7 +125,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
143
125
  version: '0'
144
126
  segments:
145
127
  - 0
146
- hash: -3789922764660391293
128
+ hash: -2165468162116161805
147
129
  required_rubygems_version: !ruby/object:Gem::Requirement
148
130
  none: false
149
131
  requirements:
@@ -152,7 +134,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
152
134
  version: '0'
153
135
  requirements: []
154
136
  rubyforge_project:
155
- rubygems_version: 1.8.24
137
+ rubygems_version: 1.8.15
156
138
  signing_key:
157
139
  specification_version: 3
158
140
  summary: A tiny Campfire client