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.
- 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 +33 -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.rb +17 -0
- data/lib/plugins/exec_and_update.rb +14 -0
- data/lib/plugins/expand-tinyurl.rb +34 -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/hatebu_and_update.rb +58 -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/notify-send3.rb +45 -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/sl.rb +48 -0
- data/lib/plugins/spam.rb +16 -0
- data/lib/plugins/standard_plugins.rb +525 -0
- data/lib/plugins/stdout.rb +220 -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/tinyurl.rb +20 -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/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 +324 -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 +115 -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 +211 -0
data/lib/plugins/say.rb
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
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
|
+
register_hook(
|
|
14
|
+
:name => :say,
|
|
15
|
+
:points => [:output],
|
|
16
|
+
:exec_proc => lambda {|statuses, event|
|
|
17
|
+
statuses.reverse.each do |s|
|
|
18
|
+
text_without_uri = s[:text].gsub(%r|https?://[^\s]+|, 'U.R.I.')
|
|
19
|
+
say s[:screen_name], text_without_uri
|
|
20
|
+
end
|
|
21
|
+
}
|
|
22
|
+
)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# KNOWN BUG:
|
|
26
|
+
# * 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.user_timeline(member)
|
|
10
|
+
end
|
|
11
|
+
statuses
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.scrape_group(group)
|
|
15
|
+
members = config.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 = config.plugins.group.groups.keys
|
|
25
|
+
puts "get all groups..."
|
|
26
|
+
end
|
|
27
|
+
members = []
|
|
28
|
+
groups.each do |group|
|
|
29
|
+
members += config.plugins.group.groups[group]
|
|
30
|
+
end
|
|
31
|
+
statuses = scrape_members(members.uniq.compact.sort)
|
|
32
|
+
output(statuses_to_hash(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,20 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
config.screen_notify.set_default(:format, "[termtter] %s")
|
|
4
|
+
|
|
5
|
+
module Termtter::Client
|
|
6
|
+
register_hook(
|
|
7
|
+
:name => :screen_notify,
|
|
8
|
+
:points => [:output],
|
|
9
|
+
:exec_proc => lambda{|statuses, event|
|
|
10
|
+
return unless event = :update_friends_timeline
|
|
11
|
+
Thread.new(statuses) do |ss|
|
|
12
|
+
ss.each do |s|
|
|
13
|
+
msg = config.screen_notify.format % s.user.screen_name
|
|
14
|
+
system 'screen', '-X', 'eval', "bell_msg '#{msg}'", 'bell'
|
|
15
|
+
sleep 1
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
}
|
|
19
|
+
)
|
|
20
|
+
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\\\n"
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Add below to your ~/.termtter
|
|
14
|
+
#
|
|
15
|
+
# require 'plugins/yonda'
|
|
16
|
+
# require 'plugins/screen'
|
|
17
|
+
# module Termtter::Client
|
|
18
|
+
# register_hook(:name => :screen,
|
|
19
|
+
# :points => [:post_exec__update_timeline, :plugin_yonda_yonda, :post_exec_yonda],
|
|
20
|
+
# :exec_proc => lambda { |cmd, arg, result|
|
|
21
|
+
# Termtter::Plugin::Screen::set_title("termtter(#{public_storage[:unread_count]})")
|
|
22
|
+
# }
|
|
23
|
+
# )
|
|
24
|
+
# end
|
|
@@ -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/plugins/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] = config.prompt
|
|
9
|
+
config.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}")
|
|
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
|
+
config.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/plugins/spam.rb
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
message = '*super spam time*'
|
|
4
|
+
Termtter::API.twitter.update(message)
|
|
5
|
+
puts "=> #{message}"
|
|
6
|
+
|
|
7
|
+
Termtter::Client.register_hook(
|
|
8
|
+
:name => :span,
|
|
9
|
+
:point => /^pre_exec/,
|
|
10
|
+
:exec => lambda{|*arg|
|
|
11
|
+
text = arg.join(' ')
|
|
12
|
+
Termtter::API.twitter.update(text)
|
|
13
|
+
puts "=> #{text}"
|
|
14
|
+
raise Termtter::CommandCanceled
|
|
15
|
+
}
|
|
16
|
+
)
|
|
@@ -0,0 +1,525 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require 'erb'
|
|
4
|
+
require 'set'
|
|
5
|
+
|
|
6
|
+
config.plugins.standard.set_default(
|
|
7
|
+
:limit_format,
|
|
8
|
+
'<<%=remaining_color%>><%=limit.remaining_hits%></<%=remaining_color%>>/<%=limit.hourly_limit%> until <%=limit.reset_time%> (<%=remaining_time%> remaining)')
|
|
9
|
+
|
|
10
|
+
module Termtter::Client
|
|
11
|
+
|
|
12
|
+
register_command(
|
|
13
|
+
:name => :update, :aliases => [:u],
|
|
14
|
+
:exec_proc => lambda {|arg|
|
|
15
|
+
unless arg.empty?
|
|
16
|
+
Termtter::API.twitter.update(arg)
|
|
17
|
+
puts "=> #{arg}"
|
|
18
|
+
end
|
|
19
|
+
},
|
|
20
|
+
:completion_proc => lambda {|cmd, args|
|
|
21
|
+
if /(.*)@([^\s]*)$/ =~ args
|
|
22
|
+
find_user_candidates $2, "#{cmd} #{$1}@%s"
|
|
23
|
+
end
|
|
24
|
+
},
|
|
25
|
+
:help => ["update,u TEXT", "Post a new message"]
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
direct_message_struct = Struct.new(:id, :text, :user, :created_at)
|
|
29
|
+
direct_message_struct.class_eval do
|
|
30
|
+
def method_missing(*args, &block)
|
|
31
|
+
nil
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
register_command(
|
|
35
|
+
:name => :direct, :aliases => [:d],
|
|
36
|
+
:exec_proc => lambda {|arg|
|
|
37
|
+
case arg
|
|
38
|
+
when /^([^\s]+)\s+(.*)\s*$/
|
|
39
|
+
user, text = $1, $2
|
|
40
|
+
Termtter::API.twitter.direct_message(user, text)
|
|
41
|
+
puts "=> to:#{user} message:#{text}"
|
|
42
|
+
when 'list'
|
|
43
|
+
output(
|
|
44
|
+
Termtter::API.twitter.direct_messages.map { |d|
|
|
45
|
+
direct_message_struct.new(d.id, "#{d.text} => #{d.recipient_screen_name}", d.sender, d.created_at)
|
|
46
|
+
},
|
|
47
|
+
:direct_messages
|
|
48
|
+
)
|
|
49
|
+
when 'sent_list'
|
|
50
|
+
output(
|
|
51
|
+
Termtter::API.twitter.sent_direct_messages.map { |d|
|
|
52
|
+
direct_message_struct.new(d.id, "#{d.text} => #{d.recipient_screen_name}", d.sender, d.created_at)
|
|
53
|
+
},
|
|
54
|
+
:direct_messages
|
|
55
|
+
)
|
|
56
|
+
end
|
|
57
|
+
},
|
|
58
|
+
:completion_proc => lambda {|cmd, arg|
|
|
59
|
+
find_user_candidates(arg, "#{cmd} %s") +
|
|
60
|
+
["list", "sent_list"].grep(/^#{Regexp.quote(arg)}/).map { |i| "#{cmd} #{i}" }
|
|
61
|
+
},
|
|
62
|
+
:help => [
|
|
63
|
+
["direct,d USERNAME TEXT", "Send direct message"],
|
|
64
|
+
["direct,d list", 'List direct messages'],
|
|
65
|
+
["direct,d sent_list", 'List sent direct messages']
|
|
66
|
+
]
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
register_command(
|
|
70
|
+
:name => :profile, :aliases => [:p],
|
|
71
|
+
:exec_proc => lambda {|arg|
|
|
72
|
+
user = Termtter::API.twitter.user(arg.strip)
|
|
73
|
+
attrs = %w[ name screen_name url description profile_image_url location protected following
|
|
74
|
+
friends_count followers_count statuses_count favourites_count
|
|
75
|
+
id time_zone created_at utc_offset notifications
|
|
76
|
+
]
|
|
77
|
+
label_width = attrs.map(&:size).max
|
|
78
|
+
attrs.each do |attr|
|
|
79
|
+
value = user.__send__(attr.to_sym)
|
|
80
|
+
puts "#{attr.gsub('_', ' ').rjust(label_width)}: #{value}"
|
|
81
|
+
end
|
|
82
|
+
},
|
|
83
|
+
:completion_proc => lambda {|cmd, arg|
|
|
84
|
+
find_user_candidates arg, "#{cmd} %s"
|
|
85
|
+
},
|
|
86
|
+
:help => ["profile,p USERNAME", "Show user's profile"]
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
register_command(
|
|
90
|
+
:name => :followers,
|
|
91
|
+
:exec_proc => lambda {|arg|
|
|
92
|
+
user_name = arg.strip
|
|
93
|
+
user_name = config.user_name if user_name.empty?
|
|
94
|
+
|
|
95
|
+
followers = []
|
|
96
|
+
page = 0
|
|
97
|
+
begin
|
|
98
|
+
followers += tmp = Termtter::API.twitter.followers(user_name, :page => page+=1)
|
|
99
|
+
end until tmp.empty?
|
|
100
|
+
Termtter::Client.public_storage[:followers] = followers
|
|
101
|
+
public_storage[:users] += followers.map(&:screen_name)
|
|
102
|
+
puts followers.map(&:screen_name).join(' ')
|
|
103
|
+
},
|
|
104
|
+
:completion_proc => lambda {|cmd, arg|
|
|
105
|
+
find_user_candidates arg, "#{cmd} %s"
|
|
106
|
+
},
|
|
107
|
+
:help => ["followers", "Show followers"]
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
register_command(
|
|
111
|
+
:name => :list, :aliases => [:l],
|
|
112
|
+
:exec_proc => lambda {|arg|
|
|
113
|
+
if arg.empty?
|
|
114
|
+
event = :list_friends_timeline
|
|
115
|
+
statuses = Termtter::API.twitter.friends_timeline
|
|
116
|
+
else
|
|
117
|
+
event = :list_user_timeline
|
|
118
|
+
statuses = Termtter::API.twitter.user_timeline(arg)
|
|
119
|
+
end
|
|
120
|
+
output(statuses, event)
|
|
121
|
+
},
|
|
122
|
+
:completion_proc => lambda {|cmd, arg|
|
|
123
|
+
find_user_candidates arg, "#{cmd} %s"
|
|
124
|
+
},
|
|
125
|
+
:help => ["list,l [USERNAME]", "List the posts"]
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
public_storage[:search_keywords] = Set.new
|
|
129
|
+
register_command(
|
|
130
|
+
:name => :search, :aliases => [:s],
|
|
131
|
+
:exec_proc => lambda {|arg|
|
|
132
|
+
statuses = Termtter::API.twitter.search(arg)
|
|
133
|
+
public_storage[:search_keywords] << arg
|
|
134
|
+
output(statuses, :search)
|
|
135
|
+
},
|
|
136
|
+
:completion_proc => lambda {|cmd, arg|
|
|
137
|
+
public_storage[:search_keywords].grep(/#{Regexp.quote(arg)}/).map { |i| "#{cmd} #{i}" }
|
|
138
|
+
},
|
|
139
|
+
:help => ["search,s TEXT", "Search for Twitter"]
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
register_command(
|
|
143
|
+
:name => :replies, :aliases => [:r],
|
|
144
|
+
:exec_proc => lambda {|arg|
|
|
145
|
+
output(Termtter::API.twitter.replies, :replies)
|
|
146
|
+
},
|
|
147
|
+
:help => ["replies,r", "List the most recent @replies for the authenticating user"]
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
register_command(
|
|
151
|
+
:name => :show,
|
|
152
|
+
:exec_proc => lambda {|arg|
|
|
153
|
+
id = arg.gsub(/.*:\s*/, '')
|
|
154
|
+
output([Termtter::API.twitter.show(id)], :show)
|
|
155
|
+
},
|
|
156
|
+
:completion_proc => lambda {|cmd, arg|
|
|
157
|
+
case arg
|
|
158
|
+
when /(\w+):\s*(\d+)\s*$/
|
|
159
|
+
find_status_ids($2).map{|id| "#{cmd} #{$1}: #{id}"}
|
|
160
|
+
else
|
|
161
|
+
users = find_users(arg)
|
|
162
|
+
unless users.empty?
|
|
163
|
+
users.map {|user| "#{cmd} #{user}:"}
|
|
164
|
+
else
|
|
165
|
+
find_status_ids(arg).map {|id| "#{cmd} #{id}"}
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
},
|
|
169
|
+
:help => ["show ID", "Show a single status"]
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
register_command(
|
|
173
|
+
:name => :shows,
|
|
174
|
+
:exec_proc => lambda {|arg|
|
|
175
|
+
id = arg.gsub(/.*:\s*/, '')
|
|
176
|
+
# TODO: Implement
|
|
177
|
+
#output([Termtter::API.twitter.show(id)], :show)
|
|
178
|
+
puts "Not implemented yet."
|
|
179
|
+
},
|
|
180
|
+
:completion_proc => get_command(:show).completion_proc
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
register_command(
|
|
184
|
+
:name => :follow, :aliases => [],
|
|
185
|
+
:exec_proc => lambda {|args|
|
|
186
|
+
args.split(' ').each do |arg|
|
|
187
|
+
if /^(\w+)/ =~ arg
|
|
188
|
+
res = Termtter::API::twitter.follow($1.strip)
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
},
|
|
192
|
+
:completion_proc => lambda {|cmd, args|
|
|
193
|
+
find_user_candidates args, "#{cmd} %s"
|
|
194
|
+
},
|
|
195
|
+
:help => ['follow USER', 'Follow user']
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
register_command(
|
|
199
|
+
:name => :leave, :aliases => [],
|
|
200
|
+
:exec_proc => lambda {|args|
|
|
201
|
+
args.split(' ').each do |arg|
|
|
202
|
+
if /^(\w+)/ =~ arg
|
|
203
|
+
res = Termtter::API::twitter.leave($1.strip)
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
},
|
|
207
|
+
:completion_proc => lambda {|cmd, args|
|
|
208
|
+
find_user_candidates args, "#{cmd} %s"
|
|
209
|
+
},
|
|
210
|
+
:help => ['leave USER', 'Leave user']
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
register_command(
|
|
214
|
+
:name => :favorite, :aliases => [:fav],
|
|
215
|
+
:exec_proc => lambda {|arg|
|
|
216
|
+
id = 0
|
|
217
|
+
case arg
|
|
218
|
+
when /^\d+/
|
|
219
|
+
id = arg.to_i
|
|
220
|
+
when /^@([A-Za-z0-9_]+)/
|
|
221
|
+
user = $1
|
|
222
|
+
statuses = Termtter::API.twitter.user_timeline(user)
|
|
223
|
+
return if statuses.empty?
|
|
224
|
+
id = statuses[0].id
|
|
225
|
+
when /^\/(.*)$/
|
|
226
|
+
word = $1
|
|
227
|
+
raise "Not implemented yet."
|
|
228
|
+
else
|
|
229
|
+
return
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
r = Termtter::API.twitter.favorite id
|
|
233
|
+
puts "Favorited status ##{r.id} on user @#{r.user.screen_name} #{r.text}"
|
|
234
|
+
},
|
|
235
|
+
:completion_proc => lambda {|cmd, arg|
|
|
236
|
+
case arg
|
|
237
|
+
when /@(.*)/
|
|
238
|
+
find_user_candidates $1, "#{cmd} @%s"
|
|
239
|
+
when /(\d+)/
|
|
240
|
+
find_status_ids(arg).map{|id| "#{cmd} #{id}"}
|
|
241
|
+
else
|
|
242
|
+
%w(favorite).grep(/^#{Regexp.quote arg}/)
|
|
243
|
+
end
|
|
244
|
+
},
|
|
245
|
+
:help => ['favorite,fav (ID|@USER|/WORD)', 'Favorite a status']
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
def self.show_settings(conf, level = 0)
|
|
249
|
+
conf.__values__.each do |k, v|
|
|
250
|
+
if v.instance_of? Termtter::Config
|
|
251
|
+
puts "#{k}:"
|
|
252
|
+
show_settings v, level + 1
|
|
253
|
+
else
|
|
254
|
+
print ' ' * level
|
|
255
|
+
puts "#{k} = #{v.nil? ? 'nil' : v.inspect}"
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
register_command(
|
|
261
|
+
:name => :settings, :aliases => [:set],
|
|
262
|
+
:exec_proc => lambda {|_|
|
|
263
|
+
show_settings config
|
|
264
|
+
},
|
|
265
|
+
:help => ['settings,set', 'Show your settings']
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
# TODO: Change colors when remaining_hits is low.
|
|
269
|
+
# TODO: Simmulate remaining_hits.
|
|
270
|
+
register_command(
|
|
271
|
+
:name => :limit, :aliases => [:lm],
|
|
272
|
+
:exec_proc => lambda {|arg|
|
|
273
|
+
limit = Termtter::API.twitter.limit_status
|
|
274
|
+
remaining_time = "%dmin %dsec" % (Time.parse(limit.reset_time) - Time.now).divmod(60)
|
|
275
|
+
remaining_color =
|
|
276
|
+
case limit.remaining_hits / limit.hourly_limit.to_f
|
|
277
|
+
when 0.2..0.4 then :yellow
|
|
278
|
+
when 0..0.2 then :red
|
|
279
|
+
else :green
|
|
280
|
+
end
|
|
281
|
+
erbed_text = ERB.new(config.plugins.standard.limit_format).result(binding)
|
|
282
|
+
puts TermColor.parse(erbed_text)
|
|
283
|
+
},
|
|
284
|
+
:help => ["limit,lm", "Show the API limit status"]
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
register_command(
|
|
288
|
+
:name => :pause,
|
|
289
|
+
:exec_proc => lambda {|arg| pause},
|
|
290
|
+
:help => ["pause", "Pause updating"]
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
register_command(
|
|
294
|
+
:name => :resume,
|
|
295
|
+
:exec_proc => lambda {|arg| resume},
|
|
296
|
+
:help => ["resume", "Resume updating"]
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
register_command(
|
|
300
|
+
:name => :exit, :aliases => [:e, :q, :quit],
|
|
301
|
+
:exec_proc => lambda {|arg| exit},
|
|
302
|
+
:help => ['exit,e', 'Exit']
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
register_command(
|
|
306
|
+
:name => :help, :aliases => [:h],
|
|
307
|
+
:exec_proc => lambda {|arg|
|
|
308
|
+
helps = []
|
|
309
|
+
@commands.map do |name, command|
|
|
310
|
+
next unless command.help
|
|
311
|
+
case command.help[0]
|
|
312
|
+
when String
|
|
313
|
+
helps << command.help
|
|
314
|
+
when Array
|
|
315
|
+
helps += command.help
|
|
316
|
+
end
|
|
317
|
+
end
|
|
318
|
+
helps.compact!
|
|
319
|
+
puts formatted_help(helps)
|
|
320
|
+
},
|
|
321
|
+
:help => ["help,h", "Print this help message"]
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
def self.formatted_help(helps)
|
|
325
|
+
helps = helps.sort_by {|help| help[0] }
|
|
326
|
+
width = helps.map {|n, _| n.size }.max
|
|
327
|
+
space = 3
|
|
328
|
+
helps.map {|name, desc|
|
|
329
|
+
name.to_s.ljust(width + space) + desc.to_s
|
|
330
|
+
}.join("\n")
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
# completion for standard commands
|
|
334
|
+
|
|
335
|
+
public_storage[:users] ||= Set.new
|
|
336
|
+
public_storage[:status_ids] ||= Set.new
|
|
337
|
+
public_storage[:last_status_id] ||= Hash.new
|
|
338
|
+
|
|
339
|
+
register_hook(
|
|
340
|
+
:name => :for_completion,
|
|
341
|
+
:points => [:pre_filter],
|
|
342
|
+
:exec_proc => lambda {|statuses, event|
|
|
343
|
+
statuses.each do |s|
|
|
344
|
+
public_storage[:users].add(s.user.screen_name)
|
|
345
|
+
public_storage[:users] += s.text.scan(/@([a-zA-Z_0-9]*)/).flatten
|
|
346
|
+
public_storage[:status_ids].add(s.id)
|
|
347
|
+
public_storage[:status_ids].add(s.in_reply_to_status_id) if s.in_reply_to_status_id
|
|
348
|
+
public_storage[:last_status_id].store(s.user.screen_name, s.id)
|
|
349
|
+
end
|
|
350
|
+
}
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
public_storage[:plugins] = (Dir["#{File.dirname(__FILE__)}/*.rb"] + Dir["#{Termtter::CONF_DIR}/plugins/*.rb"]).map do |f|
|
|
354
|
+
f.match(%r|([^/]+).rb$|)[1]
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
register_command(
|
|
358
|
+
:name => :plugin,
|
|
359
|
+
:exec_proc => lambda {|arg|
|
|
360
|
+
if arg.empty?
|
|
361
|
+
puts 'Should specify plugin name.'
|
|
362
|
+
return
|
|
363
|
+
end
|
|
364
|
+
begin
|
|
365
|
+
result = plugin arg
|
|
366
|
+
rescue LoadError
|
|
367
|
+
ensure
|
|
368
|
+
puts "=> #{result.inspect}"
|
|
369
|
+
end
|
|
370
|
+
},
|
|
371
|
+
:completion_proc => lambda {|cmd, args|
|
|
372
|
+
find_user_candidates args, "#{cmd} %s"
|
|
373
|
+
unless args.empty?
|
|
374
|
+
find_plugin_candidates args, "#{cmd} %s"
|
|
375
|
+
else
|
|
376
|
+
public_storage[:plugins].sort
|
|
377
|
+
end
|
|
378
|
+
},
|
|
379
|
+
:help => ['plugin FILE', 'Load a plugin']
|
|
380
|
+
)
|
|
381
|
+
|
|
382
|
+
register_command(
|
|
383
|
+
:name => :plugins,
|
|
384
|
+
:exec_proc => lambda {|arg|
|
|
385
|
+
puts public_storage[:plugins].sort.join("\n")
|
|
386
|
+
},
|
|
387
|
+
:help => ['plugins', 'Show list of plugins']
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
register_command(
|
|
391
|
+
:name => :reply,
|
|
392
|
+
:aliases => [:re],
|
|
393
|
+
:exec_proc => lambda {|arg|
|
|
394
|
+
case arg
|
|
395
|
+
when /^\s*(?:list|ls)\s*(?:\s+(\w+))?\s*$/
|
|
396
|
+
public_storage[:log4re] = if $1
|
|
397
|
+
public_storage[:log].
|
|
398
|
+
select{|l| l.user.screen_name == $1}.
|
|
399
|
+
sort {|a,b| a.id <=> b.id}
|
|
400
|
+
else
|
|
401
|
+
public_storage[:log].sort {|a,b| a.id <=> b.id}
|
|
402
|
+
end
|
|
403
|
+
public_storage[:log4re].each_with_index do |s, i|
|
|
404
|
+
puts "#{i}: #{s.user.screen_name}: #{s.text}"
|
|
405
|
+
end
|
|
406
|
+
when /^\s*(?:up(?:date)?)\s+(\d+)\s+(.+)$/
|
|
407
|
+
id = public_storage[:log4re][$1.to_i].id
|
|
408
|
+
text = $2
|
|
409
|
+
user = public_storage[:log4re][$1.to_i].user
|
|
410
|
+
update_with_user_and_id(text, user.screen_name, id) if user
|
|
411
|
+
public_storage.delete :log4re
|
|
412
|
+
when /^\s*(\d+)\s+(.+)$/
|
|
413
|
+
id, text = $1, $2
|
|
414
|
+
user = public_storage[:log].select {|l| l.id == id.to_i }.first.user
|
|
415
|
+
update_with_user_and_id(text, user.screen_name, id) if user
|
|
416
|
+
when /^\s*@(\w+)/
|
|
417
|
+
in_reply_to_status_id = Termtter::API.twitter.user($1).status.id rescue nil
|
|
418
|
+
params = in_reply_to_status_id ? {:in_reply_to_status_id => in_reply_to_status_id} : {}
|
|
419
|
+
Termtter::API.twitter.update(arg, params)
|
|
420
|
+
puts "=> #{arg}"
|
|
421
|
+
end
|
|
422
|
+
},
|
|
423
|
+
:completion_proc => lambda {|cmd, arg|
|
|
424
|
+
case arg
|
|
425
|
+
when /(.*)@([^\s]*)$/
|
|
426
|
+
find_user_candidates $2, "#{cmd} #{$1}@%s"
|
|
427
|
+
when /(\d+)/
|
|
428
|
+
find_status_ids(arg).map{|id| "#{cmd} #{id}"}
|
|
429
|
+
end
|
|
430
|
+
},
|
|
431
|
+
:help => ["reply,re @USERNAME or STATUS_ID", "Send a reply"]
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
register_command(
|
|
435
|
+
:name => :redo,
|
|
436
|
+
:aliases => [:"."],
|
|
437
|
+
:exec_proc => lambda {|arg|
|
|
438
|
+
break if Readline::HISTORY.length < 2
|
|
439
|
+
i = Readline::HISTORY.length - 2
|
|
440
|
+
input = ""
|
|
441
|
+
begin
|
|
442
|
+
input = Readline::HISTORY[i]
|
|
443
|
+
i -= 1
|
|
444
|
+
return if i <= 0
|
|
445
|
+
end while input == "redo" or input == "."
|
|
446
|
+
begin
|
|
447
|
+
Termtter::Client.call_commands(input)
|
|
448
|
+
rescue CommandNotFound => e
|
|
449
|
+
warn "Unknown command \"#{e}\""
|
|
450
|
+
warn 'Enter "help" for instructions'
|
|
451
|
+
rescue => e
|
|
452
|
+
handle_error e
|
|
453
|
+
end
|
|
454
|
+
},
|
|
455
|
+
:help => ["redo,.", "Execute previous command"]
|
|
456
|
+
)
|
|
457
|
+
|
|
458
|
+
def self.update_with_user_and_id(text, username, id)
|
|
459
|
+
text = ERB.new("@#{username} #{text}").result(binding).gsub(/\n/, ' ')
|
|
460
|
+
result = Termtter::API.twitter.update(text, {'in_reply_to_status_id' => id})
|
|
461
|
+
puts "=> #{text}"
|
|
462
|
+
result
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
=begin
|
|
466
|
+
= Termtter reply command
|
|
467
|
+
== Usage
|
|
468
|
+
=== list
|
|
469
|
+
* ステータスリストを連番と一緒に出す。
|
|
470
|
+
> reply [list|ls]
|
|
471
|
+
0: foo: foo's message
|
|
472
|
+
1: bar: bar's message
|
|
473
|
+
..
|
|
474
|
+
|
|
475
|
+
* ユーザ指定してリスト作成。
|
|
476
|
+
> reply [list|ls] foo
|
|
477
|
+
0: foo: foo's message0
|
|
478
|
+
1: foo: foo's message1
|
|
479
|
+
|
|
480
|
+
=== reply
|
|
481
|
+
メッセージ送信の際、@usernameが自動的に付与される。
|
|
482
|
+
|
|
483
|
+
* status_idを自分で入力してreply送信
|
|
484
|
+
> reply 1234567890 message to status_id
|
|
485
|
+
=> @foo message to status_id (reply to 1234567890)
|
|
486
|
+
|
|
487
|
+
* reply listコマンドで出したステータス番号に対してreply送信
|
|
488
|
+
> reply up 0 message to status no
|
|
489
|
+
=> @foo message to status_no
|
|
490
|
+
|
|
491
|
+
* 対象ユーザの最後の発言に対してreply
|
|
492
|
+
> reply @foo message to foo
|
|
493
|
+
=> @foo message to foo
|
|
494
|
+
|
|
495
|
+
== Todo
|
|
496
|
+
* 英語で説明 => ヘルプを設定する
|
|
497
|
+
* リファクタ
|
|
498
|
+
* 補完
|
|
499
|
+
* 確認画面を出したい
|
|
500
|
+
=end
|
|
501
|
+
|
|
502
|
+
def self.find_plugin_candidates(a, b)
|
|
503
|
+
public_storage[:plugins].
|
|
504
|
+
grep(/^#{Regexp.quote a}/i).
|
|
505
|
+
map {|u| b % u }
|
|
506
|
+
end
|
|
507
|
+
|
|
508
|
+
def self.find_status_ids(text)
|
|
509
|
+
public_storage[:status_ids].select {|id| /#{Regexp.quote(text)}/ =~ id.to_s}
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
def self.find_users(text)
|
|
513
|
+
public_storage[:users].select {|user| /^#{Regexp.quote(text)}/ =~ user}
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
def self.find_user_candidates(a, b)
|
|
517
|
+
users =
|
|
518
|
+
if a.nil? || a.empty?
|
|
519
|
+
public_storage[:users].to_a
|
|
520
|
+
else
|
|
521
|
+
public_storage[:users].grep(/^#{Regexp.quote a}/i)
|
|
522
|
+
end
|
|
523
|
+
users.map {|u| b % u }
|
|
524
|
+
end
|
|
525
|
+
end
|