draftcode-termtter 1.0.8

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 (118) 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 +33 -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.rb +17 -0
  20. data/lib/plugins/exec_and_update.rb +14 -0
  21. data/lib/plugins/expand-tinyurl.rb +34 -0
  22. data/lib/plugins/fib.rb +28 -0
  23. data/lib/plugins/fib_filter.rb +14 -0
  24. data/lib/plugins/filter.rb +69 -0
  25. data/lib/plugins/graduatter.rb +8 -0
  26. data/lib/plugins/grass.rb +27 -0
  27. data/lib/plugins/group.rb +64 -0
  28. data/lib/plugins/growl.rb +52 -0
  29. data/lib/plugins/growl2.rb +143 -0
  30. data/lib/plugins/hatebu.rb +59 -0
  31. data/lib/plugins/hatebu_and_update.rb +58 -0
  32. data/lib/plugins/history.rb +93 -0
  33. data/lib/plugins/ignore.rb +19 -0
  34. data/lib/plugins/keyword.rb +18 -0
  35. data/lib/plugins/l2.rb +25 -0
  36. data/lib/plugins/log.rb +73 -0
  37. data/lib/plugins/me.rb +10 -0
  38. data/lib/plugins/modify_arg_hook_sample.rb +7 -0
  39. data/lib/plugins/msagent.rb +38 -0
  40. data/lib/plugins/multi_reply.rb +27 -0
  41. data/lib/plugins/notify-send.rb +22 -0
  42. data/lib/plugins/notify-send2.rb +52 -0
  43. data/lib/plugins/notify-send3.rb +45 -0
  44. data/lib/plugins/open_url.rb +59 -0
  45. data/lib/plugins/otsune.rb +21 -0
  46. data/lib/plugins/outputz.rb +33 -0
  47. data/lib/plugins/pause.rb +3 -0
  48. data/lib/plugins/post_exec_hook_sample.rb +9 -0
  49. data/lib/plugins/pre_exec_hook_sample.rb +9 -0
  50. data/lib/plugins/primes.rb +30 -0
  51. data/lib/plugins/quicklook.rb +41 -0
  52. data/lib/plugins/random.rb +23 -0
  53. data/lib/plugins/reblog.rb +40 -0
  54. data/lib/plugins/reload.rb +3 -0
  55. data/lib/plugins/reply.rb +8 -0
  56. data/lib/plugins/retweet.rb +46 -0
  57. data/lib/plugins/reverse.rb +13 -0
  58. data/lib/plugins/say.rb +26 -0
  59. data/lib/plugins/scrape.rb +41 -0
  60. data/lib/plugins/screen-notify.rb +20 -0
  61. data/lib/plugins/screen.rb +24 -0
  62. data/lib/plugins/shell.rb +14 -0
  63. data/lib/plugins/sl.rb +48 -0
  64. data/lib/plugins/spam.rb +16 -0
  65. data/lib/plugins/standard_plugins.rb +525 -0
  66. data/lib/plugins/stdout.rb +220 -0
  67. data/lib/plugins/storage.rb +55 -0
  68. data/lib/plugins/storage/DB.rb +37 -0
  69. data/lib/plugins/storage/status.rb +83 -0
  70. data/lib/plugins/storage/status_mook.rb +30 -0
  71. data/lib/plugins/switch_user.rb +22 -0
  72. data/lib/plugins/system_status.rb +33 -0
  73. data/lib/plugins/timer.rb +18 -0
  74. data/lib/plugins/tinyurl.rb +20 -0
  75. data/lib/plugins/translation.rb +38 -0
  76. data/lib/plugins/typable_id.rb +94 -0
  77. data/lib/plugins/update_editor.rb +53 -0
  78. data/lib/plugins/uri-open.rb +66 -0
  79. data/lib/plugins/wassr_post.rb +22 -0
  80. data/lib/plugins/yhara.rb +148 -0
  81. data/lib/plugins/yhara_filter.rb +8 -0
  82. data/lib/plugins/yonda.rb +21 -0
  83. data/lib/termtter.rb +38 -0
  84. data/lib/termtter/api.rb +57 -0
  85. data/lib/termtter/client.rb +324 -0
  86. data/lib/termtter/command.rb +80 -0
  87. data/lib/termtter/config.rb +68 -0
  88. data/lib/termtter/config_setup.rb +38 -0
  89. data/lib/termtter/connection.rb +41 -0
  90. data/lib/termtter/hook.rb +31 -0
  91. data/lib/termtter/optparse.rb +14 -0
  92. data/lib/termtter/system_extensions.rb +115 -0
  93. data/lib/termtter/task.rb +17 -0
  94. data/lib/termtter/task_manager.rb +116 -0
  95. data/lib/termtter/version.rb +4 -0
  96. data/spec/plugins/cool_spec.rb +10 -0
  97. data/spec/plugins/english_spec.rb +19 -0
  98. data/spec/plugins/fib_spec.rb +15 -0
  99. data/spec/plugins/filter_spec.rb +18 -0
  100. data/spec/plugins/pause_spec.rb +8 -0
  101. data/spec/plugins/primes_spec.rb +15 -0
  102. data/spec/plugins/shell_spec.rb +10 -0
  103. data/spec/plugins/sl_spec.rb +8 -0
  104. data/spec/plugins/spam_spec.rb +4 -0
  105. data/spec/plugins/standard_plugins_spec.rb +23 -0
  106. data/spec/plugins/storage/DB_spec.rb +12 -0
  107. data/spec/plugins/storage/status_spec.rb +24 -0
  108. data/spec/spec_helper.rb +7 -0
  109. data/spec/termtter/client_spec.rb +255 -0
  110. data/spec/termtter/command_spec.rb +107 -0
  111. data/spec/termtter/config_spec.rb +111 -0
  112. data/spec/termtter/hook_spec.rb +78 -0
  113. data/spec/termtter/task_manager_spec.rb +78 -0
  114. data/spec/termtter/task_spec.rb +22 -0
  115. data/spec/termtter_spec.rb +29 -0
  116. data/test/friends_timeline.json +5 -0
  117. data/test/search.json +8 -0
  118. metadata +211 -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,17 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Termtter::Client
4
+ register_command(
5
+ :name => :exec,
6
+ :exec_proc => lambda{|arg|
7
+ return unless arg
8
+ begin
9
+ pause
10
+ system *arg.split(/\s+/)
11
+ ensure
12
+ resume
13
+ end
14
+ },
15
+ :help => ['exec SHELL_COMMAND', 'execute a shell command']
16
+ )
17
+ end
@@ -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,34 @@
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
+ { :host => "ff.im", :pattern => %r'(http://ff\.im(/[\w/]+))'},
8
+ ]
9
+
10
+ module Termtter::Client
11
+ add_filter do |statuses, event|
12
+ statuses.each do |s|
13
+ URL_SHORTTERS.each do |site|
14
+ s.text.gsub!(site[:pattern]) do |m|
15
+ expand_url(site[:host], $2) || $1
16
+ end
17
+ end
18
+ end
19
+ statuses
20
+ end
21
+ end
22
+
23
+ def expand_url(host, path)
24
+ http_class = Net::HTTP
25
+ unless config.proxy.host.nil? or config.proxy.host.empty?
26
+ http_class = Net::HTTP::Proxy(config.proxy.host,
27
+ config.proxy.port,
28
+ config.proxy.user_name,
29
+ config.proxy.password)
30
+ end
31
+ res = http_class.new(host).head(path)
32
+ return nil unless res.code == "301" or res.code == "302"
33
+ res['Location']
34
+ 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']