termtter 1.8.0 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/Rakefile +1 -1
  2. data/VERSION +1 -1
  3. data/lib/plugins/aa.rb +1 -1
  4. data/lib/plugins/appendtitle.rb +5 -12
  5. data/lib/plugins/defaults/auto_reload.rb +1 -0
  6. data/lib/plugins/defaults/cache.rb +18 -0
  7. data/lib/plugins/defaults/command_line.rb +1 -1
  8. data/lib/plugins/defaults/fib.rb +15 -6
  9. data/lib/plugins/defaults/retweet.rb +1 -1
  10. data/lib/plugins/defaults/standard_commands.rb +31 -25
  11. data/lib/plugins/defaults/stdout.rb +12 -4
  12. data/lib/plugins/defaults/system.rb +27 -0
  13. data/lib/plugins/dupu.rb +13 -0
  14. data/lib/plugins/erase.rb +4 -0
  15. data/lib/plugins/error_log.rb +17 -0
  16. data/lib/plugins/expand-tinyurl.rb +8 -1
  17. data/lib/plugins/growl.rb +10 -7
  18. data/lib/plugins/hatena_keyword_haiku.rb +88 -0
  19. data/lib/plugins/irc_gw.rb +12 -4
  20. data/lib/plugins/itunes.rb +29 -26
  21. data/lib/plugins/mecab.rb +23 -0
  22. data/lib/plugins/mudan_kinshi.rb +13 -0
  23. data/lib/plugins/ndkn.rb +7 -0
  24. data/lib/plugins/other_user.rb +47 -0
  25. data/lib/plugins/reply_sound.rb +75 -25
  26. data/lib/plugins/ruby-v.rb +10 -0
  27. data/lib/plugins/time_signal.rb +21 -0
  28. data/lib/plugins/tinyurl.rb +6 -4
  29. data/lib/plugins/train.rb +1 -1
  30. data/lib/plugins/translation.rb +2 -0
  31. data/lib/plugins/user_stream.rb +122 -0
  32. data/lib/plugins/whale.rb +28 -0
  33. data/lib/termtter/active_rubytter.rb +4 -0
  34. data/lib/termtter/api.rb +55 -30
  35. data/lib/termtter/client.rb +19 -4
  36. data/lib/termtter/config_setup.rb +10 -2
  37. data/lib/termtter/config_template.erb +4 -2
  38. data/lib/termtter/crypt.rb +13 -0
  39. data/lib/termtter/default_config.rb +5 -2
  40. data/lib/termtter/hookable.rb +4 -0
  41. data/lib/termtter/memory_cache.rb +67 -19
  42. data/lib/termtter/rubytter_proxy.rb +101 -26
  43. data/lib/termtter/system_extensions.rb +22 -18
  44. data/lib/termtter.rb +5 -1
  45. data/spec/termtter/crypt_spec.rb +16 -0
  46. data/spec/termtter/rubytter_proxy_spec.rb +14 -0
  47. metadata +85 -26
@@ -0,0 +1,13 @@
1
+ # coding: utf-8
2
+ # http://twitter.com/ototorosama/status/14283311303
3
+
4
+ Termtter::Client.register_hook(
5
+ :name => :mudan_kinshi,
6
+ :author => 'Sora Harakami',
7
+ :point => :pre_coloring,
8
+ :exec => lambda {|r,e|
9
+ r.gsub(/無断(.+?)禁止/) {|s|
10
+ "か、勝手に#{$1}しないでよね!! ...バカ....."
11
+ }
12
+ }
13
+ )
@@ -0,0 +1,7 @@
1
+ Termtter::Client.register_command(
2
+ :name => :ndkn,
3
+ :exec => lambda do |arg|
4
+ n = Termtter::Crypt.crypt(arg)
5
+ puts "ndkned => #{n.inspect}"
6
+ end
7
+ )
@@ -0,0 +1,47 @@
1
+ require 'base64'
2
+
3
+ config.plugins.other_user.set_default(:accounts,{})
4
+ config.plugins.other_user.set_default(:tokens_file,"~/.termtter/other_user_tokens")
5
+ config.plugins.other_user.set_default(:alias,{})
6
+
7
+ Termtter::Client.register_command(
8
+ :name => :other_user,
9
+ :alias => :o,
10
+ :help => ['other_user, o','Post by other user'],
11
+ :exec => lambda do |arg_raw|
12
+ tokens =
13
+ if File.exist?(File.expand_path(config.plugins.other_user.tokens_file))
14
+ Marshal.load(
15
+ Base64.decode64(File.read(File.expand_path(
16
+ config.plugins.other_user.tokens_file))))
17
+ else
18
+ {}
19
+ end
20
+
21
+ body = arg_raw.split(/ /)
22
+ user_raw = body.shift
23
+ user = config.plugins.other_user.alias[user_raw] || user_raw
24
+
25
+ unless tokens[user]
26
+ puts "<on_red>ERROR</on_red> #{user} isn't authorized yet. Starting authorization...".termcolor
27
+ tokens[user] = Termtter::API.authorize_by_oauth(false,false,false)
28
+ open(File.expand_path(config.plugins.other_user.tokens_file), 'w') do |f|
29
+ f.print Base64.encode64(Marshal.dump(tokens))
30
+ end
31
+ end
32
+
33
+ at = OAuth::AccessToken.new(
34
+ OAuth::Consumer.new(
35
+ Termtter::Crypt.decrypt(Termtter::CONSUMER_KEY),
36
+ Termtter::Crypt.decrypt(Termtter::CONSUMER_SECRET),
37
+ :site => "http://twitter.com/",
38
+ :proxy => ENV['http_proxy']),
39
+ tokens[user][:token],
40
+ tokens[user][:secret])
41
+
42
+ t = OAuthRubytter.new(at, Termtter::API.twitter_option)
43
+ t.update(body.join(' '))
44
+
45
+ puts "updated by #{user} => #{body.join(' ')}"
46
+ end
47
+ )
@@ -1,33 +1,83 @@
1
1
  #-*- coding: utf-8 -*-
2
2
 
3
- # FIXME: Currently this plugin is available only on Mac OS X.
3
+ config.plugins.reply_sound.set_default(:interval, 600)
4
4
 
5
- if RUBY_PLATFORM =~ /darwin/i
6
- config.plugins.reply_sound.set_default(:interval, 600)
7
- config.plugins.reply_sound.set_default(
8
- :sound_file, '/System/Library/Sounds/Hero.aiff')
5
+ nul_port = /mswin/i =~ RUBY_PLATFORM ? "NUL" : "/dev/null"
9
6
 
10
- reply_sound_cache = nil
11
- reply_sound_cache_ids = []
7
+ reply_sound_cache = nil
8
+ reply_sound_cache_ids = []
9
+ not_supported = false
10
+ cmd_ok = false
12
11
 
13
- Termtter::Client.add_task(
14
- :name => :reply_sound,
15
- :interval => config.plugins.reply_sound.interval) do
16
- replies = Termtter::API.twitter.replies
17
- new_replies = replies.delete_if {|x| reply_sound_cache_ids.index(x[:id]) }
18
- if !reply_sound_cache.nil? && new_replies.size > 0
19
- if respond_to? :spawn, true
20
- system 'afplay "'+config.plugins.reply_sound.sound_file+'" 2>/dev/null &'
12
+
13
+ Termtter::Client.register_hook(
14
+ :name => :reply_sound_initialization,
15
+ :point => :initialize,
16
+ :exec => lambda do
17
+ case RUBY_PLATFORM
18
+ when /darwin/i
19
+ config.plugins.reply_sound.set_default(
20
+ :sound_file, '/System/Library/Sounds/Hero.aiff')
21
+ config.plugins.reply_sound.set_default(
22
+ :command, ['afplay', config.plugins.reply_sound.sound_file, {:out => nul_port, :err => nul_port}])
23
+ cmd_ok = true
24
+ when /linux/i
25
+ case `uname -v`.chomp
26
+ when /ubuntu/i
27
+ config.plugins.reply_sound.set_default(
28
+ :sound_file, '/usr/share/sounds/gnome/default/alerts/drip.ogg')
21
29
  else
22
- spawn 'afplay', config.plugins.reply_sound.sound_file, :out => '/dev/null'
30
+ config.plugins.reply_sound.set_default(
31
+ :sound_file, '')
32
+ end
33
+ else
34
+ not_supported = true
35
+ puts TermColor.parse(
36
+ "<red>WARNING: Currently reply_sound plugin is not supported yet in your environment.</red>")
37
+ end
38
+
39
+ unless cmd_ok
40
+ begin
41
+ if /mplayer/i =~ `mplayer -v`.chomp
42
+ config.plugins.reply_sound.set_default(
43
+ :command, ['mplayer', config.plugins.reply_sound.sound_file, :out => nul_port, :err => nul_port])
44
+ cmd_ok = true
45
+ not_supported = false
46
+ end
47
+ rescue Errno::ENOENT
23
48
  end
24
- Termtter::Client.output(
25
- new_replies, Termtter::Event.new(:new_replies,:type => :reply))
26
49
  end
27
- reply_sound_cache = replies
28
- reply_sound_cache_ids += replies.map {|x| x[:id]}
29
- end
30
- else
31
- puts TermColor.parse(
32
- "<red>WARNING: Currently reply_sound plugin is available only on Mac OS X.</red>")
33
- end
50
+
51
+ unless not_supported
52
+ Termtter::Client.add_task(
53
+ :name => :reply_sound_wait,
54
+ :interval => 10) do
55
+ Termtter::Client.add_task(
56
+ :name => :reply_sound,
57
+ :interval => config.plugins.reply_sound.interval) do
58
+ cmd = config.plugins.reply_sound.command.kind_of?(Array) ?
59
+ config.plugins.reply_sound.command : [config.plugins.reply_sound.command]
60
+ replies = Termtter::API.twitter.replies
61
+ new_replies = replies.delete_if {|x| reply_sound_cache_ids.index(x[:id]) }
62
+ if !reply_sound_cache.nil? && new_replies.size > 0
63
+ if respond_to? :spawn, true
64
+ if respond_to? :fork, true
65
+ fork { exec *cmd }
66
+ else
67
+ system *cmd
68
+ end
69
+ else
70
+ spawn *cmd
71
+ end
72
+ print "\e[0G" + "\e[K" unless win?
73
+ Termtter::Client.output(
74
+ new_replies, Termtter::Event.new(:new_replies,:type => :reply))
75
+ Readline.refresh_line
76
+ end
77
+ reply_sound_cache = replies
78
+ reply_sound_cache_ids += replies.map {|x| x[:id]}
79
+ end
80
+ Termtter::Client.delete_task(:reply_sound_wait)
81
+ end
82
+ end
83
+ end)
@@ -0,0 +1,10 @@
1
+ module Termtter::Client
2
+ register_command(
3
+ :name => 'ruby-v',
4
+ :author => 'ujihisa',
5
+ :help => ["ruby-v", "Post the Ruby version you are using"],
6
+ :exec_proc => lambda {|_|
7
+ result = Termtter::API.twitter.update("#{RUBY_DESCRIPTION} #termtterrubyversion")
8
+ puts "=> " << result.text
9
+ })
10
+ end
@@ -0,0 +1,21 @@
1
+ config.plugins.time_signal.set_default(:minutes, [0])
2
+
3
+ last_signal_time = nil
4
+
5
+ Termtter::Client.add_task(:name => :time_signal, :interval => 10) do
6
+ begin
7
+ now = Time.now
8
+ if config.plugins.time_signal.minutes.include?(now.min)
9
+ hour = now.strftime('%H:%M')
10
+ unless hour == last_signal_time
11
+ print "\e[0G\e[2K"
12
+ puts "<on_green> #{hour} </on_green>".termcolor
13
+ Termtter::Client.notify 'time signal', hour
14
+ Readline.refresh_line
15
+ last_signal_time = hour
16
+ end
17
+ end
18
+ rescue Exception => e
19
+ Termtter::Client.handle_error(e)
20
+ end
21
+ end
@@ -10,11 +10,14 @@ config.plugins.tinyurl.set_default(:ignore_regexp, %r{
10
10
  \Ahttp://bit\.ly/ | \Ahttp://tinyurl\.com/ | \Ahttp://is\.gd/
11
11
  | \Ahttp://ff\.im/ | \Ahttp://j\.mp/ | \Ahttp://goo\.gl/
12
12
  | \Ahttp://tr\.im/ | \Ahttp://short\.to/ | \Ahttp://ow\.ly/
13
- | \Ahttp://u\.nu/ | \Ahttp://twurl\.nl/
13
+ | \Ahttp://u\.nu/ | \Ahttp://twurl\.nl/ | \Ahttp://icio\.us/
14
+ | \Ahttp://htn\.to/ | \Ahttp://cot\.ag/ | \Ahttp://ht\.ly/ | \Ahttp://p\.tl/
15
+ | \Ahttp://url4\.eu/ | |Ahttp://t\.co/
14
16
  }x )
15
17
  config.plugins.tinyurl.set_default(:tinyurl_hook_commands, [:update, :reply, :retweet])
16
- config.plugins.tinyurl.set_default(:uri_regexp,
17
- /#{URI.regexp(%w(http https ftp))}\S*/ )
18
+ config.plugins.tinyurl.set_default(
19
+ :uri_regexp,
20
+ /#{URI.regexp(%w(http https ftp))}\S*/ )
18
21
 
19
22
  module Termtter::Client
20
23
  register_hook(
@@ -53,7 +56,6 @@ module Termtter::Client
53
56
  nil
54
57
  end
55
58
  end
56
-
57
59
  end
58
60
 
59
61
  # tinyuri.rb
data/lib/plugins/train.rb CHANGED
@@ -1,5 +1,5 @@
1
- # あ
2
1
  # -*- coding: utf-8 -*-
2
+ # あ
3
3
  module Termtter::Client
4
4
  def self.train(length)
5
5
  text = "ε="
@@ -6,6 +6,8 @@ require 'kconv'
6
6
  require 'uri'
7
7
 
8
8
  def translate(text, langpair)
9
+ text = Termtter::API.twitter.show(text)[:text] if /^\d+$/ =~ text
10
+
9
11
  req = Net::HTTP::Post.new('/translate_t')
10
12
  req.add_field('Content-Type', 'application/x-www-form-urlencoded')
11
13
  req.add_field('User-Agent', 'Mozilla/5.0')
@@ -0,0 +1,122 @@
1
+ module Termtter::Client
2
+ register_command(:"user_stream stop", :help => 'user_stream stop') do |arg|
3
+ logger.info 'stopping user stream'
4
+ if @user_stream_thread
5
+ @user_stream_thread.exit
6
+ end
7
+ @user_stream_thread = nil
8
+ end
9
+
10
+ handle_chunk = lambda { |chunk|
11
+ data = Termtter::ActiveRubytter.new(JSON.parse(chunk)) rescue return
12
+ Termtter::Client.logger.debug "user_stream: received #{JSON.parse(chunk).inspect}"
13
+ begin
14
+ if data[:event]
15
+ if /list_/ =~ data[:event]
16
+ typable_id = Termtter::Client.data_to_typable_id(data.target.id)
17
+ puts "[%s] %s %s %s to %s]" %
18
+ [typable_id, data.source.screen_name, data.event, data.target.screen_name, data.target_object.uri]
19
+ return
20
+ end
21
+ if data[:target_object]
22
+ # target_object is status
23
+ source_user = data.source
24
+ status = data.target_object
25
+ typable_id = Termtter::Client.data_to_typable_id(status.id)
26
+ puts "[#{typable_id}] #{source_user.screen_name} #{data.event} #{status.user.screen_name}: #{status.text}"
27
+ else
28
+ # target is user
29
+ source_user = data.source
30
+ target_user = data.target
31
+ typable_id = Termtter::Client.data_to_typable_id(target_user.id)
32
+ puts "[#{typable_id}] #{source_user.screen_name} #{data.event} #{target_user.screen_name}"
33
+ end
34
+ elsif data[:friends]
35
+ puts "You have #{data[:friends].length} friends."
36
+ elsif data[:delete]
37
+ status = Termtter::API.twitter.safe.show(data.delete.status.id)
38
+ puts "#{status.user.screen_name} deleted: #{status.text}"
39
+ else
40
+ output([data], Termtter::Event.new(:update_friends_timeline, :type => :main))
41
+ Termtter::API.twitter.store_status_cache(data)
42
+ end
43
+ rescue Termtter::RubytterProxy::FrequentAccessError
44
+ # ignore
45
+ rescue Timeout::Error, StandardError => error
46
+ new_error = error.class.new("#{error.message} (#{JSON.parse(chunk).inspect})")
47
+ error.instance_variables.each{ |v|
48
+ new_error.instance_variable_set(v, error.instance_variable_get(v))
49
+ }
50
+ handle_error new_error
51
+ end
52
+ }
53
+
54
+ register_command(:"user_stream", :help => 'user_stream') do |arg|
55
+ unless config.password.kind_of? String
56
+ raise "config.password is required."
57
+ end
58
+
59
+ uri = URI.parse('http://betastream.twitter.com/2b/user.json')
60
+
61
+ unless @user_stream_thread
62
+ logger.info 'checking API status'
63
+ 1.times{ # to use break
64
+ Net::HTTP.start(uri.host, uri.port){ |http|
65
+ request = Net::HTTP::Get.new(uri.request_uri)
66
+ request.basic_auth(config.user_name, config.password)
67
+ http.request(request){ |response|
68
+ raise response.code.to_i unless response.code.to_i == 200
69
+ break
70
+ }
71
+ }
72
+ }
73
+ logger.info 'API seems working'
74
+ end
75
+
76
+ execute('user_stream stop') if @user_stream_thread
77
+ delete_task(:auto_reload)
78
+
79
+ @user_stream_thread = Thread.new {
80
+ loop do
81
+ begin
82
+ logger.info 'connecting to user stream'
83
+ Net::HTTP.start(uri.host, uri.port){ |http|
84
+ request = Net::HTTP::Get.new(uri.request_uri)
85
+ request.basic_auth(config.user_name, config.password)
86
+ http.request(request){ |response|
87
+ raise response.code.to_i unless response.code.to_i == 200
88
+ raise 'Response is not chuncked' unless response.chunked?
89
+ response.read_body{ |chunk|
90
+ handle_chunk.call(chunk)
91
+ }
92
+ }
93
+ }
94
+ rescue Timeout::Error, StandardError => e
95
+ handle_error e
96
+ logger.info 'sleeping'
97
+ sleep 10
98
+ end
99
+ end
100
+ }
101
+ end
102
+
103
+ register_hook(
104
+ :name => :user_stream_init,
105
+ :author => '?', # FIXME
106
+ :point => :initialize,
107
+ :exec => lambda {
108
+ execute('user_stream')
109
+ })
110
+ end
111
+
112
+ # user_stream.rb
113
+ #
114
+ # to use,
115
+ # > plug user_stream
116
+ # > user_stream
117
+ #
118
+ # to stop,
119
+ # > user_stream stop
120
+ #
121
+ # Specification
122
+ # http://apiwiki.twitter.com/ChirpUserStreams
@@ -0,0 +1,28 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Termtter
3
+ class RubytterProxy
4
+ alias_method :error_html_message_orig, :error_html_message
5
+
6
+ def error_html_message_whale(e)
7
+ if %r'Twitter / Over capacity' =~ e.message
8
+ WHALE
9
+ else
10
+ error_html_message_orig(e)
11
+ end
12
+ end
13
+
14
+ alias_method :error_html_message, :error_html_message_whale
15
+ end
16
+
17
+ # first blank line is to skip prompt.
18
+ WHALE = <<'__WHALE__'
19
+
20
+   ,......-..-—‐—--..r、_   ,r:, Twitter / Over capacity
21
+  ヾー-゚、 :::::::::::::::::::::::::_ ̄ニ、く
22
+    ゙`ー-`ー'-ー'" ̄    `'
23
+ __WHALE__
24
+ end
25
+
26
+ # whale.rb:
27
+ # print whale when twitter is over capacity.
28
+ # ASCII-Art from http://bhdaamov.hp.infoseek.co.jp/zukan/fish.html#kuji
@@ -44,6 +44,10 @@ module Termtter
44
44
  end
45
45
  end
46
46
 
47
+ def destructize
48
+ self.to_hash
49
+ end
50
+
47
51
  def retweeted_status
48
52
  nil
49
53
  end
data/lib/termtter/api.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- config.set_default(:host, 'twitter.com')
3
+ config.set_default(:host, 'api.twitter.com')
4
+ config.set_default(:oauth_consumer_site, 'http://api.twitter.com')
4
5
  if ENV.has_key?('HTTP_PROXY')
5
6
  require 'uri'
6
7
  proxy = ENV['HTTP_PROXY']
@@ -30,47 +31,71 @@ module Termtter
30
31
  class << self
31
32
  attr_reader :connection, :twitter
32
33
  def setup
33
- 3.times do
34
- begin
35
- if twitter = try_auth
36
- @twitter = twitter
37
- # NOTE: for compatible
38
- @connection = twitter.instance_variable_get(:@connection)
39
- break
40
- end
41
- rescue Timeout::Error
42
- puts TermColor.parse("<red>Time out :(</red>")
43
- exit!
34
+ # NOTE: for compatible
35
+ @connection = twitter.instance_variable_get(:@connection)
36
+ if config.access_token.empty? || config.access_token_secret.empty?
37
+ if config.token_file &&
38
+ File.exist?(File.expand_path(config.token_file))
39
+ config.access_token, config.access_token_secret = File.read(File.expand_path(config.token_file)) \
40
+ .split(/\r?\n/).map(&:chomp)
41
+ else
42
+ self.authorize_by_oauth(true)
44
43
  end
45
44
  end
46
45
 
47
- exit! unless twitter
46
+ access_token = OAuth::AccessToken.new(consumer, config.access_token, config.access_token_secret)
47
+ @twitter = RubytterProxy.new(access_token, twitter_option)
48
+
49
+ config.user_name = @twitter.verify_credentials[:screen_name]
48
50
  end
51
+
52
+ def authorize_by_oauth(show_information=false, save_to_token_file=true, put_to_config=true, verbose=true)
53
+ puts '1. Contacting to twitter...' if verbose
54
+
55
+ request_token = consumer.get_request_token
56
+
57
+ puts '2. URL for authorize: ' + request_token.authorize_url if verbose
58
+ puts ' Opening web page to authorization...' if verbose
49
59
 
50
- def try_auth
51
- if config.user_name.empty? || config.password.empty?
52
- puts 'Please enter your Twitter login:'
60
+ begin
61
+ open_browser(request_token.authorize_url)
62
+ rescue BrowserNotFound
63
+ puts "Browser not found. Please log in and/or grant access to get PIN via your browser at #{request_token.authorize_url}"
53
64
  end
65
+ sleep 2
54
66
 
55
67
  ui = create_highline
68
+ pin = ui.ask('3. Enter PIN: ')
69
+ puts ""
70
+ puts "4. Getting access_token..."
71
+ access_token = request_token.get_access_token(:oauth_verifier => pin)
56
72
 
57
- if config.user_name.empty?
58
- config.user_name = ui.ask('Username: ')
59
- else
60
- puts "Username: #{config.user_name}"
61
- end
62
- if config.password.empty?
63
- config.password = ui.ask('Password: ') { |q| q.echo = false}
73
+ if put_to_config
74
+ config.access_token = access_token.token
75
+ config.access_token_secret = access_token.secret
64
76
  end
65
77
 
66
- twitter = RubytterProxy.new(config.user_name, config.password, twitter_option)
67
- begin
68
- twitter.verify_credentials
69
- return twitter
70
- rescue Rubytter::APIError
71
- config.__clear__(:password)
78
+ if save_to_token_file
79
+ puts "5. Saving to token file... (" + config.token_file + ")"
80
+ open(File.expand_path(config.token_file),"w") do |f|
81
+ f.puts access_token.token
82
+ f.puts access_token.secret
83
+ end
72
84
  end
73
- return nil
85
+
86
+ puts "Authorize is successfully done."
87
+
88
+ return {:token => access_token.token,
89
+ :secret => access_token.secret}
90
+ end
91
+
92
+ def consumer
93
+ @consumer ||= OAuth::Consumer.new(
94
+ Termtter::Crypt.decrypt(CONSUMER_KEY),
95
+ Termtter::Crypt.decrypt(CONSUMER_SECRET),
96
+ :site => config.oauth_consumer_site,
97
+ :proxy => ENV['http_proxy']
98
+ )
74
99
  end
75
100
 
76
101
  def twitter_option
@@ -17,7 +17,7 @@ module Termtter
17
17
  Thread.abort_on_exception = true
18
18
 
19
19
  class << self
20
- attr_reader :commands
20
+ attr_reader :commands, :logger, :task_manager
21
21
 
22
22
  # plug :: Name -> (Hash) -> IO () where NAME = String | Symbol | [NAME]
23
23
  def plug(name, options = {})
@@ -30,8 +30,9 @@ module Termtter
30
30
 
31
31
  return if config.system.disable_plugins.include?(name.gsub('defaults/', ''))
32
32
 
33
+ name_sym = name.gsub(/-/, '_').to_sym
33
34
  options.each do |key, value|
34
- config.plugins.__refer__(name.gsub(/-/, '_').to_sym).__assign__(key.to_sym, value)
35
+ config.plugins.__refer__(name_sym).__assign__(key.to_sym, value)
35
36
  end
36
37
  load "plugins/#{name}.rb"
37
38
  rescue Exception => e
@@ -42,6 +43,10 @@ module Termtter
42
43
  @public_storage ||= {}
43
44
  end
44
45
 
46
+ def memory_cache
47
+ @memory_cache ||= Termtter::MemoryCache.new
48
+ end
49
+
45
50
  def add_filter(&b)
46
51
  warn "add_filter method will be removed. Use Termtter::Client.register_hook(:name => ..., :point => :filter_for_output, :exec => ... ) instead."
47
52
  @filters << b
@@ -68,6 +73,10 @@ module Termtter
68
73
  @commands[command.name] = command
69
74
  end
70
75
 
76
+ def remove_command(name)
77
+ commands.delete(name.to_sym)
78
+ end
79
+
71
80
  def add_command(name)
72
81
  if block_given?
73
82
  command = Command.new(:name => name)
@@ -206,6 +215,10 @@ module Termtter
206
215
  @task_manager.add_task(*arg, &block)
207
216
  end
208
217
 
218
+ def delete_task(name)
219
+ @task_manager.delete_task(name)
220
+ end
221
+
209
222
  def exit
210
223
  puts 'finalizing...'
211
224
  call_hooks(:exit)
@@ -303,8 +316,8 @@ module Termtter
303
316
  parse_options
304
317
  config.__freeze__(:user_name) unless config.user_name.empty?
305
318
  show_splash
306
- load_config
307
319
  setup_task_manager
320
+ load_config
308
321
  load_plugins
309
322
  eval_init_block
310
323
  config.__unfreeze__(:user_name)
@@ -331,7 +344,9 @@ module Termtter
331
344
  end
332
345
 
333
346
  def handle_error(e)
334
- logger.error("#{e.class.to_s}: #{e.message}")
347
+ message = e.message
348
+ message = message[0..29] + " ..." if message.size >= 30 && !config.devel
349
+ logger.error("#{e.class.to_s}: #{message}")
335
350
  logger.error(e.backtrace.join("\n")) if (e.backtrace and config.devel)
336
351
  get_hooks(:on_error).each {|hook| hook.call(e) }
337
352
  end
@@ -5,9 +5,8 @@ require 'erb'
5
5
  module Termtter
6
6
  module ConfigSetup
7
7
  module_function
8
+
8
9
  def run
9
- ui = create_highline
10
- user_name = ui.ask('your twitter user name: ')
11
10
 
12
11
  plugins = Dir.glob(File.expand_path(File.dirname(__FILE__) + "/../plugins/*.rb")).map {|f|
13
12
  f.match(%r|lib/plugins/(.*?).rb$|)[1]
@@ -23,6 +22,15 @@ module Termtter
23
22
  }
24
23
 
25
24
  puts "generated: ~/.termtter/config"
25
+
26
+ token_and_secret = Termtter::API.authorize_by_oauth
27
+ token = token_and_secret[:token]
28
+ secret = token_and_secret[:secret]
29
+
30
+ puts "Setup is all over. enjoy!"
31
+ rescue OAuth::Unauthorized
32
+ puts 'failed to authentication!'
33
+ exit!
26
34
  end
27
35
  end
28
36
  end
@@ -1,6 +1,8 @@
1
1
  # -*- coding: utf-8 -*-
2
+ # vim: filetype=ruby
3
+
4
+ config.token_file = "~/.termtter/token"
2
5
 
3
- config.user_name = '<%= user_name %>'
4
6
  #config.update_interval = 120
5
7
  #config.timeout = 60
6
8
  #config.retry = 3
@@ -10,7 +12,7 @@ config.user_name = '<%= user_name %>'
10
12
  #config.proxy.user_name = 'proxy user'
11
13
  #config.proxy.password = 'proxy password'
12
14
 
13
- config.plugins.keyword.keywords = ["@<%= user_name %>"]
15
+ #config.plugins.keyword.keywords = ["termtter"]
14
16
  config.confirm = true
15
17
  #config.plugins.stdout.colors = (31..36).to_a + (91..96).to_a
16
18
 
@@ -0,0 +1,13 @@
1
+ require 'base64'
2
+
3
+ module Termtter
4
+ module Crypt
5
+ def self.crypt(s)
6
+ Base64.encode64(s)
7
+ end
8
+
9
+ def self.decrypt(s)
10
+ Base64.decode64(s)
11
+ end
12
+ end
13
+ end