termtter 1.8.0 → 1.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/plugins/aa.rb +1 -1
- data/lib/plugins/appendtitle.rb +5 -12
- data/lib/plugins/defaults/auto_reload.rb +1 -0
- data/lib/plugins/defaults/cache.rb +18 -0
- data/lib/plugins/defaults/command_line.rb +1 -1
- data/lib/plugins/defaults/fib.rb +15 -6
- data/lib/plugins/defaults/retweet.rb +1 -1
- data/lib/plugins/defaults/standard_commands.rb +31 -25
- data/lib/plugins/defaults/stdout.rb +12 -4
- data/lib/plugins/defaults/system.rb +27 -0
- data/lib/plugins/dupu.rb +13 -0
- data/lib/plugins/erase.rb +4 -0
- data/lib/plugins/error_log.rb +17 -0
- data/lib/plugins/expand-tinyurl.rb +8 -1
- data/lib/plugins/growl.rb +10 -7
- data/lib/plugins/hatena_keyword_haiku.rb +88 -0
- data/lib/plugins/irc_gw.rb +12 -4
- data/lib/plugins/itunes.rb +29 -26
- data/lib/plugins/mecab.rb +23 -0
- data/lib/plugins/mudan_kinshi.rb +13 -0
- data/lib/plugins/ndkn.rb +7 -0
- data/lib/plugins/other_user.rb +47 -0
- data/lib/plugins/reply_sound.rb +75 -25
- data/lib/plugins/ruby-v.rb +10 -0
- data/lib/plugins/time_signal.rb +21 -0
- data/lib/plugins/tinyurl.rb +6 -4
- data/lib/plugins/train.rb +1 -1
- data/lib/plugins/translation.rb +2 -0
- data/lib/plugins/user_stream.rb +122 -0
- data/lib/plugins/whale.rb +28 -0
- data/lib/termtter/active_rubytter.rb +4 -0
- data/lib/termtter/api.rb +55 -30
- data/lib/termtter/client.rb +19 -4
- data/lib/termtter/config_setup.rb +10 -2
- data/lib/termtter/config_template.erb +4 -2
- data/lib/termtter/crypt.rb +13 -0
- data/lib/termtter/default_config.rb +5 -2
- data/lib/termtter/hookable.rb +4 -0
- data/lib/termtter/memory_cache.rb +67 -19
- data/lib/termtter/rubytter_proxy.rb +101 -26
- data/lib/termtter/system_extensions.rb +22 -18
- data/lib/termtter.rb +5 -1
- data/spec/termtter/crypt_spec.rb +16 -0
- data/spec/termtter/rubytter_proxy_spec.rb +14 -0
- 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", ">=
|
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.
|
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
|
-
|
data/lib/plugins/appendtitle.rb
CHANGED
@@ -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{
|
21
|
-
if v =
|
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
|
-
|
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
|
-
|
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
|
@@ -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
|
data/lib/plugins/defaults/fib.rb
CHANGED
@@ -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(:
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
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
|
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
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
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
|
-
|
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 ?
|
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.
|
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 "
|
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.
|
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.
|
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
|
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>=></90>".termcolor + " #{points.ljust(points_max_size)} " +
|
9
|
+
"<90>=></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>=></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
|
data/lib/plugins/dupu.rb
ADDED
@@ -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,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
|
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
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
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
|
+
)
|
data/lib/plugins/irc_gw.rb
CHANGED
@@ -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 => :
|
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
|
|
data/lib/plugins/itunes.rb
CHANGED
@@ -1,33 +1,36 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
|
-
|
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
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
-
|
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
|
+
})
|