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
data/Rakefile CHANGED
@@ -11,7 +11,7 @@ begin
11
11
  gem.add_dependency("json", ">= 1.1.3")
12
12
  gem.add_dependency("highline", ">= 1.5.0")
13
13
  gem.add_dependency("termcolor", ">= 1.0.0")
14
- gem.add_dependency("rubytter", ">= 0.11.0")
14
+ gem.add_dependency("rubytter", ">= 1.4.0")
15
15
  gem.add_dependency("notify", ">= 0.2.1")
16
16
  gem.authors = %w(jugyo ujihisa)
17
17
  gem.email = 'jugyo.org@gmail.com'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.8.0
1
+ 1.9.0
data/lib/plugins/aa.rb CHANGED
@@ -34,6 +34,7 @@ end
34
34
 
35
35
  Termtter::Client.register_command(
36
36
  :name => :aa,
37
+ :author => 'hitode909',
37
38
  :exec_proc => lambda {|arg|
38
39
  name = Termtter::Client.normalize_as_user_name(arg)
39
40
  command = name.length > 0 ? "u @#{name} #{AAMaker.make}" : "u #{AAMaker.make}"
@@ -41,4 +42,3 @@ Termtter::Client.register_command(
41
42
  },
42
43
  :help => ["aa [(Optinal) USER]", "Post a AA"]
43
44
  )
44
-
@@ -9,33 +9,26 @@ require 'digest/sha1'
9
9
  module Termtter::Client
10
10
  config.plugins.appendtitle.set_default(:timeout, 30)
11
11
  config.plugins.appendtitle.set_default(:cache_expire, 3600 * 24 * 7)
12
- config.plugins.appendtitle.set_default(:memcached_server, 'localhost:11211')
13
-
14
- def self.memcache_client
15
- @memcache_client ||= MemCache.new(config.plugins.appendtitle.memcached_server)
16
- end
17
12
 
18
13
  def self.fetch_title(uri)
19
14
  return unless uri
20
- key = %w{ termtter plugins appendtitle title}.push(Digest::SHA1.hexdigest(uri)).join('-')
21
- if v = memcache_client.get(key)
15
+ key = %w{ plugins appendtitle title}.push(Digest::SHA1.hexdigest(uri)).join('-')
16
+ if v = memory_cache.get(key)
22
17
  logger.debug "appendtitle: cache hit for #{uri}"
23
18
  return v
24
19
  end
25
20
 
26
- memcache_client.set(key, '', config.plugins.appendtitle.cache_expire) # to avoid duplicate fetch
21
+ memory_cache.set(key, '', config.plugins.appendtitle.cache_expire) # to avoid duplicate fetch
27
22
  begin
28
23
  logger.debug "appendtitle: fetching title for #{uri}"
29
24
  source = Nokogiri(open(uri).read)
30
25
  if source and source.at('title')
31
26
  title = source.at('title').text
32
- memcache_client.set(key, title, config.plugins.appendtitle.cache_expire)
27
+ memory_cache.set(key, title, config.plugins.appendtitle.cache_expire)
33
28
  return title
34
29
  end
35
30
  nil
36
- rescue Timeout::Error
37
- nil
38
- rescue
31
+ rescue Timeout::Error, StandardError
39
32
  nil
40
33
  end
41
34
  end
@@ -4,6 +4,7 @@ auto_reload_proc = lambda do
4
4
  Termtter::Client.execute('reload -r')
5
5
  rescue TimeoutError
6
6
  # do nothing
7
+ rescue
7
8
  rescue Exception => e
8
9
  Termtter::Client.handle_error(e)
9
10
  end
@@ -0,0 +1,18 @@
1
+ require 'pp'
2
+
3
+ module Termtter::Client
4
+ register_command(
5
+ :name => :"cache stats",
6
+ :help => 'Show Memcached stats.',
7
+ :exec_proc => lambda {|arg|
8
+ puts memory_cache.stats.pretty_inspect
9
+ })
10
+
11
+ register_command(
12
+ :name => :"cache flush",
13
+ :help => 'Flush all caches.',
14
+ :exec_proc => lambda {|arg|
15
+ memory_cache.flush_all
16
+ logger.info "cache flushed."
17
+ })
18
+ end
@@ -113,7 +113,7 @@ module Termtter
113
113
 
114
114
  def trap_setting()
115
115
  return if /mswin(?!ce)|mingw|bccwin/ =~ RUBY_PLATFORM
116
-
116
+
117
117
  begin
118
118
  stty_save = `stty -g`.chomp
119
119
  trap("INT") do
@@ -1,7 +1,16 @@
1
1
  def fib(n)i=0;j=1;n.times{j=i+i=j};i end
2
- Termtter::Client.register_command(:fib) do |arg|
3
- n = arg.to_i
4
- text = "fib(#{n}) = #{fib n}"
5
- Termtter::API.twitter.update(text)
6
- puts "=> " << text
7
- end
2
+ Termtter::Client.register_command(:name => :fib,
3
+ :aliases => [:f, :ho],
4
+ :exec => lambda do |arg|
5
+ case arg
6
+ when "ukumori"
7
+ puts 'Does it mean "Sora Harakami (@sora_h)"?'
8
+ when "ootsuite", "otsuite"
9
+ puts "NDA :D"
10
+ else
11
+ n = arg.to_i
12
+ text = "fib(#{n}) = #{fib n}"
13
+ Termtter::API.twitter.update(text)
14
+ puts "=> " << text
15
+ end
16
+ end)
@@ -11,7 +11,7 @@ config.plugins.retweet.set_default(
11
11
 
12
12
  module Termtter::Client
13
13
  def self.post_retweet(s, comment = nil)
14
- s.user.protected and
14
+ s[:user][:protected] and
15
15
  config.plugins.retweet.confirm_protected and
16
16
  !confirm("#{s.user.screen_name} is protected! Are you sure?", false) and
17
17
  return
@@ -32,25 +32,31 @@ module Termtter::Client
32
32
  register_command(
33
33
  :name => :update, :alias => :u,
34
34
  :exec => lambda {|arg|
35
- unless arg.empty?
36
- params =
37
- if config.easy_reply && /^\s*(@\w+)/ =~ arg
38
- user_name = normalize_as_user_name($1)
39
- in_reply_to_status_id =
40
- Termtter::API.twitter.user(user_name).status.id rescue nil
41
- in_reply_to_status_id ?
42
- {:in_reply_to_status_id => in_reply_to_status_id} : {}
43
- else
44
- {}
45
- end
46
-
47
- result = Termtter::API.twitter.update(arg, params)
48
-
49
- if result.text == arg
50
- puts "updated => #{result.text}"
35
+ return if arg.empty?
36
+ params =
37
+ if config.easy_reply && /^\s*(@\w+)/ =~ arg
38
+ user_name = normalize_as_user_name($1)
39
+ in_reply_to_status_id =
40
+ Termtter::API.twitter.user(user_name).status.id rescue nil
41
+ in_reply_to_status_id ?
42
+ {:in_reply_to_status_id => in_reply_to_status_id} : {}
51
43
  else
52
- puts TermColor.parse("<red>Failed to update :(</red>")
44
+ {}
53
45
  end
46
+
47
+ # "u $aa msg" is likely to be a mistake of
48
+ # "re $aa msg".
49
+ if /^\s*\d+\s/ =~ arg
50
+ puts "Does it mean `re[ply] #{arg}`?"
51
+ break
52
+ end
53
+
54
+ result = Termtter::API.twitter.update(arg, params)
55
+
56
+ if result.text == arg
57
+ puts "updated => #{result.text}"
58
+ else
59
+ puts TermColor.parse("<red>Failed to update :(</red>")
54
60
  end
55
61
  },
56
62
  :help => ["update,u TEXT", "Post a new message"]
@@ -127,7 +133,7 @@ module Termtter::Client
127
133
  end
128
134
 
129
135
  def self.get_friends_or_followers(type, user_name, max)
130
- raise "type should :friends or :followers" unless [:friends, :followers].include? type
136
+ raise "type should be :friends or :followers" unless [:friends, :followers].include? type
131
137
  users = []
132
138
  cursor = -1
133
139
  begin
@@ -158,7 +164,7 @@ module Termtter::Client
158
164
  )
159
165
 
160
166
  def self.friends_or_followers_command(type, arg)
161
- raise "type should :friends or :followers" unless [:friends, :followers].include? type
167
+ raise "type should be :friends or :followers" unless [:friends, :followers].include? type
162
168
  limit = 20
163
169
  if /\-([\d]+)/ =~ arg
164
170
  limit = $1.to_i
@@ -171,7 +177,7 @@ module Termtter::Client
171
177
  users.reverse.each{|user|
172
178
  padding = ' ' * (longest - user.screen_name.length)
173
179
  user_id = Termtter::Client.data_to_typable_id(user.id) rescue ''
174
- color = user.following ? 'BLACK' : 'RED'
180
+ color = user.following ? config.plugins.stdout.colors.first : config.plugins.stdout.colors.last
175
181
  mark = user.following ? '♥' : '✂'
176
182
  erbed_text = ERB.new(config.plugins.standard.one_line_profile_format).result(binding)
177
183
  puts TermColor.unescape(TermColor.parse(erbed_text))
@@ -261,7 +267,7 @@ module Termtter::Client
261
267
  args.split(' ').each do |arg|
262
268
  user_name = normalize_as_user_name(arg)
263
269
  user = Termtter::API::twitter.follow(user_name)
264
- puts "followed #{user.name}"
270
+ puts "followed #{user.screen_name}"
265
271
  end
266
272
  },
267
273
  :help => ['follow USER', 'Follow user']
@@ -273,7 +279,7 @@ module Termtter::Client
273
279
  args.split(' ').each do |arg|
274
280
  user_name = normalize_as_user_name(arg)
275
281
  user = Termtter::API::twitter.leave(user_name)
276
- puts "leaved #{user.name}"
282
+ puts "left #{user.screen_name}"
277
283
  end
278
284
  },
279
285
  :help => ['leave USER', 'Leave user']
@@ -285,7 +291,7 @@ module Termtter::Client
285
291
  args.split(' ').each do |arg|
286
292
  user_name = normalize_as_user_name(arg)
287
293
  user = Termtter::API::twitter.block(user_name)
288
- puts "blocked #{user.name}"
294
+ puts "blocked #{user.screen_name}"
289
295
  end
290
296
  },
291
297
  :help => ['block USER', 'Block user']
@@ -297,7 +303,7 @@ module Termtter::Client
297
303
  args.split(' ').each do |arg|
298
304
  user_name = normalize_as_user_name(arg)
299
305
  user = Termtter::API::twitter.unblock(user_name)
300
- puts "unblocked #{user.name}"
306
+ puts "unblocked #{user.screen_name}"
301
307
  end
302
308
  },
303
309
  :help => ['unblock USER', 'Unblock user']
@@ -442,7 +448,7 @@ module Termtter::Client
442
448
  :alias => :plugin,
443
449
  :exec_proc => lambda {|arg|
444
450
  if arg.empty?
445
- plugin_list
451
+ puts plugin_list.join(', ')
446
452
  return
447
453
  end
448
454
  begin
@@ -14,7 +14,7 @@ config.plugins.stdout.set_default(
14
14
  '<90>',
15
15
  '<%=reply_to_status_id ? " (reply_to [#{reply_to_status_id}]) " : ""%>',
16
16
  '<%=retweeted_status_id ? " (retweet_to [#{retweeted_status_id}]) " : ""%>',
17
- '<%=source%><%=s.user.protected ? "[P]" : ""%>',
17
+ '<%=source%><%=s[:user][:protected] ? "[P]" : ""%>',
18
18
  '</90>'
19
19
  ].join('')
20
20
  )
@@ -98,6 +98,10 @@ module Termtter
98
98
  print_statuses(statuses, event)
99
99
  end
100
100
 
101
+ def inspect
102
+ "#<Termtter::StdOut @name=#{@name}, @points=#{@points.inspect}, @exec_proc=#{@exec_proc.inspect}>"
103
+ end
104
+
101
105
  def print_statuses(statuses, event, sort = true, time_format = nil)
102
106
  return unless statuses and statuses.first
103
107
  time_format ||= Termtter::Client.time_format_for statuses
@@ -122,7 +126,7 @@ module Termtter
122
126
 
123
127
  def status_line(s, time_format, event, indent = 0)
124
128
  return '' unless s
125
- text = TermColor.escape(s.text)
129
+ text = escape(TermColor.escape(s.text))
126
130
  color = color_of_user(s.user)
127
131
  status_id = Termtter::Client.data_to_typable_id(s.id)
128
132
  reply_to_status_id =
@@ -148,13 +152,13 @@ module Termtter
148
152
 
149
153
  text = colorize_users(text)
150
154
  text = Client.get_hooks(:pre_coloring).inject(text) {|result, hook|
151
- Termtter::Client.logger.debug "stdout status_line: call hook :pre_coloring #{hook.inspect}"
155
+ #Termtter::Client.logger.debug "stdout status_line: call hook :pre_coloring #{hook.inspect}"
152
156
  hook.call(result, event)
153
157
  }
154
158
  indent_text = indent > 0 ? eval(config.plugins.stdout.indent_format) : ''
155
159
  erbed_text = ERB.new(config.plugins.stdout.timeline_format).result(binding)
156
160
  erbed_text = Client.get_hooks(:pre_output).inject(erbed_text) {|result, hook|
157
- Termtter::Client.logger.debug "stdout status_line: call hook :pre_output #{hook.inspect}"
161
+ #Termtter::Client.logger.debug "stdout status_line: call hook :pre_output #{hook.inspect}"
158
162
  hook.call(result, event)
159
163
  }
160
164
  text = TermColor.unescape(TermColor.parse(erbed_text) + "\n")
@@ -203,6 +207,10 @@ module Termtter
203
207
  def color_of_screen_name_cache
204
208
  @color_of_screen_name_cache ||= {}
205
209
  end
210
+
211
+ def escape(data)
212
+ data.gsub(/[:cntrl:]/) {|c| c == "\n" ? c : c.dump[1...-1]}.untaint
213
+ end
206
214
  end
207
215
 
208
216
  Client.register_hook(StdOut.new)
@@ -0,0 +1,27 @@
1
+ module Termtter::Client
2
+ register_command('hook list') do
3
+ name_max_size = hooks.keys.map{|i|i.size}.max
4
+ points_max_size = hooks.values.map{|i|i.points.join(', ').size}.max
5
+ hooks.each do |name, hook|
6
+ points = "[#{hook.points.join(', ')}]"
7
+ puts "#{name.to_s.ljust(name_max_size)} " +
8
+ "<90>=&gt;</90>".termcolor + " #{points.ljust(points_max_size)} " +
9
+ "<90>=&gt;</90>".termcolor + " #{hook.exec_proc}"
10
+ end
11
+ end
12
+
13
+ register_command('hook remove') do |name|
14
+ puts remove_hook(name) ? "removed => #{name}" : '<red>hook not found!</red>'.termcolor
15
+ end
16
+
17
+ register_command('command list') do
18
+ name_max_size = commands.keys.map{|i|i.size}.max
19
+ commands.each do |name, command|
20
+ puts "#{name.to_s.ljust(name_max_size)} " + "<90>=&gt;</90>".termcolor + " #{command.exec_proc}"
21
+ end
22
+ end
23
+
24
+ register_command('command remove') do |name|
25
+ puts remove_command(name) ? "removed => #{name}" : '<red>command not found!</red>'.termcolor
26
+ end
27
+ end
@@ -0,0 +1,13 @@
1
+ # Maintainer: Sora Harakami
2
+ # http://gist.github.com/453709
3
+
4
+ Termtter::Client.register_command(:name => :dupu, :exec => lambda do |body|
5
+ #Termtter::Client.execute("update #{arg.chars.inject([]){|r,v|r << v*(5+rand(3)}.join}")
6
+ body.chomp!
7
+ max = 140
8
+ len = body.split(//).length
9
+ mod = max % len
10
+ ext = (0...len).to_a.sort_by{ rand }.take(mod)
11
+ res = body.split(//).each_with_index.map{ |c, i| c * (max / len + (ext.include?(i) ? 1 : 0)) }.join('')
12
+ Termtter::Client.execute("update #{res}")
13
+ end)
@@ -0,0 +1,4 @@
1
+ Termtter::Client.register_command('erase') do |arg|
2
+ num = /(\d+)/ =~ arg ? $1.to_i : 1
3
+ print "\e[#{num + 1}F\e[0J"
4
+ end
@@ -0,0 +1,17 @@
1
+ config.plugins.error_log.set_default(:file, File.expand_path("~/.termtter/error.log.txt"))
2
+
3
+ Termtter::Client.register_hook(
4
+ :name => :error_log,
5
+ :point => :on_error,
6
+ :exec => lambda do |e|
7
+ open(config.plugins.error_log.file,"a") do |f|
8
+ f.puts "#{Time.now} ---------------------"
9
+ f.puts " #{e.class.to_s}: #{e.message}"
10
+ begin
11
+ e.backtrace.each do |s|
12
+ f.puts " #{s}"
13
+ end
14
+ rescue NoMethodError; end
15
+ end
16
+ end
17
+ )
@@ -12,6 +12,13 @@ URL_SHORTTERS = [
12
12
  {:host => "ow.ly", :pattern => %r'(http://ow\.ly(/[\w/]+))'},
13
13
  {:host => "u.nu", :pattern => %r'(http://u\.nu(/[\w/]+))'},
14
14
  {:host => "twurl.nl", :pattern => %r'(http://twurl\.nl(/\w+))'},
15
+ {:host => "icio.us", :pattern => %r'(http://icio\.us(/\w+))'},
16
+ {:host => "htn.to", :pattern => %r'(http://htn\.to(/\w+))'},
17
+ {:host => "cot.ag", :pattern => %r'(http://cot\.ag(/\w+))'},
18
+ {:host => "ht.ly", :pattern => %r'(http://ht\.ly(/\w+))'},
19
+ {:host => "p.tl", :pattern => %r'(http://p\.tl(/\w+))'},
20
+ {:host => "url4.eu", :pattern => %r'(http://url4\.eu(/\w+))'},
21
+ {:host => "t.co", :pattern => %r'(http://t\.co(/\w+))'},
15
22
  ]
16
23
 
17
24
  config.plugins.expand_tinyurl.set_default(:shortters, [])
@@ -39,7 +46,7 @@ def expand_url(host, path)
39
46
  res = Termtter::HTTPpool.start(host) do |h|
40
47
  h.get(path, { 'User-Agent' => 'Mozilla' })
41
48
  end
42
- return nil unless res.code == "301" or res.code == "302"
49
+ return nil unless res.code =~ /\A30/
43
50
  newurl = res['Location']
44
51
  newurl.respond_to?(:force_encoding) ? newurl.force_encoding(Encoding::UTF_8) : newurl
45
52
  rescue Exception => e
data/lib/plugins/growl.rb CHANGED
@@ -93,13 +93,16 @@ Termtter::Client.register_hook(
93
93
  # TODO: Add option for priority and sticky
94
94
  system 'growlnotify', s.user.screen_name, '-m', s.text.gsub("\n",''), '-n', 'termtter', '--image', get_icon_path(s)
95
95
  else
96
- growl.notify(
97
- "update_friends_timeline",
98
- s.user.screen_name,
99
- CGI.unescapeHTML(s.text),
100
- config.plugins.growl.priority,
101
- config.plugins.growl.sticky
102
- )
96
+ begin
97
+ growl.notify(
98
+ "update_friends_timeline",
99
+ s.user.screen_name,
100
+ CGI.unescapeHTML(s.text),
101
+ config.plugins.growl.priority,
102
+ config.plugins.growl.sticky
103
+ )
104
+ rescue Errno::ECONNREFUSED
105
+ end
103
106
  end
104
107
  sleep 0.1
105
108
  end
@@ -0,0 +1,88 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'nkf'
3
+ require 'open-uri'
4
+
5
+ module HatenaKeywordHaiku
6
+ class Word
7
+ def initialize(word, yomi)
8
+ raise 'word is nil' unless word and not word.empty?
9
+ @word = word
10
+ @yomi = yomi
11
+ end
12
+
13
+ def word
14
+ @word
15
+ end
16
+
17
+ def yomi
18
+ @yomi
19
+ end
20
+
21
+ def length
22
+ @length ||= self.yomi.gsub(/\n|ぁ|ぃ|ぅ|ぇ|ぉ|ァ|ィ|ゥ|ェ|ォ|ゃ|ゅ|ょ|ャ|ュ|ョ/, '').split(//).length
23
+ end
24
+ end
25
+
26
+ @@words = nil
27
+
28
+ def self.generate(*args)
29
+ args = [5,7,5] if args.empty?
30
+
31
+ args.map{ |len|
32
+ words[len.to_i].choice rescue raise "No word which length is #{len}"
33
+ }.map{ |w| w.word }.join(' ')
34
+ end
35
+
36
+ # http://d.hatena.ne.jp/hatenadiary/20060922/1158908401
37
+ def self.setup(csv_path = '/tmp/keywordlist_furigana.csv', csv_url = 'http://d.hatena.ne.jp/images/keyword/keywordlist_furigana.csv')
38
+ return if @@words
39
+ @@words = { }
40
+ csv_path = File.expand_path(csv_path)
41
+ unless File.exists? csv_path
42
+ puts "haiku: downloading CSV"
43
+ open(csv_path, 'w'){ |f|
44
+ f.write(open(csv_url).read)
45
+ }
46
+ end
47
+
48
+
49
+ puts "haiku: parsing CSV"
50
+ open(csv_path).each_line{ |line|
51
+ yomi, word = *NKF.nkf('-w', line.chomp).split(/\t/)
52
+ next unless yomi and word
53
+ w = Word.new(word, yomi)
54
+ @@words[w.length] = [] unless @@words.has_key? w.length
55
+ @@words[w.length].push w
56
+ }
57
+ puts "haiku: setup done"
58
+ @@words
59
+ end
60
+
61
+ def self.words
62
+ setup unless @@words
63
+ @@words
64
+ end
65
+ end
66
+
67
+ Thread.new{
68
+ HatenaKeywordHaiku.setup('~/.termtter/keywordlist_furigana.csv')
69
+ }
70
+ Termtter::Client.register_command(
71
+ :name => :hatena_keyword_haiku,
72
+ :aliases => [:haiku],
73
+ :author => 'hitode909',
74
+ :exec_proc => lambda {|arg|
75
+ args = arg.split(/\s+/)
76
+
77
+ name = ''
78
+ if args.first and not args.first =~ /^\d+$/
79
+ name = Termtter::Client.normalize_as_user_name(args.shift)
80
+ command = "u @#{name} #{HatenaKeywordHaiku.generate(*args)}"
81
+ else
82
+ command = "u #{HatenaKeywordHaiku.generate(*args)}"
83
+ end
84
+
85
+ Termtter::Client.execute command
86
+ },
87
+ :help => ['haiku [(Optinal) USER] [(Optional) 5 7 5 7 7]', 'Post a Haiku']
88
+ )
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'net/irc'
4
4
  require 'set'
5
+ require 'cgi'
5
6
 
6
7
  config.plugins.irc_gw.set_default(:port, 16669)
7
8
  config.plugins.irc_gw.set_default(:last_statuses_count, 100)
@@ -34,7 +35,7 @@ class TermtterIrcGateway < Net::IRC::Server::Session
34
35
  @@last_statuses = []
35
36
 
36
37
  Termtter::Client.register_hook(
37
- :name => :irc_gw,
38
+ :name => :irc_gw_output,
38
39
  :point => :output,
39
40
  :exec => lambda { |statuses, event|
40
41
  if event == :update_friends_timeline
@@ -47,6 +48,15 @@ class TermtterIrcGateway < Net::IRC::Server::Session
47
48
  end
48
49
  }
49
50
  )
51
+ Termtter::Client.register_hook(
52
+ :name => :irc_gw_handle_error,
53
+ :point => :on_error,
54
+ :exec => lambda { |error|
55
+ @@listners.each{ |listener|
56
+ listener.log "[ERROR] #{error.class.to_s}: #{error.message}"
57
+ }
58
+ }
59
+ )
50
60
  if Termtter::Client.respond_to? :register_output
51
61
  Termtter::Client.register_output(:irc) do |message|
52
62
  @@listners.each do |listener|
@@ -99,7 +109,7 @@ class TermtterIrcGateway < Net::IRC::Server::Session
99
109
  statuses.each do |s|
100
110
  typable_id = Termtter::Client.data_to_typable_id(s.id)
101
111
  time = Time.parse(s.created_at).strftime(time_format) if time_format
102
- post s.user.screen_name, msg_type, main_channel, [time, s.text, typable_id].compact.join(' ')
112
+ post s.user.screen_name, msg_type, main_channel, [time, CGI.unescapeHTML(s.text), typable_id].compact.join(' ')
103
113
  end
104
114
  end
105
115
 
@@ -109,7 +119,6 @@ class TermtterIrcGateway < Net::IRC::Server::Session
109
119
  post '#termtter', NOTICE, main_channel, '> ' + termtter_command
110
120
  Termtter::Client.execute(termtter_command)
111
121
  rescue Exception => e
112
- post '#termtter', NOTICE, main_channel, "#{e.class.to_s}: #{e.message}"
113
122
  Termtter::Client.handle_error(e)
114
123
  end
115
124
 
@@ -144,7 +153,6 @@ class TermtterIrcGateway < Net::IRC::Server::Session
144
153
  Termtter::Client.execute('update ' + message)
145
154
  post @prefix, TOPIC, main_channel, message
146
155
  rescue Exception => e
147
- post '#termtter', NOTICE, main_channel, "#{e.class.to_s}: #{e.message}"
148
156
  Termtter::Client.handle_error(e)
149
157
  end
150
158
 
@@ -1,33 +1,36 @@
1
1
  # -*- coding: utf-8 -*-
2
- require 'appscript' or raise 'itunes plugin cannot run'
2
+ begin
3
+ require 'appscript'
4
+ rescue LoadError
5
+ raise "itunes plug: can't load appscript gem. please run 'gem install rb-appscript'"
6
+ end
3
7
 
4
8
  config.plugins.itunes.set_default(:prefix, 'Listening now:')
5
9
  config.plugins.itunes.set_default(:suffix, '#iTunes #listening')
6
- config.plugins.itunes.set_default(
7
- :format,
10
+ config.plugins.itunes.set_default(:format,
8
11
  '<%=prefix%> <%=track_name%> (<%=time%>) <%=artist%> <%=album%> <%=suffix%>')
9
12
 
10
- module Termtter::Client
11
- register_command :name => :listening_now, :aliases => [:ln],
12
- :help => ['listening_now,ln', "Post the information of listening now."],
13
- :exec_proc => lambda {|args|
14
- begin
15
- prefix = config.plugins.itunes.prefix
16
- track_name = Appscript.app('iTunes').current_track.name.get
17
- artist = Appscript.app('iTunes').current_track.artist.get
18
- genre = Appscript.app('iTunes').current_track.genre.get
19
- time = Appscript.app('iTunes').current_track.time.get
20
- album = Appscript.app('iTunes').current_track.album.get
21
- suffix = config.plugins.itunes.suffix
22
- erbed_text = ERB.new(config.plugins.itunes.format).result(binding)
23
- erbed_text.gsub!(/\s{2,}/, ' ')
24
- if args.length > 0
25
- erbed_text = args + ' ' + erbed_text
26
- end
27
- Termtter::API.twitter.update(erbed_text)
28
- puts "=> " << erbed_text
29
- rescue => e
30
- p e
13
+ Termtter::Client.register_command(
14
+ :name => :listening_now, :aliases => [:ln, :itunes, :music, :m],
15
+ :help => ['listening_now,ln,itunes,music', "Post the information of listening now."],
16
+ :exec => lambda {|args|
17
+ begin
18
+ prefix = config.plugins.itunes.prefix
19
+ track_name = Appscript.app('iTunes').current_track.name.get
20
+ artist = Appscript.app('iTunes').current_track.artist.get
21
+ genre = Appscript.app('iTunes').current_track.genre.get
22
+ time = Appscript.app('iTunes').current_track.time.get
23
+ album = Appscript.app('iTunes').current_track.album.get
24
+ suffix = config.plugins.itunes.suffix
25
+ erbed_text = ERB.new(config.plugins.itunes.format).result(binding)
26
+ erbed_text.gsub!(/\s{2,}/, ' ')
27
+ if args.length > 0
28
+ erbed_text = args + ' ' + erbed_text
31
29
  end
32
- }
33
- end
30
+ Termtter::API.twitter.update(erbed_text)
31
+ puts "=> " << erbed_text
32
+ rescue => e
33
+ p e
34
+ end
35
+ }
36
+ )
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ $KCODE = 'u' unless defined?(Encoding)
3
+ # mecab('これはテストです') #=>
4
+ # [["これ", "名詞", "代名詞", "一般", "*", "*", "*", "これ", "コレ", "コレ"],
5
+ # ["は", "助詞", "係助詞", "*", "*", "*", "*", "は", "ハ", "ワ"],
6
+ # ["テスト", "名詞", "サ変接続", "*", "*", "*", "*", "テスト", "テスト", "テスト"],
7
+ # ["です", "助動詞", "*", "*", "*", "特殊・デス", "基本形", "です", "デス", "デス"]]
8
+ def mecab(str)
9
+ IO.popen('mecab', 'r+') {|io|
10
+ io.puts str
11
+ io.close_write
12
+ io.read.split(/\n/).map {|i| i.split(/\t|,/) }[0..-2]
13
+ }
14
+ end
15
+
16
+ Termtter::Client.register_command(
17
+ :name => 'mecab',
18
+ :help => 'post a Japanese message with syntaxtic explanations. Requirements: mecab command',
19
+ :exec => lambda {|arg|
20
+ text = mecab(arg).map {|i| "#{i[0]}(#{i[1]}: #{i[2]})" }.join + ' #mecab'
21
+ update(text)
22
+ puts "=> #{test}"
23
+ })