emasaka-termtter 1.0.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. data/History.txt +4 -0
  2. data/README.rdoc +100 -0
  3. data/Rakefile +55 -0
  4. data/bin/kill_termtter +22 -0
  5. data/bin/termtter +6 -0
  6. data/lib/plugins/addspace.rb +27 -0
  7. data/lib/plugins/april_fool.rb +15 -0
  8. data/lib/plugins/bomb.rb +39 -0
  9. data/lib/plugins/clear.rb +14 -0
  10. data/lib/plugins/command_plus.rb +47 -0
  11. data/lib/plugins/confirm.rb +12 -0
  12. data/lib/plugins/cool.rb +10 -0
  13. data/lib/plugins/countter.rb +23 -0
  14. data/lib/plugins/devel.rb +18 -0
  15. data/lib/plugins/direct_messages.rb +36 -0
  16. data/lib/plugins/en2ja.rb +11 -0
  17. data/lib/plugins/english.rb +25 -0
  18. data/lib/plugins/erb.rb +17 -0
  19. data/lib/plugins/exec_and_update.rb +14 -0
  20. data/lib/plugins/expand-tinyurl.rb +33 -0
  21. data/lib/plugins/fib.rb +28 -0
  22. data/lib/plugins/fib_filter.rb +14 -0
  23. data/lib/plugins/filter.rb +69 -0
  24. data/lib/plugins/graduatter.rb +8 -0
  25. data/lib/plugins/grass.rb +27 -0
  26. data/lib/plugins/group.rb +64 -0
  27. data/lib/plugins/growl.rb +52 -0
  28. data/lib/plugins/growl2.rb +143 -0
  29. data/lib/plugins/hatebu.rb +59 -0
  30. data/lib/plugins/history.rb +93 -0
  31. data/lib/plugins/ignore.rb +19 -0
  32. data/lib/plugins/keyword.rb +18 -0
  33. data/lib/plugins/l2.rb +25 -0
  34. data/lib/plugins/log.rb +73 -0
  35. data/lib/plugins/me.rb +10 -0
  36. data/lib/plugins/modify_arg_hook_sample.rb +7 -0
  37. data/lib/plugins/msagent.rb +38 -0
  38. data/lib/plugins/multi_reply.rb +27 -0
  39. data/lib/plugins/notify-send.rb +22 -0
  40. data/lib/plugins/notify-send2.rb +52 -0
  41. data/lib/plugins/open_url.rb +59 -0
  42. data/lib/plugins/otsune.rb +21 -0
  43. data/lib/plugins/outputz.rb +33 -0
  44. data/lib/plugins/pause.rb +3 -0
  45. data/lib/plugins/post_exec_hook_sample.rb +9 -0
  46. data/lib/plugins/pre_exec_hook_sample.rb +9 -0
  47. data/lib/plugins/primes.rb +30 -0
  48. data/lib/plugins/quicklook.rb +41 -0
  49. data/lib/plugins/random.rb +23 -0
  50. data/lib/plugins/reblog.rb +40 -0
  51. data/lib/plugins/reload.rb +3 -0
  52. data/lib/plugins/reply.rb +8 -0
  53. data/lib/plugins/retweet.rb +46 -0
  54. data/lib/plugins/reverse.rb +13 -0
  55. data/lib/plugins/say.rb +26 -0
  56. data/lib/plugins/scrape.rb +41 -0
  57. data/lib/plugins/screen-notify.rb +20 -0
  58. data/lib/plugins/screen.rb +24 -0
  59. data/lib/plugins/shell.rb +14 -0
  60. data/lib/plugins/shorturl_on_update.rb +36 -0
  61. data/lib/plugins/sl.rb +48 -0
  62. data/lib/plugins/spam.rb +16 -0
  63. data/lib/plugins/standard_plugins.rb +519 -0
  64. data/lib/plugins/stdout.rb +83 -0
  65. data/lib/plugins/storage.rb +55 -0
  66. data/lib/plugins/storage/DB.rb +37 -0
  67. data/lib/plugins/storage/status.rb +83 -0
  68. data/lib/plugins/storage/status_mook.rb +30 -0
  69. data/lib/plugins/switch_user.rb +22 -0
  70. data/lib/plugins/system_status.rb +33 -0
  71. data/lib/plugins/timer.rb +18 -0
  72. data/lib/plugins/translation.rb +38 -0
  73. data/lib/plugins/typable_id.rb +94 -0
  74. data/lib/plugins/update_editor.rb +53 -0
  75. data/lib/plugins/update_filter.rb +30 -0
  76. data/lib/plugins/uri-open.rb +66 -0
  77. data/lib/plugins/wassr_post.rb +22 -0
  78. data/lib/plugins/yhara.rb +148 -0
  79. data/lib/plugins/yhara_filter.rb +8 -0
  80. data/lib/plugins/yonda.rb +21 -0
  81. data/lib/termtter.rb +38 -0
  82. data/lib/termtter/api.rb +57 -0
  83. data/lib/termtter/client.rb +370 -0
  84. data/lib/termtter/command.rb +80 -0
  85. data/lib/termtter/config.rb +68 -0
  86. data/lib/termtter/config_setup.rb +38 -0
  87. data/lib/termtter/connection.rb +41 -0
  88. data/lib/termtter/hook.rb +31 -0
  89. data/lib/termtter/optparse.rb +14 -0
  90. data/lib/termtter/system_extensions.rb +161 -0
  91. data/lib/termtter/task.rb +17 -0
  92. data/lib/termtter/task_manager.rb +116 -0
  93. data/lib/termtter/version.rb +4 -0
  94. data/spec/plugins/cool_spec.rb +10 -0
  95. data/spec/plugins/english_spec.rb +19 -0
  96. data/spec/plugins/fib_spec.rb +15 -0
  97. data/spec/plugins/filter_spec.rb +18 -0
  98. data/spec/plugins/pause_spec.rb +8 -0
  99. data/spec/plugins/primes_spec.rb +15 -0
  100. data/spec/plugins/shell_spec.rb +10 -0
  101. data/spec/plugins/sl_spec.rb +8 -0
  102. data/spec/plugins/spam_spec.rb +4 -0
  103. data/spec/plugins/standard_plugins_spec.rb +23 -0
  104. data/spec/plugins/storage/DB_spec.rb +12 -0
  105. data/spec/plugins/storage/status_spec.rb +24 -0
  106. data/spec/spec_helper.rb +7 -0
  107. data/spec/termtter/client_spec.rb +255 -0
  108. data/spec/termtter/command_spec.rb +107 -0
  109. data/spec/termtter/config_spec.rb +111 -0
  110. data/spec/termtter/hook_spec.rb +78 -0
  111. data/spec/termtter/task_manager_spec.rb +78 -0
  112. data/spec/termtter/task_spec.rb +22 -0
  113. data/spec/termtter_spec.rb +29 -0
  114. data/test/friends_timeline.json +5 -0
  115. data/test/search.json +8 -0
  116. metadata +210 -0
@@ -0,0 +1,11 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ plugin 'translation'
4
+
5
+ Termtter::Client.add_filter do |statuses, event|
6
+ statuses.each do |s|
7
+ if s.english?
8
+ s.text = translate(s.text, 'en|ja')
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,25 @@
1
+ # -*- coding: utf-8 -*-
2
+ # vim: set fenc=utf-8
3
+
4
+ module Termtter::English
5
+ # english? :: String -> Boolean
6
+ def self.english?(message)
7
+ /[一-龠]+|[ぁ-ん]+|[ァ-ヴー]+|[a-zA-Z0-9]+/ !~ message
8
+ end
9
+ end
10
+
11
+ Termtter::Client.add_filter do |statuses, event|
12
+ config.plugins.english.set_default(:only, [])
13
+ statuses.select {|i|
14
+ !config.plugins.english.only.include?(event) ||
15
+ Termtter::English.english?(i.text)
16
+ }
17
+ end
18
+
19
+ # english_filter.rb
20
+ # select English posts only
21
+ #
22
+ # config sample:
23
+ # plugin 'english'
24
+ # or,
25
+ # plugin 'english', :only => [:list_friends_timeline, :update_friends_timeline]
@@ -0,0 +1,17 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'erb'
4
+
5
+ Termtter::Client.register_hook(
6
+ :name => :erb,
7
+ :point => :modify_arg_for_update,
8
+ :exec_proc => lambda {|cmd, arg|
9
+ ERB.new(arg).result(binding)
10
+ }
11
+ )
12
+
13
+ # erb.rb
14
+ # enable to <%= %> in the command update
15
+ # example:
16
+ # > u erb test <%= 1+1 %>
17
+ # => erb test 2
@@ -0,0 +1,14 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ Termtter::Client.register_command(
4
+ :name => :exec_and_update,
5
+ :exec_proc => lambda{|arg|
6
+ return unless arg
7
+ `#{arg}`.each_line do |line|
8
+ next if line =~ /^\s*$/
9
+ Termtter::API.twitter.update(line)
10
+ puts "=> #{line}"
11
+ end
12
+ },
13
+ :help => ['exec_and_update COMMAND', 'execute the command']
14
+ )
@@ -0,0 +1,33 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ URL_SHORTTERS = [
4
+ { :host => "tinyurl.com", :pattern => %r'(http://tinyurl\.com(/[\w/]+))' },
5
+ { :host => "is.gd", :pattern => %r'(http://is\.gd(/[\w/]+))' },
6
+ # { :host => "bit.ly", :pattern => %r'(http://bit\.ly(/[\w/]+))' }
7
+ ]
8
+
9
+ module Termtter::Client
10
+ add_filter do |statuses, event|
11
+ statuses.each do |s|
12
+ URL_SHORTTERS.each do |site|
13
+ s.text.gsub!(site[:pattern]) do |m|
14
+ expand_url(site[:host], $2) || $1
15
+ end
16
+ end
17
+ end
18
+ statuses
19
+ end
20
+ end
21
+
22
+ def expand_url(host, path)
23
+ http_class = Net::HTTP
24
+ unless config.proxy.host.nil? or config.proxy.host.empty?
25
+ http_class = Net::HTTP::Proxy(config.proxy.host,
26
+ config.proxy.port,
27
+ config.proxy.user_name,
28
+ config.proxy.password)
29
+ end
30
+ res = http_class.new('tinyurl.com').head(path)
31
+ return nil unless res.code == "301" or res.code == "302"
32
+ res['Location']
33
+ end
@@ -0,0 +1,28 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ def fib(n)i=0;j=1;n.times{j=i+i=j};i end
4
+ module Termtter::Client
5
+ register_command(
6
+ :name => :fib,
7
+ :exec_proc => lambda {|arg|
8
+ n = arg.to_i
9
+ text = "fib(#{n}) = #{fib n}"
10
+ Termtter::API.twitter.update(text)
11
+ puts "=> " << text
12
+ }
13
+ )
14
+ register_command(
15
+ :name => :fibyou,
16
+ :exec_proc => lambda {|arg|
17
+ /(\w+)\s(\d+)/ =~ arg
18
+ name = $1
19
+ n = $2.to_i
20
+ text = "@#{name} fib(#{n}) = #{fib n}"
21
+ Termtter::API.twitter.update(text)
22
+ puts "=> " << text
23
+ },
24
+ :completion_proc => lambda {|cmd, arg|
25
+ find_user_candidates arg, "#{cmd} %s"
26
+ }
27
+ )
28
+ end
@@ -0,0 +1,14 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ def fib(n)i=0;j=1;n.times{j=i+i=j};i end
4
+ module Termtter::Client
5
+ add_filter do |statuses, _|
6
+ statuses.each do |s|
7
+ s.text.gsub!(/(\d+)/) do |m|
8
+ n = $1.to_i
9
+ n < 1000000000 ? fib(n) : n # not to calc fib(id)
10
+ end
11
+ end
12
+ statuses
13
+ end
14
+ end
@@ -0,0 +1,69 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+
4
+ module Termtter::Client
5
+ public_storage[:filters] = []
6
+ filters = Dir["#{File.dirname(__FILE__)}/../filter/*.rb"].map do |f|
7
+ f.match(%r|([^/]+).rb$|)[1]
8
+ end
9
+
10
+ register_command(
11
+ :name => :filter, :aliases => [],
12
+ :exec_proc => lambda {|arg|
13
+ begin
14
+ result = filter arg.strip
15
+ rescue LoadError
16
+ result = false
17
+ ensure
18
+ puts "=> #{result.inspect}"
19
+ end
20
+ },
21
+ :completion_proc => lambda {|cmd, args|
22
+ find_filter_candidates args, "#{cmd} %s", filters
23
+ },
24
+ :help => ['filter FILE', 'Apply a filter']
25
+ )
26
+
27
+ register_command(
28
+ :name => :unfilter, :aliases => [],
29
+ :exec_proc => lambda {|arg|
30
+ clear_filters
31
+ public_storage[:filters].clear
32
+ puts '=> filter cleared'
33
+ },
34
+ :help => ['ufilter', 'Clear all filters']
35
+ )
36
+
37
+ register_command(
38
+ :name => :filters, :aliases => [],
39
+ :exec_proc => lambda {|arg|
40
+ unless public_storage[:filters].empty?
41
+ puts public_storage[:filters].join(', ')
42
+ else
43
+ puts 'no filter was applied'
44
+ end
45
+ },
46
+ :help => ['filters', 'Show list of applied filters']
47
+ )
48
+
49
+ def self.find_filter_candidates(a, b, filters)
50
+ if a.empty?
51
+ filters.to_a
52
+ else
53
+ filters.grep(/^#{Regexp.quote a}/i)
54
+ end.
55
+ map {|u| b % u }
56
+ end
57
+ end
58
+
59
+ # filter.rb
60
+ # a dynamic filter loader
61
+ # example
62
+ # > list
63
+ # (15:49:00) termtter: こんにちは
64
+ # (15:48:02) termtter: hello
65
+ # > filter english
66
+ # => true
67
+ # > list
68
+ # (15:48:02) termtter: hello
69
+ # vim: fenc=utf8
@@ -0,0 +1,8 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ Thread.start do
4
+ 100.times do |i|
5
+ Twitter::API.twitter.update(
6
+ "I decided not to use twitter so as not to leave university before I complete the dissertation#{i.odd? ? '!' : '.'}")
7
+ end
8
+ end
@@ -0,0 +1,27 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Termtter
3
+ module Client
4
+
5
+ config.plugins.grass.set_default(:rate, 0)
6
+
7
+ register_command(
8
+ :name => :w, :aliases => [:grass],
9
+ :exec_proc => lambda {|arg|
10
+ arg, rate = arg.split(/ /)
11
+ count = arg =~ /^[0-9]+$/ ? arg.to_i : 3
12
+ rate ||= config.plugins.grass.rate
13
+ grow = (count * rate.to_i).quo(100).round
14
+ grasses = ('w' * (count-grow) + 'W' * grow).split(//).shuffle.join
15
+ call_commands("update #{grasses}")
16
+ },
17
+ :help => ['grass, w', 'Grass it!']
18
+ )
19
+ end
20
+ end
21
+
22
+ # usage
23
+ # > w 10
24
+ # => wwwwwwwwww
25
+ #
26
+ # see also
27
+ # http://d.hatena.ne.jp/tomisima/20090204/1233762301
@@ -0,0 +1,64 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Termtter
4
+ class Status
5
+ def is_member?(group = nil)
6
+ if group
7
+ config.plugins.group.groups[group].include? self.user_screen_name
8
+ else
9
+ config.plugins.group.groups.values.flatten.include? self.user_screen_name
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ module Termtter::Client
16
+ config.plugins.group.
17
+ set_default(:groups, {})
18
+
19
+ def self.find_group_candidates(a, b)
20
+ config.plugins.group.groups.keys.map {|k| k.to_s}.
21
+ grep(/^#{Regexp.quote a}/).
22
+ map {|u| b % u }
23
+ end
24
+
25
+ def self.get_group_of(screen_name)
26
+ config.plugins.group.groups.select{ |k, v| v.include? screen_name}.map{|a| a.first}
27
+ end
28
+
29
+ register_command(
30
+ :name => :group,
31
+ :aliases => [:g],
32
+ :exec_proc => lambda {|arg|
33
+ unless arg.empty?
34
+ group_name = arg.to_sym
35
+ if group_name == :all
36
+ targets = config.plugins.group.groups.values.flatten.uniq
37
+ else
38
+ targets = config.plugins.group.groups[group_name]
39
+ end
40
+ statuses = targets ? targets.map { |target|
41
+ public_storage[:tweet][target]
42
+ }.flatten.uniq.compact.sort_by{ |s| s[:id]} : []
43
+ output(statuses, :search)
44
+ else
45
+ config.plugins.group.groups.each_pair do |key, value|
46
+ puts "#{key}: #{value.join(',')}"
47
+ end
48
+ end
49
+ },
50
+ :completion_proc => lambda {|cmd, arg|
51
+ find_group_candidates arg, "#{cmd} %s"
52
+ },
53
+ :help => ['group,g GROUPNAME', 'Filter by group members']
54
+ )
55
+
56
+ end
57
+
58
+ # group.rb
59
+ # plugin 'group'
60
+ # config.plugins.group.groups = {
61
+ # :rits => %w(hakobe isano hitode909)
62
+ # }
63
+ # NOTE: group.rb needs plugin/log
64
+
@@ -0,0 +1,52 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'tmpdir'
4
+ require 'open-uri'
5
+ require 'uri'
6
+ require 'fileutils'
7
+ require 'cgi'
8
+
9
+ begin
10
+ require 'ruby-growl'
11
+ growl = Growl.new "localhost", "termtter", ["update_friends_timeline"]
12
+ rescue LoadError
13
+ growl = nil
14
+ end
15
+
16
+ config.plugins.growl.set_default(:icon_cache_dir, "#{Termtter::CONF_DIR}/tmp/user_profile_images")
17
+ FileUtils.mkdir_p(config.plugins.growl.icon_cache_dir) unless File.exist?(config.plugins.growl.icon_cache_dir)
18
+
19
+ def get_icon_path(s)
20
+ Dir.mkdir_p(config.plugins.growl.icon_cache_dir) unless File.exists?(config.plugins.growl.icon_cache_dir)
21
+ cache_file = "%s/%s%s" % [ config.plugins.growl.icon_cache_dir,
22
+ s.user.screen_name,
23
+ File.extname(s.user.profile_image_url) ]
24
+ if !File.exist?(cache_file) || (File.atime(cache_file) + 24*60*60) < Time.now
25
+ File.open(cache_file, "wb") do |f|
26
+ begin
27
+ f << open(URI.escape(s.user.profile_image_url)).read
28
+ rescue OpenURI::HTTPError
29
+ return nil
30
+ end
31
+ end
32
+ end
33
+ cache_file
34
+ end
35
+
36
+ Termtter::Client.register_hook(
37
+ :name => :growl,
38
+ :points => [:output],
39
+ :exec_proc => lambda {|statuses, event|
40
+ return unless event == :update_friends_timeline
41
+ Thread.start do
42
+ statuses.each do |s|
43
+ unless growl
44
+ system 'growlnotify', s.user.screen_name, '-m', s.text.gsub("\n",''), '-n', 'termtter', '--image', get_icon_path(s)
45
+ else
46
+ growl.notify "update_friends_timeline", s.user.screen_name, CGI.unescapeHTML(s.text)
47
+ end
48
+ sleep 0.1
49
+ end
50
+ end
51
+ }
52
+ )
@@ -0,0 +1,143 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'open-uri'
4
+ require 'uri'
5
+ require 'fileutils'
6
+ require 'cgi'
7
+
8
+ begin
9
+ require 'meow'
10
+ growl = Meow.new('termtter', 'update_friends_timeline')
11
+ rescue LoadError
12
+ growl = nil
13
+ end
14
+
15
+ config.plugins.growl.set_default(:icon_cache_dir, "#{Termtter::CONF_DIR}/tmp/user_profile_images")
16
+ config.plugins.growl.set_default(:growl_user, [])
17
+ config.plugins.growl.set_default(:growl_keyword, [])
18
+ config.plugins.growl.set_default(:priority_veryhigh_user, [])
19
+ config.plugins.growl.set_default(:priority_high_user, [])
20
+ config.plugins.growl.set_default(:priority_normal_user, [])
21
+ config.plugins.growl.set_default(:priority_low_user, [])
22
+ config.plugins.growl.set_default(:priority_verylow_user, [])
23
+ config.plugins.growl.set_default(:priority_veryhigh_keyword, [])
24
+ config.plugins.growl.set_default(:priority_high_keyword, [])
25
+ config.plugins.growl.set_default(:priority_normal_keyword, [])
26
+ config.plugins.growl.set_default(:priority_low_keyword, [])
27
+ config.plugins.growl.set_default(:priority_verylow_keyword, [])
28
+ config.plugins.growl.set_default(:sticky_user, [])
29
+ config.plugins.growl.set_default(:sticky_keyword, [])
30
+ growl_keys = { 'user' => config.plugins.growl.growl_user,
31
+ 'keyword' => Regexp.union(*config.plugins.growl.growl_keyword) }
32
+ priority_keys = { 'user' => [config.plugins.growl.priority_veryhigh_user,
33
+ config.plugins.growl.priority_high_user,
34
+ config.plugins.growl.priority_normal_user,
35
+ config.plugins.growl.priority_low_user,
36
+ config.plugins.growl.priority_verylow_user],
37
+ 'keyword' => [Regexp.union(*config.plugins.growl.priority_veryhigh_keyword),
38
+ Regexp.union(*config.plugins.growl.priority_high_keyword),
39
+ Regexp.union(*config.plugins.growl.priority_normal_keyword),
40
+ Regexp.union(*config.plugins.growl.priority_low_keyword),
41
+ Regexp.union(*config.plugins.growl.priority_verylow_keyword) ] }
42
+ sticky_keys = { 'user' => config.plugins.growl.sticky_user,
43
+ 'keyword' => Regexp.union(*config.plugins.growl.sticky_keyword) }
44
+
45
+ FileUtils.mkdir_p(config.plugins.growl.icon_cache_dir) unless File.exist?(config.plugins.growl.icon_cache_dir)
46
+ Dir.glob("#{config.plugins.growl.icon_cache_dir}/*") {|f| File.delete(f) unless File.size?(f) }
47
+ unless File.exist?("#{config.plugins.growl.icon_cache_dir}/default.png")
48
+ File.open("#{config.plugins.growl.icon_cache_dir}/default.png", "wb") do |f|
49
+ f << open("http://static.twitter.com/images/default_profile_normal.png").read
50
+ end
51
+ end
52
+
53
+ def get_icon_path(s)
54
+ /https?:\/\/.+\/(\d+)\/.*?$/ =~ s.user.profile_image_url
55
+ cache_file = "%s/%s-%s%s" % [ config.plugins.growl.icon_cache_dir,
56
+ s.user.screen_name,
57
+ $+,
58
+ File.extname(s.user.profile_image_url) ]
59
+ unless File.exist?(cache_file)
60
+ Thread.new(s,cache_file) do |s,cache_file|
61
+ Dir.glob("#{config.plugins.growl.icon_cache_dir}/#{s.user.screen_name}-*") {|f| File.delete(f) }
62
+ begin
63
+ s.user.profile_image_url.sub!(/^https/,'http')
64
+ File.open(cache_file, 'wb') do |f|
65
+ f << open(URI.escape(s.user.profile_image_url)).read
66
+ end
67
+ rescue OpenURI::HTTPError
68
+ cache_file = "#{config.plugins.growl.icon_cache_dir}/default.png"
69
+ end
70
+ end
71
+ end
72
+ return cache_file
73
+ end
74
+
75
+ def get_priority(s,priority_keys)
76
+ priority = 2
77
+ 5.times {|n|
78
+ return priority.to_s if priority_keys['user'][n].include?(s.user.screen_name) ||
79
+ priority_keys['keyword'][n] =~ s.text
80
+ priority -= 1
81
+ }
82
+ return '0'
83
+ end
84
+
85
+ def is_growl(s,growl_keys)
86
+ return true if (growl_keys['user'].empty? && growl_keys['keyword'] == /(?!)/) ||
87
+ (growl_keys['user'].include?(s.user.screen_name) || growl_keys['keyword'] =~ s.text)
88
+ return false
89
+ end
90
+
91
+ def is_sticky(s,sticky_keys)
92
+ return true if sticky_keys['user'].include?(s.user.screen_name) || sticky_keys['keyword'] =~ s.text
93
+ return false
94
+ end
95
+
96
+ Termtter::Client.register_hook(
97
+ :name => :growl2,
98
+ :points => [:output],
99
+ :exec_proc => lambda {|statuses, event|
100
+ return unless event == :update_friends_timeline
101
+ Thread.start do
102
+ statuses.each do |s|
103
+ next unless is_growl(s,growl_keys)
104
+ growl_title = s.user.screen_name
105
+ growl_title += " (#{s.user.name})" unless s.user.screen_name == s.user.name
106
+ unless growl
107
+ arg = ['growlnotify', growl_title, '-m', s.text.gsub("\n",''), '-n', 'termtter', '-p', get_priority(s,priority_keys), '--image', get_icon_path(s)]
108
+ arg.push('-s') if is_sticky(s,sticky_keys)
109
+ system *arg
110
+ else
111
+ begin
112
+ icon = Meow.import_image(get_icon_path(s))
113
+ rescue
114
+ icon = Meow.import_image("#{config.plugins.growl.icon_cache_dir}/default.png")
115
+ end
116
+ growl.notify(growl_title, CGI.unescape(CGI.unescapeHTML(s.text)),
117
+ {:icon => icon,
118
+ :priority => get_priority(s,priority_keys),
119
+ :sticky => is_sticky(s,sticky_keys) }) do
120
+ s.text.gsub(URI.regexp) {|uri| system "open #{uri}"}
121
+ end
122
+ end
123
+ sleep 0.1
124
+ end
125
+ end
126
+ }
127
+ )
128
+ #Optional setting example.
129
+ # Growl ON setting.
130
+ # config.plugins.growl.growl_user = ['p2pquake', 'jihou']
131
+ # config.plugins.growl.growl_keyword = ['地震', /^@screen_name/]
132
+ # Priority setting.
133
+ # config.plugins.growl.priority_veryhigh_user = ['veryhigh_user']
134
+ # config.plugins.growl.priority_veryhigh_keyword = ['veryhigh_keyword', /^@screen_name']
135
+ # config.plugins.growl.priority_high_user = ['high_user']
136
+ # config.plugins.growl.priority_high_keyword = ['high_keyword']
137
+ # config.plugins.growl.priority_low_user = ['low_user']
138
+ # config.plugins.growl.priority_low_keyword = ['low_keyword']
139
+ # config.plugins.growl.priority_verylow_user = ['verylow_user']
140
+ # config.plugins.growl.priority_verylow_keyword = ['verylow_keyword']
141
+ # Sticky setting.
142
+ # config.plugins.growl.sticky_user = ['screen_name']
143
+ # config.plugins.growl.sticky_keyword = [/^@screen_name/, '#termtter']