emasaka-termtter 1.0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/README.rdoc +100 -0
- data/Rakefile +55 -0
- data/bin/kill_termtter +22 -0
- data/bin/termtter +6 -0
- data/lib/plugins/addspace.rb +27 -0
- data/lib/plugins/april_fool.rb +15 -0
- data/lib/plugins/bomb.rb +39 -0
- data/lib/plugins/clear.rb +14 -0
- data/lib/plugins/command_plus.rb +47 -0
- data/lib/plugins/confirm.rb +12 -0
- data/lib/plugins/cool.rb +10 -0
- data/lib/plugins/countter.rb +23 -0
- data/lib/plugins/devel.rb +18 -0
- data/lib/plugins/direct_messages.rb +36 -0
- data/lib/plugins/en2ja.rb +11 -0
- data/lib/plugins/english.rb +25 -0
- data/lib/plugins/erb.rb +17 -0
- data/lib/plugins/exec_and_update.rb +14 -0
- data/lib/plugins/expand-tinyurl.rb +33 -0
- data/lib/plugins/fib.rb +28 -0
- data/lib/plugins/fib_filter.rb +14 -0
- data/lib/plugins/filter.rb +69 -0
- data/lib/plugins/graduatter.rb +8 -0
- data/lib/plugins/grass.rb +27 -0
- data/lib/plugins/group.rb +64 -0
- data/lib/plugins/growl.rb +52 -0
- data/lib/plugins/growl2.rb +143 -0
- data/lib/plugins/hatebu.rb +59 -0
- data/lib/plugins/history.rb +93 -0
- data/lib/plugins/ignore.rb +19 -0
- data/lib/plugins/keyword.rb +18 -0
- data/lib/plugins/l2.rb +25 -0
- data/lib/plugins/log.rb +73 -0
- data/lib/plugins/me.rb +10 -0
- data/lib/plugins/modify_arg_hook_sample.rb +7 -0
- data/lib/plugins/msagent.rb +38 -0
- data/lib/plugins/multi_reply.rb +27 -0
- data/lib/plugins/notify-send.rb +22 -0
- data/lib/plugins/notify-send2.rb +52 -0
- data/lib/plugins/open_url.rb +59 -0
- data/lib/plugins/otsune.rb +21 -0
- data/lib/plugins/outputz.rb +33 -0
- data/lib/plugins/pause.rb +3 -0
- data/lib/plugins/post_exec_hook_sample.rb +9 -0
- data/lib/plugins/pre_exec_hook_sample.rb +9 -0
- data/lib/plugins/primes.rb +30 -0
- data/lib/plugins/quicklook.rb +41 -0
- data/lib/plugins/random.rb +23 -0
- data/lib/plugins/reblog.rb +40 -0
- data/lib/plugins/reload.rb +3 -0
- data/lib/plugins/reply.rb +8 -0
- data/lib/plugins/retweet.rb +46 -0
- data/lib/plugins/reverse.rb +13 -0
- data/lib/plugins/say.rb +26 -0
- data/lib/plugins/scrape.rb +41 -0
- data/lib/plugins/screen-notify.rb +20 -0
- data/lib/plugins/screen.rb +24 -0
- data/lib/plugins/shell.rb +14 -0
- data/lib/plugins/shorturl_on_update.rb +36 -0
- data/lib/plugins/sl.rb +48 -0
- data/lib/plugins/spam.rb +16 -0
- data/lib/plugins/standard_plugins.rb +519 -0
- data/lib/plugins/stdout.rb +83 -0
- data/lib/plugins/storage.rb +55 -0
- data/lib/plugins/storage/DB.rb +37 -0
- data/lib/plugins/storage/status.rb +83 -0
- data/lib/plugins/storage/status_mook.rb +30 -0
- data/lib/plugins/switch_user.rb +22 -0
- data/lib/plugins/system_status.rb +33 -0
- data/lib/plugins/timer.rb +18 -0
- data/lib/plugins/translation.rb +38 -0
- data/lib/plugins/typable_id.rb +94 -0
- data/lib/plugins/update_editor.rb +53 -0
- data/lib/plugins/update_filter.rb +30 -0
- data/lib/plugins/uri-open.rb +66 -0
- data/lib/plugins/wassr_post.rb +22 -0
- data/lib/plugins/yhara.rb +148 -0
- data/lib/plugins/yhara_filter.rb +8 -0
- data/lib/plugins/yonda.rb +21 -0
- data/lib/termtter.rb +38 -0
- data/lib/termtter/api.rb +57 -0
- data/lib/termtter/client.rb +370 -0
- data/lib/termtter/command.rb +80 -0
- data/lib/termtter/config.rb +68 -0
- data/lib/termtter/config_setup.rb +38 -0
- data/lib/termtter/connection.rb +41 -0
- data/lib/termtter/hook.rb +31 -0
- data/lib/termtter/optparse.rb +14 -0
- data/lib/termtter/system_extensions.rb +161 -0
- data/lib/termtter/task.rb +17 -0
- data/lib/termtter/task_manager.rb +116 -0
- data/lib/termtter/version.rb +4 -0
- data/spec/plugins/cool_spec.rb +10 -0
- data/spec/plugins/english_spec.rb +19 -0
- data/spec/plugins/fib_spec.rb +15 -0
- data/spec/plugins/filter_spec.rb +18 -0
- data/spec/plugins/pause_spec.rb +8 -0
- data/spec/plugins/primes_spec.rb +15 -0
- data/spec/plugins/shell_spec.rb +10 -0
- data/spec/plugins/sl_spec.rb +8 -0
- data/spec/plugins/spam_spec.rb +4 -0
- data/spec/plugins/standard_plugins_spec.rb +23 -0
- data/spec/plugins/storage/DB_spec.rb +12 -0
- data/spec/plugins/storage/status_spec.rb +24 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/termtter/client_spec.rb +255 -0
- data/spec/termtter/command_spec.rb +107 -0
- data/spec/termtter/config_spec.rb +111 -0
- data/spec/termtter/hook_spec.rb +78 -0
- data/spec/termtter/task_manager_spec.rb +78 -0
- data/spec/termtter/task_spec.rb +22 -0
- data/spec/termtter_spec.rb +29 -0
- data/test/friends_timeline.json +5 -0
- data/test/search.json +8 -0
- metadata +210 -0
@@ -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]
|
data/lib/plugins/erb.rb
ADDED
@@ -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
|
data/lib/plugins/fib.rb
ADDED
@@ -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,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']
|