termtter 0.8.3
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 +97 -0
- data/Rakefile +46 -0
- data/bin/kill_termtter +22 -0
- data/bin/termtter +7 -0
- data/lib/filter/en2ja.rb +11 -0
- data/lib/filter/english.rb +8 -0
- data/lib/filter/expand-tinyurl.rb +24 -0
- data/lib/filter/fib.rb +15 -0
- data/lib/filter/ignore.rb +19 -0
- data/lib/filter/reply.rb +8 -0
- data/lib/filter/reverse.rb +13 -0
- data/lib/filter/url_addspace.rb +16 -0
- data/lib/filter/yhara.rb +20 -0
- data/lib/plugin/april_fool.rb +15 -0
- data/lib/plugin/bomb.rb +29 -0
- data/lib/plugin/clear.rb +14 -0
- data/lib/plugin/confirm.rb +9 -0
- data/lib/plugin/cool.rb +10 -0
- data/lib/plugin/devel.rb +13 -0
- data/lib/plugin/english.rb +59 -0
- data/lib/plugin/erb.rb +17 -0
- data/lib/plugin/favorite.rb +75 -0
- data/lib/plugin/fib.rb +8 -0
- data/lib/plugin/filter.rb +69 -0
- data/lib/plugin/follow.rb +56 -0
- data/lib/plugin/graduatter.rb +9 -0
- data/lib/plugin/grass.rb +27 -0
- data/lib/plugin/group.rb +60 -0
- data/lib/plugin/growl.rb +62 -0
- data/lib/plugin/hatebu.rb +59 -0
- data/lib/plugin/history.rb +82 -0
- data/lib/plugin/keyword.rb +18 -0
- data/lib/plugin/log.rb +63 -0
- data/lib/plugin/modify_arg_hook_sample.rb +7 -0
- data/lib/plugin/msagent.rb +26 -0
- data/lib/plugin/multi_reply.rb +36 -0
- data/lib/plugin/notify-send.rb +17 -0
- data/lib/plugin/otsune.rb +21 -0
- data/lib/plugin/outputz.rb +35 -0
- data/lib/plugin/pause.rb +3 -0
- data/lib/plugin/plugin.rb +53 -0
- data/lib/plugin/post_exec_hook_sample.rb +9 -0
- data/lib/plugin/pre_exec_hook_sample.rb +9 -0
- data/lib/plugin/primes.rb +23 -0
- data/lib/plugin/quicklook.rb +38 -0
- data/lib/plugin/reblog.rb +40 -0
- data/lib/plugin/reload.rb +3 -0
- data/lib/plugin/say.rb +24 -0
- data/lib/plugin/scrape.rb +41 -0
- data/lib/plugin/screen.rb +24 -0
- data/lib/plugin/shell.rb +14 -0
- data/lib/plugin/sl.rb +48 -0
- data/lib/plugin/spam.rb +9 -0
- data/lib/plugin/standard_plugins.rb +269 -0
- data/lib/plugin/stdout.rb +62 -0
- data/lib/plugin/system_status.rb +33 -0
- data/lib/plugin/translation.rb +28 -0
- data/lib/plugin/update_editor.rb +53 -0
- data/lib/plugin/uri-open.rb +69 -0
- data/lib/plugin/wassr_post.rb +22 -0
- data/lib/plugin/yhara.rb +148 -0
- data/lib/plugin/yonda.rb +20 -0
- data/lib/termtter/api.rb +14 -0
- data/lib/termtter/client.rb +399 -0
- data/lib/termtter/command.rb +77 -0
- data/lib/termtter/connection.rb +39 -0
- data/lib/termtter/hook.rb +18 -0
- data/lib/termtter/status.rb +26 -0
- data/lib/termtter/task.rb +16 -0
- data/lib/termtter/task_manager.rb +116 -0
- data/lib/termtter/twitter.rb +173 -0
- data/lib/termtter/user.rb +13 -0
- data/lib/termtter/version.rb +3 -0
- data/lib/termtter.rb +157 -0
- data/spec/plugin/cool_spec.rb +10 -0
- data/spec/plugin/fib_spec.rb +16 -0
- data/spec/plugin/filter_spec.rb +18 -0
- data/spec/plugin/plugin_spec.rb +25 -0
- data/spec/plugin/shell_spec.rb +10 -0
- data/spec/plugin/spam_spec.rb +17 -0
- data/spec/plugin/standard_plugins_spec.rb +31 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/termtter/client_spec.rb +175 -0
- data/spec/termtter/command_spec.rb +161 -0
- data/spec/termtter/task_manager_spec.rb +78 -0
- data/spec/termtter/task_spec.rb +22 -0
- data/spec/termtter/user_spec.rb +27 -0
- data/spec/termtter_spec.rb +43 -0
- data/test/friends_timeline.json +5 -0
- data/test/search.json +8 -0
- data/test/test_termtter.rb +86 -0
- metadata +177 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
def primes(n)
|
4
|
+
table = []
|
5
|
+
(2 .. n).each do |i|
|
6
|
+
table << i
|
7
|
+
end
|
8
|
+
|
9
|
+
prime = []
|
10
|
+
loop do
|
11
|
+
prime << table[0]
|
12
|
+
table = table.delete_if {|x| x % prime.max == 0 }
|
13
|
+
break if table.max < (prime.max ** 2)
|
14
|
+
end
|
15
|
+
|
16
|
+
r = (table+prime).sort {|a, b| a<=>b }
|
17
|
+
r.join(', ')
|
18
|
+
end
|
19
|
+
|
20
|
+
module Termtter::Client
|
21
|
+
add_command /^primes\s(\d+)/ do|m,t|t.update_status x="primes(#{n=m[1].to_i}) = {#{primes n}}"
|
22
|
+
puts "=> #{x}" end
|
23
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'uri'
|
4
|
+
require 'open-uri'
|
5
|
+
require 'pathname'
|
6
|
+
require 'tmpdir'
|
7
|
+
|
8
|
+
configatron.plugins.quicklook.set_default(:quicklook_tmpdir, "#{Dir.tmpdir}/termtter-quicklook-tmpdir")
|
9
|
+
tmpdir = Pathname.new(configatron.plugins.quicklook.quicklook_tmpdir)
|
10
|
+
tmpdir.mkdir unless tmpdir.exist?
|
11
|
+
|
12
|
+
def quicklook(url)
|
13
|
+
tmpdir = Pathname.new(configatron.plugins.quicklook.quicklook_tmpdir)
|
14
|
+
path = tmpdir + Pathname.new(url).basename
|
15
|
+
|
16
|
+
Thread.new do
|
17
|
+
open(path, 'w') do |f|
|
18
|
+
f.write(open(url).read)
|
19
|
+
end
|
20
|
+
system("qlmanage -p #{path} > /dev/null 2>&1")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
module Termtter::Client
|
25
|
+
add_command %r'^(?:quicklook|ql)\s+(\w+)$' do |m,t|
|
26
|
+
id = m[1]
|
27
|
+
status = t.show(id).first
|
28
|
+
|
29
|
+
if (status)
|
30
|
+
uris = URI.regexp.match(status.text).to_a
|
31
|
+
quicklook(uris.first) unless uris.empty?
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# quicklook.rb
|
37
|
+
# TODO:
|
38
|
+
# Close quicklook window automatically.
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'tumblr'
|
5
|
+
|
6
|
+
module Termtter::Client
|
7
|
+
register_command(
|
8
|
+
:name => :reblog, :aliases => [],
|
9
|
+
:exec_proc => lambda {|arg|
|
10
|
+
if arg =~ /^reblog\s+(\d+)(.*)$/
|
11
|
+
id = $1.strip
|
12
|
+
comment = $2.strip
|
13
|
+
statuses = public_storage[:log].select { |s| s.id == id }
|
14
|
+
unless statuses.empty?
|
15
|
+
status = statuses.first
|
16
|
+
else
|
17
|
+
status = t.show(id).first
|
18
|
+
end
|
19
|
+
|
20
|
+
Tumblr::API.write(configatron.plugins.reblog.email, configatron.plugins.reblog.password) do
|
21
|
+
quote("#{status.text}", "<a href=\"http://twitter.com/#{status.user_screen_name}/status/#{status.id}\">Twitter / #{status.user_name}</a>")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
},
|
25
|
+
:completion_proc => lambda {|cmd, args|
|
26
|
+
if args =~ /^(\d*)$/
|
27
|
+
find_status_id_candidates $1, "#{cmd} %s"
|
28
|
+
end
|
29
|
+
},
|
30
|
+
:help => ['reblog ID', 'Tumblr Reblog a status']
|
31
|
+
)
|
32
|
+
end
|
33
|
+
|
34
|
+
# reblog.rb
|
35
|
+
# tumblr reblog it!
|
36
|
+
#
|
37
|
+
# configatron.plugins.reblog.email = 'your-email-on-tumblr'
|
38
|
+
# configatron.plugins.reblog.password = 'your-password-on-tumblr'
|
39
|
+
#
|
40
|
+
# reblog 1114860346
|
data/lib/plugin/say.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
raise 'say.rb runs only in OSX Leopard' if /darwin9/ !~ RUBY_PLATFORM
|
4
|
+
|
5
|
+
# say :: String -> String -> IO ()
|
6
|
+
def say(who, what)
|
7
|
+
voices = %w(Alex Alex Bruce Fred Ralph Agnes Kathy Vicki)
|
8
|
+
voice = voices[who.hash % voices.size]
|
9
|
+
system 'say', '-v', voice, what
|
10
|
+
end
|
11
|
+
|
12
|
+
module Termtter::Client
|
13
|
+
add_hook do |statuses, event, t|
|
14
|
+
if !statuses.empty? && event == :update_friends_timeline
|
15
|
+
statuses.reverse.each do |s|
|
16
|
+
text_without_uri = s.text.gsub(%r|https?://[^\s]+|, 'U.R.I.')
|
17
|
+
say s.user_screen_name, text_without_uri
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# KNOWN BUG:
|
24
|
+
# * exit or <C-c> doen't work quickly.
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Termtter::Client
|
4
|
+
|
5
|
+
def self.scrape_members(members)
|
6
|
+
statuses = []
|
7
|
+
members.each_with_index do |member, index|
|
8
|
+
puts "member #{index+1}/#{members.size} #{member}"
|
9
|
+
statuses += Termtter::API.twitter.get_user_timeline(member)
|
10
|
+
end
|
11
|
+
statuses
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.scrape_group(group)
|
15
|
+
members = configatron.plugins.group.groups[group] || []
|
16
|
+
scrape_members(members)
|
17
|
+
end
|
18
|
+
|
19
|
+
register_command(
|
20
|
+
:name => :scrape_group,
|
21
|
+
:exec_proc => lambda{ |args|
|
22
|
+
groups = args.split(' ').map{|g| g.to_sym}
|
23
|
+
if groups.include? :all
|
24
|
+
groups = configatron.plugins.group.groups.keys
|
25
|
+
puts "get all groups..."
|
26
|
+
end
|
27
|
+
members = []
|
28
|
+
groups.each do |group|
|
29
|
+
members += configatron.plugins.group.groups[group]
|
30
|
+
end
|
31
|
+
statuses = scrape_members(members.uniq.compact.sort)
|
32
|
+
call_hooks(statuses, :pre_filter)
|
33
|
+
},
|
34
|
+
:completion_proc => lambda {|cmd, args|
|
35
|
+
arg = args.split(' ').last
|
36
|
+
prefix = args.split(' ')[0..-2].join(' ')
|
37
|
+
find_group_candidates arg, "#{cmd} #{prefix} %s"
|
38
|
+
},
|
39
|
+
:help => ['scrape_group GROUPNAME(S)', 'Get the group timeline']
|
40
|
+
)
|
41
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Termtter
|
4
|
+
module Plugin
|
5
|
+
module Screen
|
6
|
+
def self.set_title(title)
|
7
|
+
print "\033k#{title}\033\\"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# Add below to your ~/.termtter
|
14
|
+
#
|
15
|
+
# require 'plugin/yonda'
|
16
|
+
# require 'plugin/screen'
|
17
|
+
# module Termtter::Client
|
18
|
+
# add_hook do |statuses, event|
|
19
|
+
# case event
|
20
|
+
# when :update_friends_timeline, :plugin_yonda_yonda
|
21
|
+
# Termtter::Plugin::Screen::set_title("termtter(#{public_storage[:unread_count]})")
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
# end
|
data/lib/plugin/shell.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Termtter::Client
|
4
|
+
register_command :name => :shell, :aliases => [:sh],
|
5
|
+
:help => ['shell,sh', 'Start your shell'],
|
6
|
+
:exec_proc => lambda {|args|
|
7
|
+
begin
|
8
|
+
pause
|
9
|
+
system ENV['SHELL'] || ENV['COMSPEC']
|
10
|
+
ensure
|
11
|
+
resume
|
12
|
+
end
|
13
|
+
}
|
14
|
+
end
|
data/lib/plugin/sl.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Termtter
|
4
|
+
|
5
|
+
module Client
|
6
|
+
|
7
|
+
public_storage[:current] = ''
|
8
|
+
public_storage[:orig_prompt] = configatron.prompt
|
9
|
+
configatron.prompt = "~/ #{public_storage[:orig_prompt]}"
|
10
|
+
|
11
|
+
register_command(
|
12
|
+
:name => :sl, :aliases => [],
|
13
|
+
:exec_proc => lambda {|arg| system("sl") },
|
14
|
+
:help => ['sl', 'The train pass in front of your screen']
|
15
|
+
)
|
16
|
+
|
17
|
+
register_command(
|
18
|
+
:name => :pwd, :aliases => [],
|
19
|
+
:exec_proc => lambda {|arg| public_storage[:current] },
|
20
|
+
:help => ['pwd', 'Show current direcroty']
|
21
|
+
)
|
22
|
+
|
23
|
+
register_command(
|
24
|
+
:name => :ls, :aliases => [],
|
25
|
+
:exec_proc => lambda {|arg|
|
26
|
+
call_commands("list #{arg.empty? ? public_storage[:current] : arg}", API.twitter)
|
27
|
+
},
|
28
|
+
:completion_proc => lambda {|cmd, args|
|
29
|
+
find_user_candidates args, "#{cmd} %s"
|
30
|
+
},
|
31
|
+
:help => ['ls', 'Show list in current directory']
|
32
|
+
)
|
33
|
+
|
34
|
+
register_command(
|
35
|
+
:name => :cd, :aliases => [],
|
36
|
+
:exec_proc => lambda {|arg|
|
37
|
+
public_storage[:current] =
|
38
|
+
(arg.nil? || /\~/ =~ arg) ? '' : arg
|
39
|
+
configatron.prompt = "~/#{public_storage[:current]} #{public_storage[:orig_prompt]}"
|
40
|
+
},
|
41
|
+
:completion_proc => lambda {|cmd, args|
|
42
|
+
find_user_candidates args, "#{cmd} %s"
|
43
|
+
},
|
44
|
+
:help => ['cd USER', 'Change current directory']
|
45
|
+
)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
data/lib/plugin/spam.rb
ADDED
@@ -0,0 +1,269 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
module Termtter::Client
|
6
|
+
|
7
|
+
# standard commands
|
8
|
+
|
9
|
+
register_command(
|
10
|
+
:name => :update, :aliases => [:u],
|
11
|
+
:exec_proc => lambda {|arg|
|
12
|
+
text = ERB.new(arg).result(binding).gsub(/\n/, ' ')
|
13
|
+
Termtter::API.twitter.update_status(text)
|
14
|
+
puts "=> #{text}"
|
15
|
+
},
|
16
|
+
:completion_proc => lambda {|cmd, args|
|
17
|
+
if /(.*)@([^\s]*)$/ =~ args
|
18
|
+
find_user_candidates $2, "#{cmd} #{$1}@%s"
|
19
|
+
end
|
20
|
+
}
|
21
|
+
)
|
22
|
+
|
23
|
+
register_command(
|
24
|
+
:name => :direct, :aliases => [:d],
|
25
|
+
:exec_proc => lambda {|arg|
|
26
|
+
if arg =~ /^([^\s]+)\s+(.*)\s*$/
|
27
|
+
user, text = $1, $2
|
28
|
+
Termtter::API.twitter.direct_message(user, text)
|
29
|
+
puts "=> to:#{user} message:#{text}"
|
30
|
+
end
|
31
|
+
},
|
32
|
+
:completion_proc => lambda {|cmd, args|
|
33
|
+
if args =~ /^([^\s]+)$/
|
34
|
+
find_user_candidates $1, "#{cmd} %s"
|
35
|
+
end
|
36
|
+
}
|
37
|
+
)
|
38
|
+
|
39
|
+
register_command(
|
40
|
+
:name => :profile, :aliases => [:p],
|
41
|
+
:exec_proc => lambda {|arg|
|
42
|
+
user = Termtter::API.twitter.get_user_profile(arg)
|
43
|
+
attrs = %w[ name screen_name url description profile_image_url location protected following
|
44
|
+
friends_count followers_count statuses_count favourites_count
|
45
|
+
id time_zone created_at utc_offset notifications
|
46
|
+
]
|
47
|
+
label_width = attrs.map{|i|i.size}.max
|
48
|
+
attrs.each do |attr|
|
49
|
+
value = user.__send__(attr.to_sym)
|
50
|
+
puts "#{attr.gsub('_', ' ').rjust(label_width)}: #{value}"
|
51
|
+
end
|
52
|
+
},
|
53
|
+
:completion_proc => lambda {|cmd, arg|
|
54
|
+
find_user_candidates arg, "#{cmd} %s"
|
55
|
+
}
|
56
|
+
)
|
57
|
+
|
58
|
+
register_command(
|
59
|
+
:name => :followers,
|
60
|
+
:exec_proc => lambda {|arg|
|
61
|
+
followers = Termtter::API.twitter.followers
|
62
|
+
Termtter::Client.public_storage[:followers] = followers
|
63
|
+
p followers.map{|f|f.screen_name}
|
64
|
+
}
|
65
|
+
)
|
66
|
+
|
67
|
+
register_command(
|
68
|
+
:name => :list, :aliases => [:l],
|
69
|
+
:exec_proc => lambda {|arg|
|
70
|
+
unless arg.empty?
|
71
|
+
call_hooks(Termtter::API.twitter.get_user_timeline(arg), :list_user_timeline)
|
72
|
+
else
|
73
|
+
call_hooks(Termtter::API.twitter.get_friends_timeline(), :list_friends_timeline)
|
74
|
+
end
|
75
|
+
},
|
76
|
+
:completion_proc => lambda {|cmd, arg|
|
77
|
+
find_user_candidates arg, "#{cmd} %s"
|
78
|
+
}
|
79
|
+
)
|
80
|
+
|
81
|
+
register_command(
|
82
|
+
:name => :search, :aliases => [:s],
|
83
|
+
:exec_proc => lambda {|arg|
|
84
|
+
call_hooks(Termtter::API.twitter.search(arg), :search)
|
85
|
+
}
|
86
|
+
)
|
87
|
+
|
88
|
+
register_command(
|
89
|
+
:name => :replies, :aliases => [:r],
|
90
|
+
:exec_proc => lambda {|arg|
|
91
|
+
call_hooks(Termtter::API.twitter.replies(), :replies)
|
92
|
+
}
|
93
|
+
)
|
94
|
+
|
95
|
+
register_command(
|
96
|
+
:name => :show,
|
97
|
+
:exec_proc => lambda {|arg|
|
98
|
+
id = arg.gsub(/.*:/, '')
|
99
|
+
call_hooks(Termtter::API.twitter.show(id), :show)
|
100
|
+
}
|
101
|
+
)
|
102
|
+
|
103
|
+
register_command(
|
104
|
+
:name => :shows,
|
105
|
+
:exec_proc => lambda {|arg|
|
106
|
+
id = arg.gsub(/.*:/, '')
|
107
|
+
call_hooks(Termtter::API.twitter.show(id, true), :show)
|
108
|
+
}
|
109
|
+
)
|
110
|
+
|
111
|
+
# TODO: Change colors when remaining_hits is low.
|
112
|
+
# TODO: Simmulate remaining_hits.
|
113
|
+
register_command(
|
114
|
+
:name => :limit, :aliases => [:lm],
|
115
|
+
:exec_proc => lambda {|arg|
|
116
|
+
limit = Termtter::API.twitter.get_rate_limit_status
|
117
|
+
remaining_time = "%dmin %dsec" % (limit.reset_time - Time.now).divmod(60)
|
118
|
+
remaining_color =
|
119
|
+
case limit.remaining_hits / limit.hourly_limit.to_f
|
120
|
+
when 0.2..0.4 then :yellow
|
121
|
+
when 0..0.2 then :red
|
122
|
+
else :green
|
123
|
+
end
|
124
|
+
puts "=> #{color(limit.remaining_hits, remaining_color)}/#{limit.hourly_limit} until #{limit.reset_time} (#{remaining_time} remaining)"
|
125
|
+
},
|
126
|
+
:help => ["limit,lm", "Show the API limit status"]
|
127
|
+
)
|
128
|
+
|
129
|
+
register_command(
|
130
|
+
:name => :pause,
|
131
|
+
:exec_proc => lambda {|arg| pause},
|
132
|
+
:help => ["pause", "Pause updating"]
|
133
|
+
)
|
134
|
+
|
135
|
+
register_command(
|
136
|
+
:name => :resume,
|
137
|
+
:exec_proc => lambda {|arg| resume},
|
138
|
+
:help => ["resume", "Resume updating"]
|
139
|
+
)
|
140
|
+
|
141
|
+
register_command(
|
142
|
+
:name => :exit, :aliases => [:e],
|
143
|
+
:exec_proc => lambda {|arg| exit},
|
144
|
+
:help => ['exit,e', 'Exit']
|
145
|
+
)
|
146
|
+
|
147
|
+
register_hook(
|
148
|
+
:name => :default_error_handler,
|
149
|
+
:points => [:on_error],
|
150
|
+
:exec_proc => lambda {|e|
|
151
|
+
puts "Error: #{e}"
|
152
|
+
if configatron.devel == true
|
153
|
+
puts e.backtrace.join("\n")
|
154
|
+
end
|
155
|
+
}
|
156
|
+
)
|
157
|
+
|
158
|
+
register_command(
|
159
|
+
:name => :help, :aliases => [:h],
|
160
|
+
:exec_proc => lambda {|arg|
|
161
|
+
helps = [
|
162
|
+
["help,h", "Print this help message"],
|
163
|
+
["list,l", "List the posts in your friends timeline"],
|
164
|
+
["list,l USERNAME", "List the posts in the the given user's timeline"],
|
165
|
+
["update,u TEXT", "Post a new message"],
|
166
|
+
["direct,d @USERNAME TEXT", "Send direct message"],
|
167
|
+
["profile,p USERNAME", "Show user's profile"],
|
168
|
+
["replies,r", "List the most recent @replies for the authenticating user"],
|
169
|
+
["search,s TEXT", "Search for Twitter"],
|
170
|
+
["show ID", "Show a single status"]
|
171
|
+
]
|
172
|
+
helps += @@helps
|
173
|
+
helps += @@new_commands.map {|name, command| command.help}
|
174
|
+
helps.compact!
|
175
|
+
puts formatted_help(helps)
|
176
|
+
}
|
177
|
+
)
|
178
|
+
|
179
|
+
register_command(
|
180
|
+
:name => :execute,
|
181
|
+
:exec_proc => lambda{|arg|
|
182
|
+
if arg
|
183
|
+
`#{arg}`.each_line do |line|
|
184
|
+
unless line.strip.empty?
|
185
|
+
Termtter::API.twitter.update_status(line)
|
186
|
+
puts "=> #{line}"
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
},
|
191
|
+
:help => ['execute COMMAND', 'execute the command']
|
192
|
+
)
|
193
|
+
|
194
|
+
add_command /^!(!)?\s*(.*)$/ do |m, t|
|
195
|
+
warn '!COMMAND command will be removed. Use command execute instead.'
|
196
|
+
begin
|
197
|
+
result = `#{m[2]}` unless m[2].empty?
|
198
|
+
unless m[1].nil? || result.empty?
|
199
|
+
t.update_status(result.gsub("\n", " "))
|
200
|
+
end
|
201
|
+
puts "=> #{result}"
|
202
|
+
rescue => e
|
203
|
+
puts e
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def self.formatted_help(helps)
|
208
|
+
helps = helps.sort_by{|help| help[0]}
|
209
|
+
width = helps.map {|n, d| n.size }.max
|
210
|
+
space = 3
|
211
|
+
helps.map {|name, desc|
|
212
|
+
name.to_s.ljust(width + space) + desc.to_s
|
213
|
+
}.join("\n")
|
214
|
+
end
|
215
|
+
|
216
|
+
# completion for standard commands
|
217
|
+
|
218
|
+
require 'set'
|
219
|
+
public_storage[:users] ||= Set.new
|
220
|
+
public_storage[:status_ids] ||= Set.new
|
221
|
+
|
222
|
+
add_hook do |statuses, event, t|
|
223
|
+
statuses.each do |s|
|
224
|
+
public_storage[:users].add(s.user_screen_name)
|
225
|
+
public_storage[:users] += s.text.scan(/@([a-zA-Z_0-9]*)/).flatten
|
226
|
+
public_storage[:status_ids].add(s.id.to_s)
|
227
|
+
public_storage[:status_ids].add(s.in_reply_to_status_id.to_s) if s.in_reply_to_status_id
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def self.find_status_id_candidates(a, b, u = nil)
|
232
|
+
candidates = public_storage[:status_ids].to_a
|
233
|
+
if u && c = public_storage[:log].select {|s| s.user_screen_name == u }.map {|s| s.id.to_s }
|
234
|
+
candidates = c unless c.empty?
|
235
|
+
end
|
236
|
+
if a.empty?
|
237
|
+
candidates
|
238
|
+
else
|
239
|
+
candidates.grep(/#{Regexp.quote a}/)
|
240
|
+
end.
|
241
|
+
map {|u| b % u }
|
242
|
+
end
|
243
|
+
|
244
|
+
def self.find_user_candidates(a, b)
|
245
|
+
if a.nil? || a.empty?
|
246
|
+
public_storage[:users].to_a
|
247
|
+
else
|
248
|
+
public_storage[:users].grep(/^#{Regexp.quote a}/i)
|
249
|
+
end.
|
250
|
+
map {|u| b % u }
|
251
|
+
end
|
252
|
+
|
253
|
+
add_completion do |input|
|
254
|
+
standard_commands = %w[exit help list pause profile update direct resume replies search show limit]
|
255
|
+
case input
|
256
|
+
when /^show(s)?\s+(([\w\d]+):)?\s*(.*)/
|
257
|
+
if $2
|
258
|
+
find_status_id_candidates $4, "show#{$1} #{$2}%s", $3
|
259
|
+
else
|
260
|
+
result = find_user_candidates $4, "show#{$1} %s:"
|
261
|
+
result = find_status_id_candidates $4, "show#{$1} %s" if result.empty?
|
262
|
+
result
|
263
|
+
end
|
264
|
+
else
|
265
|
+
standard_commands.grep(/^#{Regexp.quote input}/)
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'highline'
|
4
|
+
require 'erb'
|
5
|
+
|
6
|
+
configatron.plugins.stdout.set_default(
|
7
|
+
:colors,
|
8
|
+
[:none, :red, :green, :yellow, :blue, :magenta, :cyan])
|
9
|
+
configatron.plugins.stdout.set_default(
|
10
|
+
:timeline_format,
|
11
|
+
'<%= color(time, 90) %> <%= color(status, status_color) %> <%= color(id, 90) %>')
|
12
|
+
|
13
|
+
$highline = HighLine.new
|
14
|
+
|
15
|
+
def color(str, value)
|
16
|
+
return str if value == :none
|
17
|
+
case value
|
18
|
+
when String, Symbol
|
19
|
+
$highline.color(str, value)
|
20
|
+
else
|
21
|
+
"\e[#{value}m#{str}\e[0m"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
module Termtter::Client
|
26
|
+
|
27
|
+
def self.print_statuses(statuses, sort = true, time_format = '%H:%M:%S')
|
28
|
+
(sort ? statuses.sort_by{ |s| s.id} : statuses).each do |s|
|
29
|
+
text = s.text
|
30
|
+
status_color = configatron.plugins.stdout.colors[s.user_screen_name.hash % configatron.plugins.stdout.colors.size]
|
31
|
+
status = "#{s.user_screen_name}: #{text}"
|
32
|
+
if s.in_reply_to_status_id
|
33
|
+
status += " (reply to #{s.in_reply_to_status_id})"
|
34
|
+
end
|
35
|
+
|
36
|
+
time = "(#{s.created_at.strftime(time_format)})"
|
37
|
+
id = s.id
|
38
|
+
puts ERB.new(configatron.plugins.stdout.timeline_format).result(binding)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.print_statuses_with_date(statuses, sort = true)
|
43
|
+
print_statuses(statuses, sort, '%m-%d %H:%M')
|
44
|
+
end
|
45
|
+
|
46
|
+
add_hook do |statuses, event|
|
47
|
+
next if statuses.empty?
|
48
|
+
|
49
|
+
case event
|
50
|
+
when :update_friends_timeline, :list_friends_timeline
|
51
|
+
print_statuses(statuses)
|
52
|
+
when :search, :list_user_timeline, :show, :replies
|
53
|
+
print_statuses_with_date(statuses)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
# stdout.rb
|
59
|
+
# output statuses to stdout
|
60
|
+
# example config
|
61
|
+
# configatron.plugins.stdout.colors = [:none, :red, :green, :yellow, :blue, :magenta, :cyan]
|
62
|
+
# configatron.plugins.stdout.timeline_format = '<%= color(time, 90) %> <%= color(status, status_color) %> <%= color(id, 90) %>'
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
configatron.plugins.system_status.set_default(:default_status_proc, lambda { Time.now.strftime("%x %X") })
|
6
|
+
configatron.plugins.system_status.set_default(:interval, 1)
|
7
|
+
configatron.plugins.system_status.set_default(:default_color, :on_blue)
|
8
|
+
configatron.plugins.system_status.set_default(:format, '<%= status %>')
|
9
|
+
|
10
|
+
def out_put_status(status, color)
|
11
|
+
formatted_status = ERB.new(configatron.plugins.system_status.format).result(binding)
|
12
|
+
colored_status = color(formatted_status, color)
|
13
|
+
print "\e[s\e[1000G\e[#{status.size - 1}D#{colored_status}\e[u"
|
14
|
+
$stdout.flush
|
15
|
+
end
|
16
|
+
|
17
|
+
module Termtter::Client
|
18
|
+
add_task(:name => :system_status, :interval => configatron.plugins.system_status.interval) do
|
19
|
+
status = (@@task_manager.get_task(:update_timeline).exec_at - Time.now).to_i.to_s
|
20
|
+
color = public_storage[:system_status_color] ||
|
21
|
+
configatron.plugins.system_status.default_color
|
22
|
+
out_put_status(status, color)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# system_status.rb
|
27
|
+
# show system status on left side.
|
28
|
+
# output public_storage[:system_status] or Time.now.strftime("%x %X") if nil
|
29
|
+
# example config
|
30
|
+
# configatron.plugins.system_status.default_status_proc = lambda { Time.now.strftime("%x %X") }
|
31
|
+
# configatron.plugins.system_status.interval = 1
|
32
|
+
# configatron.plugins.system_status.default_color = :on_blue
|
33
|
+
# configatron.plugins.system_status.format = '<%= status %>'
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'net/http'
|
5
|
+
require 'kconv'
|
6
|
+
require 'uri'
|
7
|
+
|
8
|
+
def translate(text, langpair)
|
9
|
+
req = Net::HTTP::Post.new('/translate_t')
|
10
|
+
req.add_field('Content-Type', 'application/x-www-form-urlencoded')
|
11
|
+
req.add_field('User-Agent', 'Mozilla/5.0')
|
12
|
+
Net::HTTP.version_1_2 # Proxy に対応してない
|
13
|
+
Net::HTTP.start('translate.google.co.jp', 80) {|http|
|
14
|
+
response = http.request(req, "langpair=#{langpair}&text=#{URI.escape(text)}")
|
15
|
+
doc = Nokogiri::HTML.parse(response.body, nil, 'utf-8')
|
16
|
+
return doc.css('#result_box').text
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
Termtter::Client.add_command /^(en2ja|ja2en)\s+(.*)$/ do |m, t|
|
21
|
+
langpair = m[1].gsub('2', '|')
|
22
|
+
puts "translating..."
|
23
|
+
puts "=> #{translate(m[2], langpair)}"
|
24
|
+
end
|
25
|
+
|
26
|
+
# This plugin does not work yet.
|
27
|
+
# requirements
|
28
|
+
# nokogiri (sudo gem install nokogiri)
|