termtter 1.8.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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