termtter 1.5.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. data/Rakefile +2 -1
  2. data/bin/termtter +1 -0
  3. data/lib/plugins/another_prompt.rb +131 -0
  4. data/lib/plugins/async.rb +23 -0
  5. data/lib/plugins/confirm.rb +1 -1
  6. data/lib/plugins/db.rb +1 -1
  7. data/lib/plugins/defaults/auto_reload.rb +20 -19
  8. data/lib/plugins/defaults/command_line.rb +10 -5
  9. data/lib/plugins/defaults/hashtag.rb +35 -0
  10. data/lib/plugins/defaults/lists.rb +14 -0
  11. data/lib/plugins/defaults/retweet.rb +15 -15
  12. data/lib/plugins/defaults/standard_commands.rb +22 -28
  13. data/lib/plugins/defaults/standard_completion.rb +5 -5
  14. data/lib/plugins/defaults/switch.rb +34 -0
  15. data/lib/plugins/eject.rb +15 -0
  16. data/lib/plugins/expand-tinyurl.rb +1 -1
  17. data/lib/plugins/favotter.rb +77 -0
  18. data/lib/plugins/friends.rb +50 -0
  19. data/lib/plugins/g.rb +16 -0
  20. data/lib/plugins/gsub.rb +17 -0
  21. data/lib/plugins/haml.rb +55 -0
  22. data/lib/plugins/hatebu_and_update.rb +2 -2
  23. data/lib/plugins/history.rb +9 -0
  24. data/lib/plugins/irc_gw.rb +11 -4
  25. data/lib/plugins/linefeed.rb +31 -0
  26. data/lib/plugins/md5pass.rb +42 -0
  27. data/lib/plugins/outputz.rb +1 -1
  28. data/lib/plugins/primes.rb +1 -1
  29. data/lib/plugins/quote.rb +43 -0
  30. data/lib/plugins/reduce_text.rb +26 -0
  31. data/lib/plugins/reverse.rb +7 -6
  32. data/lib/plugins/source.rb +31 -0
  33. data/lib/plugins/storage/status.rb +2 -2
  34. data/lib/plugins/storage.rb +1 -1
  35. data/lib/plugins/stream.rb +192 -0
  36. data/lib/plugins/switch_user.rb +1 -22
  37. data/lib/plugins/truncate.rb +29 -0
  38. data/lib/plugins/uri-open.rb +23 -9
  39. data/lib/plugins/w3mimg.rb +76 -0
  40. data/lib/termtter/active_rubytter.rb +8 -0
  41. data/lib/termtter/api.rb +37 -13
  42. data/lib/termtter/client.rb +26 -47
  43. data/lib/termtter/command.rb +15 -9
  44. data/lib/termtter/config.rb +6 -2
  45. data/lib/termtter/hookable.rb +59 -0
  46. data/lib/termtter/optparse.rb +51 -39
  47. data/lib/termtter/rubytter_proxy.rb +32 -0
  48. data/lib/termtter/system_extensions/core_compatibles.rb +16 -0
  49. data/lib/termtter/system_extensions/termtter_compatibles.rb +19 -0
  50. data/lib/termtter/system_extensions/windows.rb +86 -0
  51. data/lib/termtter/system_extensions.rb +8 -121
  52. data/lib/termtter/task_manager.rb +4 -10
  53. data/lib/termtter/version.rb +1 -1
  54. data/lib/termtter.rb +5 -3
  55. data/spec/plugins/defaults/hashtag_spec.rb +41 -0
  56. data/spec/plugins/defaults/lists_spec.rb +34 -0
  57. data/spec/plugins/{english_spec.rb → english_spec_.rb} +0 -0
  58. data/spec/plugins/{filter_spec.rb → filter_spec_.rb} +0 -0
  59. data/spec/plugins/gsub_spec.rb +18 -0
  60. data/spec/plugins/haml_spec.rb +134 -0
  61. data/spec/plugins/md5pass_spec.rb +13 -0
  62. data/spec/plugins/{primes_spec.rb → primes_spec_.rb} +0 -0
  63. data/spec/plugins/{sl_spec.rb → sl_spec_.rb} +0 -0
  64. data/spec/plugins/standard_commands_spec.rb +1 -1
  65. data/spec/plugins/storage/{DB_spec.rb → DB_spec_.rb} +0 -0
  66. data/spec/plugins/storage/{status_spec.rb → status_spec_.rb} +0 -0
  67. data/spec/plugins/truncate_spec.rb +27 -0
  68. data/spec/plugins/whois_spec_.rb +20 -0
  69. data/spec/spec_helper.rb +25 -0
  70. data/spec/termtter/active_rubytter_spec.rb +17 -0
  71. data/spec/termtter/api_spec.rb +107 -0
  72. data/spec/termtter/client_spec.rb +262 -73
  73. data/spec/termtter/command_spec.rb +31 -5
  74. data/spec/termtter/config_setup_spec.rb +19 -0
  75. data/spec/termtter/config_spec.rb +57 -27
  76. data/spec/termtter/hook_spec.rb +12 -0
  77. data/spec/termtter/hookable_spec.rb +53 -0
  78. data/spec/termtter/optparse_spec.rb +64 -9
  79. data/spec/termtter/rubytter_proxy_spec.rb +42 -0
  80. data/spec/termtter/system_extensions/windows_spec.rb +9 -0
  81. data/spec/termtter/system_extensions_spec.rb +61 -0
  82. data/spec/termtter/task_manager_spec.rb +58 -0
  83. data/spec/termtter_spec.rb +11 -0
  84. metadata +45 -20
  85. data/lib/termtter/connection.rb +0 -41
  86. data/spec/plugins/whois_spec.rb +0 -26
data/Rakefile CHANGED
@@ -23,7 +23,6 @@ spec = Gem::Specification.new do |s|
23
23
  s.add_dependency("highline", ">= 1.5.0")
24
24
  s.add_dependency("termcolor", ">= 1.0.0")
25
25
  s.add_dependency("rubytter", ">= 0.9.2")
26
- s.add_dependency("oauth", ">= 0.3.6")
27
26
  s.authors = %w(jugyo ujihisa)
28
27
  s.email = 'jugyo.org@gmail.com'
29
28
  s.homepage = 'http://termtter.org/'
@@ -61,12 +60,14 @@ end
61
60
  desc 'run all specs'
62
61
  Spec::Rake::SpecTask.new do |t|
63
62
  t.spec_files = FileList['spec/**/*_spec.rb']
63
+ t.spec_files.sort! # FIXME: Spec depends order.
64
64
  t.spec_opts = ['-c']
65
65
  end
66
66
  desc "Run all examples with RCov"
67
67
 
68
68
  Spec::Rake::SpecTask.new('rcov') do |t|
69
69
  t.spec_files = FileList['spec/**/*_spec.rb']
70
+ t.spec_files.sort! # FIXME: Spec depends order.
70
71
  t.spec_opts = ['-c', '-fs']
71
72
  t.rcov = true
72
73
  t.rcov_opts = ['-x', 'spec', '--exclude', 'lib/plugins']
data/bin/termtter CHANGED
@@ -3,4 +3,5 @@
3
3
 
4
4
  require 'rubygems'
5
5
  require 'termtter'
6
+ Termtter::OptParser.parse!(ARGV)
6
7
  Termtter::Client.run
@@ -0,0 +1,131 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ config.plugins.another_prompt.
4
+ set_default(:shortcut_setting,
5
+ { ':' => '',
6
+ 'd' => 'direct',
7
+ 'D' => 'delete',
8
+ 'f' => 'fib',
9
+ 'F' => 'favorite',
10
+ 'l' => 'list',
11
+ 'o' => 'open',
12
+ 'p' => 'profile',
13
+ 'R' => 'reply',
14
+ 's' => 'search',
15
+ 't' => 'retweet',
16
+ 'u' => 'update',
17
+ 'c' => lambda do
18
+ system('clear')
19
+ end,
20
+ 'L' => lambda do
21
+ puts '-' *
22
+ `stty size`.chomp.
23
+ sub(/^\d+\s(\d+)$/, '\\1').to_i
24
+ end,
25
+ 'q' => lambda do
26
+ Termtter::Client.call_commands('quit')
27
+ end,
28
+ 'r' => lambda do
29
+ Termtter::Client.call_commands('replies')
30
+ end,
31
+ '?' => lambda do
32
+ Termtter::Client.call_commands('help')
33
+ end,
34
+ "\e" => lambda do
35
+ system('screen', '-X', 'eval', 'copy')
36
+ end
37
+ })
38
+
39
+ Termtter::Client.plug 'curry'
40
+
41
+ module Termtter::Client
42
+ add_task(:name => :auto_reload,
43
+ :interval => config.update_interval,
44
+ :after => config.update_interval) do
45
+ begin
46
+ call_commands('reload')
47
+ rescue Exception => e
48
+ handle_error(e)
49
+ end
50
+ end
51
+
52
+ register_hook(
53
+ :name => :auto_reload_init,
54
+ :point => :initialize,
55
+ :exec => lambda {
56
+ begin
57
+ call_commands('reload')
58
+ rescue Exception => e
59
+ handle_error(e)
60
+ end
61
+ }
62
+ )
63
+ end
64
+
65
+ module Termtter
66
+ class CommandLine
67
+ include Singleton
68
+
69
+ STTY_ORIGIN = `stty -g`.chomp
70
+
71
+ def start_input_thread
72
+ setup_readline()
73
+ trap_setting()
74
+ @input_thread = Thread.new do
75
+ loop do
76
+ begin
77
+ value = config.plugins.another_prompt.shortcut_setting[wait_keypress]
78
+ Client.pause
79
+ case value
80
+ when String
81
+ call_prompt(value)
82
+ when Proc
83
+ value.call
84
+ end
85
+ ensure
86
+ Client.resume
87
+ end
88
+ end
89
+ end
90
+ @input_thread.join
91
+ end
92
+
93
+ def call_prompt(command)
94
+ Client.call_commands("curry #{command}")
95
+ if buf = Readline.readline(ERB.new(prompt).result(Termtter::API.twitter.__send__(:binding)), true)
96
+ Readline::HISTORY.pop if buf.empty?
97
+ begin
98
+ call(buf)
99
+ rescue Exception => e
100
+ Client.handle_error(e)
101
+ end
102
+ else
103
+ puts
104
+ end
105
+ ensure
106
+ Client.call_commands('uncurry')
107
+ end
108
+
109
+ def wait_keypress
110
+ system('stty', '-echo', '-icanon')
111
+ c = STDIN.getc
112
+ return [c].pack('c')
113
+ ensure
114
+ system('stty', STTY_ORIGIN)
115
+ end
116
+
117
+ def trap_setting()
118
+ begin
119
+ trap("INT") do
120
+ begin
121
+ system "stty", STTY_ORIGIN
122
+ ensure
123
+ Client.call_commands('exit')
124
+ end
125
+ end
126
+ rescue ArgumentError
127
+ rescue Errno::ENOENT
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,23 @@
1
+ module Termtter::Client
2
+ register_command(
3
+ :async,
4
+ :alias => :a,
5
+ :help => ['async COMMAND', 'asynchronously execute the command'],
6
+ :completion => lambda {|cmd, arg|
7
+ commands.map{|name, command| command.complement(arg)}.
8
+ flatten.
9
+ compact.
10
+ map{|i| "#{cmd} #{i}"}
11
+ },
12
+ :exec => lambda {|arg|
13
+ @task_manager.invoke_later do
14
+ begin
15
+ call_commands(arg)
16
+ rescue Exception => e
17
+ handle_error(e)
18
+ end
19
+ Readline.refresh_line
20
+ end
21
+ }
22
+ )
23
+ end
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- config.plugins.confirm.set_default(:commands, [:update, :reply, :direct])
3
+ config.plugins.confirm.set_default(:commands, [:update, :reply, :direct, :retweet])
4
4
  config.plugins.confirm.set_default(
5
5
  :conditions,
6
6
  [
data/lib/plugins/db.rb CHANGED
@@ -76,7 +76,7 @@ module Termtter
76
76
  end
77
77
 
78
78
  register_command(:db_clear) do |arg|
79
- if confirm('Are you shure?')
79
+ if confirm('Are you sure?')
80
80
  User.delete
81
81
  Status.delete
82
82
  end
@@ -1,22 +1,23 @@
1
1
  # -*- coding: utf-8 -*-
2
- module Termtter::Client
3
- add_task(:name => :auto_reload, :interval => config.update_interval, :after => config.update_interval) do
4
- begin
5
- call_commands('reload -r')
6
- rescue Exception => e
7
- handle_error(e)
8
- end
2
+ auto_reload_proc = lambda do
3
+ begin
4
+ Termtter::Client.call_commands('reload -r')
5
+ rescue TimeoutError
6
+ # do nothing
7
+ rescue Exception => e
8
+ Termtter::Client.handle_error(e)
9
9
  end
10
-
11
- register_hook(
12
- :name => :auto_reload_init,
13
- :point => :initialize,
14
- :exec => lambda {
15
- begin
16
- call_commands('reload -r')
17
- rescue Exception => e
18
- handle_error(e)
19
- end
20
- }
21
- )
22
10
  end
11
+
12
+ Termtter::Client.add_task(
13
+ :name => :auto_reload,
14
+ :interval => config.update_interval,
15
+ :after => config.update_interval,
16
+ &auto_reload_proc
17
+ )
18
+
19
+ Termtter::Client.register_hook(
20
+ :name => :auto_reload_init,
21
+ :point => :initialize,
22
+ :exec => auto_reload_proc
23
+ )
@@ -20,7 +20,7 @@ module Termtter
20
20
  end
21
21
 
22
22
  def stop
23
- @input_thread.kill
23
+ @input_thread.kill if @input_thread
24
24
  end
25
25
 
26
26
  def call(command_text)
@@ -32,6 +32,8 @@ module Termtter
32
32
  command_text = hook.call(command_text)
33
33
  }
34
34
  Client.call_commands(command_text)
35
+ rescue TimeoutError
36
+ puts TermColor.parse("<red>Time out :(</red>")
35
37
  end
36
38
 
37
39
  def prompt
@@ -67,11 +69,14 @@ module Termtter
67
69
  Readline.completion_case_fold = true
68
70
  Readline.completion_proc = lambda {|input|
69
71
  begin
70
- words = []
71
- words << Client.commands.map {|name, command| command.complement(input) }
72
- Client.get_hooks(:completion).each do |hook|
73
- words << hook.call(input) rescue nil
72
+ words = Client.commands.map {|name, command| command.complement(input) }.flatten.compact
73
+
74
+ if words.empty?
75
+ Client.get_hooks(:completion).each do |hook|
76
+ words << hook.call(input) rescue nil
77
+ end
74
78
  end
79
+
75
80
  words.flatten.compact
76
81
  rescue Exception => e
77
82
  Client.handle_error(e)
@@ -0,0 +1,35 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'set'
3
+
4
+ module Termtter::Client
5
+ public_storage[:hashtags] ||= Set.new
6
+ public_storage[:orig_prompt] = config.prompt
7
+
8
+ register_hook(:add_hashtags, :point => :modify_arg_for_update) do |cmd, arg|
9
+ "#{arg} #{public_storage[:hashtags].to_a.join(' ')}"
10
+ end
11
+
12
+ register_command(:raw_update) do |args|
13
+ temp = public_storage[:hashtags]
14
+ public_storage[:hashtags].clear
15
+ call_commands "update #{args}"
16
+ public_storage[:hashtags] = temp
17
+ end
18
+
19
+ register_command('hashtag add') do |args|
20
+ args.split(/\s+/).each do |arg|
21
+ hashtag = /^#/ =~ arg ? arg : "##{arg}"
22
+ public_storage[:hashtags] << hashtag
23
+ config.prompt = "#{public_storage[:hashtags].to_a.join(', ')} #{public_storage[:orig_prompt]}"
24
+ end
25
+ end
26
+
27
+ register_command('hashtag clear') do |args|
28
+ public_storage[:hashtags].clear
29
+ config.prompt = public_storage[:orig_prompt]
30
+ end
31
+
32
+ register_command('hashtag list') do |args|
33
+ puts public_storage[:hashtags].to_a
34
+ end
35
+ end
@@ -0,0 +1,14 @@
1
+ module Termtter::Client
2
+ register_command(
3
+ :name => :lists,
4
+ :exec => lambda {|arg|
5
+ unless arg.empty?
6
+ user_name = normalize_as_user_name(arg)
7
+ else
8
+ user_name = config.user_name
9
+ end
10
+ # TODO: show more information of lists
11
+ puts Termtter::API.twitter.lists(user_name).lists.map{|i| i.slug}
12
+ }
13
+ )
14
+ end
@@ -1,10 +1,11 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  config.plugins.retweet.set_default(:format, '<%= comment %>RT @<%=s.user.screen_name%>: <%=s.text%>')
4
+ config.plugins.retweet.set_default(:confirm_protected, true)
4
5
 
5
6
  module Termtter::Client
6
7
  def self.post_retweet(s, comment = nil)
7
- if s.user.protected &&
8
+ if s.user.protected && config.plugins.retweet.confirm_protected &&
8
9
  !confirm("#{s.user.screen_name} is protected! Are you sure?", false)
9
10
  return
10
11
  end
@@ -23,21 +24,20 @@ module Termtter::Client
23
24
  :help => ['retweet,rt (ID|@USER)', 'Post a retweet message'],
24
25
  :exec_proc => lambda {|arg|
25
26
  arg, comment = arg.split(/\s/, 2)
26
- txt = if public_storage[:typable_id] && s = typable_id_status(arg)
27
- post_retweet(s, comment)
28
- else
29
- case arg
30
- when /(\d+)/
31
- post_retweet(Termtter::API.twitter.show(arg), comment)
32
- when /@([A-Za-z0-9_]+)/
33
- user = $1
34
- statuses = Termtter::API.twitter.user_timeline(user)
35
- return if statuses.empty?
36
- post_retweet(statuses[0], comment)
37
- end
38
- end
39
27
 
40
- return txt
28
+ if public_storage[:typable_id] && s = typable_id_status(arg)
29
+ post_retweet(s, comment)
30
+ else
31
+ case arg
32
+ when /(\d+)/
33
+ post_retweet(Termtter::API.twitter.show(arg), comment)
34
+ when /@([A-Za-z0-9_]+)/
35
+ user = $1
36
+ statuses = Termtter::API.twitter.user_timeline(user)
37
+ return if statuses.empty?
38
+ post_retweet(statuses[0], comment)
39
+ end
40
+ end
41
41
  }
42
42
  )
43
43
  end
@@ -28,8 +28,8 @@ module Termtter::Client
28
28
  register_command(
29
29
  :name => :update, :alias => :u,
30
30
  :exec => lambda {|arg|
31
- unless arg.empty?
32
- params =
31
+ unless arg.rstrip.empty?
32
+ params =
33
33
  if config.easy_reply && /^\s*(@\w+)/ =~ arg
34
34
  user_name = normalize_as_user_name($1)
35
35
  in_reply_to_status_id = Termtter::API.twitter.user(user_name).status.id rescue nil
@@ -167,7 +167,8 @@ module Termtter::Client
167
167
  register_command(
168
168
  :name => :search, :aliases => [:s],
169
169
  :exec_proc => lambda {|arg|
170
- statuses = Termtter::API.twitter.search(arg)
170
+ search_option = config.search.option.empty? ? {} : config.search.option
171
+ statuses = Termtter::API.twitter.search(arg, search_option)
171
172
  public_storage[:search_keywords] << arg
172
173
  output(statuses, SearchEvent.new(arg))
173
174
  },
@@ -256,25 +257,25 @@ module Termtter::Client
256
257
  register_command(
257
258
  :name => :favorite, :aliases => [:fav],
258
259
  :exec_proc => lambda {|arg|
259
- id = 0
260
- case arg
261
- when /^\d+/
262
- id = arg.to_i
263
- when /^@([A-Za-z0-9_]+)/
264
- user_name = normalize_as_user_name($1)
265
- statuses = Termtter::API.twitter.user_timeline(user_name)
266
- return if statuses.empty?
267
- id = statuses[0].id
268
- when /^\/(.*)$/
269
- word = $1
270
- raise "Not implemented yet."
271
- else
272
- if public_storage[:typable_id] && typable_id?(arg)
273
- id = typable_id_convert(arg)
260
+ id =
261
+ case arg
262
+ when /^\d+/
263
+ arg.to_i
264
+ when /^@([A-Za-z0-9_]+)/
265
+ user_name = normalize_as_user_name($1)
266
+ statuses = Termtter::API.twitter.user_timeline(user_name)
267
+ return if statuses.empty?
268
+ statuses[0].id
269
+ when /^\/(.*)$/
270
+ word = $1
271
+ raise "Not implemented yet."
274
272
  else
275
- return
273
+ if public_storage[:typable_id] && typable_id?(arg)
274
+ typable_id_convert(arg)
275
+ else
276
+ return
277
+ end
276
278
  end
277
- end
278
279
 
279
280
  r = Termtter::API.twitter.favorite id
280
281
  puts "Favorited status ##{r.id} on user @#{r.user.screen_name} #{r.text}"
@@ -405,16 +406,9 @@ module Termtter::Client
405
406
 
406
407
  ## plugin_list :: IO ()
407
408
  def self.plugin_list
408
- plugin_list = (Dir["#{File.dirname(__FILE__)}/../*.rb"] + Dir["#{Termtter::CONF_DIR}/plugins/*.rb"]).
409
+ (Dir["#{File.dirname(__FILE__)}/../*.rb"] + Dir["#{Termtter::CONF_DIR}/plugins/*.rb"]).
409
410
  map {|f| File.basename(f).sub(/\.rb$/, '')}.
410
411
  sort
411
- list = plugin_list
412
- width = list.map {|i|i.size}.max + 2
413
- a = []
414
- list.sort.each_slice(4) {|i|
415
- a << i.map {|j| j + (" " * (width - j.size))}.join
416
- }
417
- puts TermColor.parse('<green>' + TermColor.escape(a.join("\n")) + '</green>')
418
412
  end
419
413
 
420
414
  register_command(
@@ -40,7 +40,7 @@ module Termtter::Client
40
40
  if part_of_user_name.nil? || part_of_user_name.empty?
41
41
  public_storage[:users].to_a
42
42
  else
43
- public_storage[:users].grep(/^#{Regexp.quote(part_of_user_name)}/i)
43
+ public_storage[:users].grep(Regexp.compile("^#{Regexp.quote(part_of_user_name)}", part_of_user_name.downcase == part_of_user_name ? Regexp::IGNORECASE : 0))
44
44
  end
45
45
 
46
46
  users.map {|u| "#{command_str} @%s" % u }
@@ -51,19 +51,19 @@ module Termtter::Client
51
51
  # completion for hashtags
52
52
  #
53
53
 
54
- public_storage[:hashtags] ||= Set.new
54
+ public_storage[:hashtags_for_completion] ||= Set.new
55
55
 
56
56
  register_hook(:collect_hashtags, :point => :pre_filter) do |statuses, event|
57
57
  statuses.each do |s|
58
- public_storage[:hashtags] += s.text.scan(/#([^\s]+)/).flatten
58
+ public_storage[:hashtags_for_completion] += s.text.scan(/#([^\s]+)/).flatten
59
59
  end
60
60
  end
61
61
 
62
- register_hook(:hashtagss_completion, :point => :completion) do |input|
62
+ register_hook(:hashtags_completion, :point => :completion) do |input|
63
63
  if /(.*)\s#([^\s]*)$/ =~ input
64
64
  command_str = $1
65
65
  part_of_hashtag = $2
66
- ht = public_storage[:hashtags]
66
+ ht = public_storage[:hashtags_for_completion]
67
67
  (ht.grep(/^#{Regexp.quote(part_of_hashtag)}/) | # prior
68
68
  ht.grep(/^#{Regexp.quote(part_of_hashtag)}/i) ).
69
69
  map { |i| "#{command_str} ##{i}" }
@@ -0,0 +1,34 @@
1
+ module Termtter::Client
2
+ passwords = {}
3
+
4
+ register_command(
5
+ :name => :switch,
6
+ :alias => :switch_user,
7
+ :exec_proc => lambda {|arg|
8
+ user_name = !arg.empty? ? normalize_as_user_name(arg) : nil
9
+ return if user_name == config.user_name
10
+
11
+ passwords[config.user_name] = config.password
12
+
13
+ if user_name
14
+ config.user_name = normalize_as_user_name(arg)
15
+ if passwords.key?(config.user_name)
16
+ config.password = passwords[config.user_name]
17
+ else
18
+ config.__clear__(:password)
19
+ end
20
+ else
21
+ config.__clear__(:user_name)
22
+ config.__clear__(:password)
23
+ end
24
+
25
+ Termtter::API.setup
26
+ call_commands('reload')
27
+ },
28
+ :help => ["switch USERNAME", "Switch twitter account."]
29
+ )
30
+
31
+ register_command(:restore_user) do |arg|
32
+ puts 'Sorry, command "restore_user" was obsoleted, and use command "switch" instead.'
33
+ end
34
+ end
@@ -0,0 +1,15 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ if /linux/ =~ PLATFORM
4
+ module Termtter::Client
5
+ help = ['eject [-t]', 'eject or close']
6
+ register_command(:eject, :help => help) do |flag|
7
+ if flag.empty?
8
+ system 'eject'
9
+ else
10
+ system 'eject -t'
11
+ end
12
+ end
13
+ end
14
+ end
15
+
@@ -51,7 +51,7 @@ def expand_url(host, path)
51
51
  config.proxy.user_name,
52
52
  config.proxy.password)
53
53
  end
54
- res = http_class.new(host).head(path)
54
+ res = http_class.new(host).get(path, { 'User-Agent' => 'Mozilla' })
55
55
  return nil unless res.code == "301" or res.code == "302"
56
56
  res['Location'].force_encoding(Encoding::UTF_8)
57
57
  rescue
@@ -0,0 +1,77 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'rubygems'
4
+ require 'nokogiri'
5
+ require 'open-uri'
6
+
7
+ module Termtter::Client
8
+
9
+ public_storage[:favorited_ids] = {}
10
+
11
+ class << self
12
+ def output_favorites(target, threshold)
13
+ favorites = parse("http://favotter.matope.com/user.php?user=#{target}&threshold=#{threshold}")
14
+
15
+ public_storage[:favorited_ids].clear
16
+ alphabet = '$a'
17
+ max_amount_width = favorites.map {|f| now = f[2].to_s.size }.max
18
+ favorites.reverse.each do |id, text, amount, users|
19
+ public_storage[:favorited_ids][alphabet] = id
20
+ color = fav_color(amount)
21
+ fav = "fav#{amount == 1 ? '' : 's'}"
22
+ favorites_info = "(#{amount} #{fav})".rjust(max_amount_width + 7)
23
+ format = "<GREEN>#{favorites_info} #{alphabet}</GREEN> <YELLOW>%s</YELLOW>: <#{color}>%s</#{color}>"
24
+ values = [users.join(', '), CGI.escape(text)]
25
+ puts CGI.unescape(TermColor.parse(format % values ))
26
+ alphabet.succ!
27
+ end
28
+ end
29
+
30
+ private
31
+ def parse(url)
32
+ doc = Nokogiri(open(url).read)
33
+ doc.css('div.entry').map do |entry|
34
+ id = entry['id'].gsub(/\Astatus_/, '')
35
+ text = entry.css('span.status_text').first.content
36
+ amount = entry.css('div.info span.favotters').first.content
37
+ amount = amount.match(/(\d+)/)[1].to_i
38
+ users = entry.css('div.info span.favotters img').map {|u| u['title'] }
39
+ [id, text, amount, users]
40
+ end
41
+ end
42
+
43
+ def fav_color(amount)
44
+ case amount
45
+ when 1 then 'WHITE'
46
+ when 2 then 'GREEN'
47
+ when 3 then 'BLUE'
48
+ when 4 then 'BLUE'
49
+ else 'RED'
50
+ end
51
+ end
52
+ end
53
+
54
+ help = ['favotter [USERNAME] [THRESHOLD]', 'Show info from favotter']
55
+ register_command('favotter', :help => help) do |arg|
56
+ target = if arg.empty?
57
+ config.user_name
58
+ else
59
+ args = arg.split
60
+ threshold = args.size == 1 ? 1 : args[1]
61
+ args[0]
62
+ end
63
+ if /@(.*)/ =~ target
64
+ target = $1
65
+ end
66
+ output_favorites target, threshold
67
+ end
68
+
69
+ help = ['favotter_fav [FavoritedID]', 'Favorite favorited status']
70
+ register_command('favotter_fav', :alias => :ffav, :help => help) do |arg|
71
+ raise 'need favorited_id' if arg.empty?
72
+ if id = public_storage[:favorited_ids][arg]
73
+ call_commands("favorite #{id}")
74
+ end
75
+ end
76
+ end
77
+