jugyo-termtter 1.1.3 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +115 -0
- data/README.rdoc +25 -10
- data/Rakefile +53 -34
- data/lib/plugins/cool.rb +2 -5
- data/lib/plugins/curry.rb +43 -0
- data/lib/plugins/db.rb +91 -0
- data/lib/plugins/{auto_reload.rb → defaults/auto_reload.rb} +5 -1
- data/lib/plugins/defaults/command_line.rb +111 -0
- data/lib/plugins/{exec.rb → defaults/exec.rb} +2 -7
- data/lib/plugins/{fib.rb → defaults/fib.rb} +1 -4
- data/lib/plugins/defaults/retweet.rb +34 -0
- data/lib/plugins/{standard_commands.rb → defaults/standard_commands.rb} +88 -162
- data/lib/plugins/defaults/standard_completion.rb +67 -0
- data/lib/plugins/defaults/stdout.rb +148 -0
- data/lib/plugins/defaults.rb +14 -0
- data/lib/plugins/en2ja.rb +11 -5
- data/lib/plugins/english.rb +2 -2
- data/lib/plugins/expand-tinyurl.rb +27 -6
- data/lib/plugins/github-issues.rb +192 -0
- data/lib/plugins/group.rb +30 -4
- data/lib/plugins/growl.rb +10 -1
- data/lib/plugins/http_server/favicon.ico +0 -0
- data/lib/plugins/http_server/index.html +117 -0
- data/lib/plugins/http_server.rb +82 -0
- data/lib/plugins/irb.rb +6 -0
- data/lib/plugins/l2.rb +1 -1
- data/lib/plugins/list_with_opts.rb +0 -3
- data/lib/plugins/log.rb +6 -9
- data/lib/plugins/modify_arg_hook_sample.rb +3 -5
- data/lib/plugins/multi_reply.rb +0 -5
- data/lib/plugins/notify-send.rb +1 -1
- data/lib/plugins/notify-send2.rb +1 -1
- data/lib/plugins/notify-send3.rb +11 -3
- data/lib/plugins/open_url.rb +5 -17
- data/lib/plugins/otsune.rb +3 -9
- data/lib/plugins/outputz.rb +1 -1
- data/lib/plugins/pool.rb +30 -0
- data/lib/plugins/protected_filter.rb +9 -0
- data/lib/plugins/quicklook.rb +1 -1
- data/lib/plugins/saykanji.rb +81 -0
- data/lib/plugins/shell.rb +1 -6
- data/lib/plugins/sl.rb +8 -8
- data/lib/plugins/tinyurl.rb +26 -7
- data/lib/plugins/trends.rb +84 -0
- data/lib/plugins/twitpic.rb +46 -0
- data/lib/plugins/uri-open.rb +33 -28
- data/lib/plugins/wassr.rb +0 -3
- data/lib/plugins/whois.rb +45 -0
- data/lib/plugins/yhara.rb +2 -6
- data/lib/termtter/client.rb +91 -103
- data/lib/termtter/command.rb +24 -9
- data/lib/termtter/config.rb +8 -6
- data/lib/termtter/config_setup.rb +1 -1
- data/lib/termtter/config_template.erb +1 -4
- data/lib/termtter/hook.rb +2 -2
- data/lib/termtter/optparse.rb +14 -1
- data/lib/termtter/system_extensions.rb +3 -2
- data/lib/termtter/task_manager.rb +1 -5
- data/lib/termtter/version.rb +1 -1
- data/spec/plugins/cool_spec.rb +1 -1
- data/spec/plugins/curry_spec.rb +13 -0
- data/spec/plugins/db_spec.rb +62 -0
- data/spec/plugins/english_spec.rb +2 -2
- data/spec/plugins/fib_spec.rb +2 -2
- data/spec/plugins/filter_spec.rb +2 -2
- data/spec/plugins/pause_spec.rb +1 -1
- data/spec/plugins/primes_spec.rb +2 -2
- data/spec/plugins/shell_spec.rb +1 -1
- data/spec/plugins/sl_spec.rb +1 -1
- data/spec/plugins/{standard_plugins_spec.rb → standard_commands_spec.rb} +2 -2
- data/spec/plugins/whois_spec.rb +20 -0
- data/spec/termtter/client_spec.rb +151 -33
- data/spec/termtter/command_spec.rb +68 -35
- data/spec/termtter/config_spec.rb +10 -0
- data/spec/termtter/optparse_spec.rb +16 -0
- data/spec/termtter_spec.rb +7 -8
- metadata +48 -19
- data/History.txt +0 -4
- data/lib/plugins/direct_messages.rb +0 -36
- data/lib/plugins/retweet.rb +0 -46
- data/lib/plugins/stdout.rb +0 -77
data/lib/plugins/english.rb
CHANGED
@@ -20,6 +20,6 @@ end
|
|
20
20
|
# select English posts only
|
21
21
|
#
|
22
22
|
# config sample:
|
23
|
-
#
|
23
|
+
# t.plug 'english'
|
24
24
|
# or,
|
25
|
-
#
|
25
|
+
# t.plug 'english', :only => [:list_friends_timeline, :update_friends_timeline]
|
@@ -4,13 +4,34 @@ URL_SHORTTERS = [
|
|
4
4
|
{ :host => "tinyurl.com", :pattern => %r'(http://tinyurl\.com(/[\w/]+))' },
|
5
5
|
{ :host => "is.gd", :pattern => %r'(http://is\.gd(/[\w/]+))' },
|
6
6
|
{ :host => "bit.ly", :pattern => %r'(http://bit\.ly(/[\w/]+))' },
|
7
|
-
{ :host => "ff.im", :pattern => %r'(http://ff\.im(/[
|
7
|
+
{ :host => "ff.im", :pattern => %r'(http://ff\.im(/[-\w/]+))'},
|
8
8
|
]
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
config.plugins.expand_tinyurl.set_default(:shortters, [])
|
11
|
+
config.plugins.expand_tinyurl.set_default(:skip_users, [])
|
12
|
+
|
13
|
+
# for Ruby 1.8
|
14
|
+
unless String.public_method_defined?(:force_encoding)
|
15
|
+
class String
|
16
|
+
def force_encoding(enc)
|
17
|
+
self
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module Encoding
|
22
|
+
UTF_8 = nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
Termtter::Client::register_hook(
|
27
|
+
:name => :expand_tinyurl,
|
28
|
+
:point => :filter_for_output,
|
29
|
+
:exec_proc => lambda do |statuses, event|
|
30
|
+
shortters = URL_SHORTTERS + config.plugins.expand_tinyurl.shortters
|
31
|
+
skip_users = config.plugins.expand_tinyurl.skip_users
|
12
32
|
statuses.each do |s|
|
13
|
-
|
33
|
+
skip_users.include?(s.user.screen_name) and next
|
34
|
+
shortters.each do |site|
|
14
35
|
s.text.gsub!(site[:pattern]) do |m|
|
15
36
|
expand_url(site[:host], $2) || $1
|
16
37
|
end
|
@@ -18,7 +39,7 @@ module Termtter::Client
|
|
18
39
|
end
|
19
40
|
statuses
|
20
41
|
end
|
21
|
-
|
42
|
+
)
|
22
43
|
|
23
44
|
def expand_url(host, path)
|
24
45
|
http_class = Net::HTTP
|
@@ -30,5 +51,5 @@ def expand_url(host, path)
|
|
30
51
|
end
|
31
52
|
res = http_class.new(host).head(path)
|
32
53
|
return nil unless res.code == "301" or res.code == "302"
|
33
|
-
res['Location']
|
54
|
+
res['Location'].force_encoding(Encoding::UTF_8)
|
34
55
|
end
|
@@ -0,0 +1,192 @@
|
|
1
|
+
# -*- coding: utf-8 -*
|
2
|
+
|
3
|
+
require 'tempfile'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'giic'
|
6
|
+
|
7
|
+
module Termtter::Client
|
8
|
+
editor = ENV['EDITOR'] or
|
9
|
+
config.editor or
|
10
|
+
config.plugins.update_editor.editor
|
11
|
+
config.plugins.github_issues.set_default('editor', editor)
|
12
|
+
|
13
|
+
config.plugins.github_issues.set_default('user', 'jugyo')
|
14
|
+
config.plugins.github_issues.set_default('repo', 'termtter')
|
15
|
+
|
16
|
+
register_command('isearch', :alias => 'ise', :help => ['isearch, ise WORD', 'search issue']) do |word|
|
17
|
+
if word.empty?
|
18
|
+
warn 'need search word'
|
19
|
+
next
|
20
|
+
end
|
21
|
+
res = gi_project.search(word)
|
22
|
+
if res.has_key?('error')
|
23
|
+
warn 'failed'
|
24
|
+
next
|
25
|
+
end
|
26
|
+
no_length = res['issues'].map {|i| i.number.to_s.size }.max
|
27
|
+
list = res['issues'].map {|i| "##{i.number.to_s.ljust(no_length)} #{i.title}" }
|
28
|
+
list.empty? ? warn('no issue found') : puts(list.join("\n"))
|
29
|
+
end
|
30
|
+
|
31
|
+
register_command('ilist', :alias => 'il', :help => ['ilist, il', 'list all issues']) do |state|
|
32
|
+
state = state.empty? ? 'open' : state
|
33
|
+
list = gi_project.list(state)['issues']
|
34
|
+
no_length = list.map {|i| i.number.to_s.size }.max
|
35
|
+
list = list.map {|i| "##{i.number.to_s.ljust(no_length)} #{i.title}" }
|
36
|
+
puts list.join("\n")
|
37
|
+
end
|
38
|
+
|
39
|
+
register_command('ishow', :alias => 'is', :help => ['ishow,is NO', 'show specific issue']) do |no|
|
40
|
+
if no.empty?
|
41
|
+
warn 'need issue number'
|
42
|
+
next
|
43
|
+
end
|
44
|
+
res = gi_project.show(no.to_i)
|
45
|
+
if res.has_key?('error')
|
46
|
+
warn 'no such issue'
|
47
|
+
next
|
48
|
+
end
|
49
|
+
issue = res['issue']
|
50
|
+
label_length = issue.keys.map(&:size).max
|
51
|
+
issue.each do |key, value|
|
52
|
+
puts "#{key.rjust(label_length)}: #{value}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
register_command('iopen', :alias => 'io', :help => ['iopen,io TITLE', 'open new issue']) do |title|
|
57
|
+
if title.empty?
|
58
|
+
warn 'need issue title'
|
59
|
+
next
|
60
|
+
end
|
61
|
+
login
|
62
|
+
body = input_editor
|
63
|
+
res = login.open(title, body)
|
64
|
+
if res.has_key?('error')
|
65
|
+
warn 'failed'
|
66
|
+
next
|
67
|
+
end
|
68
|
+
res = res['issue']
|
69
|
+
label_length = res.keys.map(&:size).max
|
70
|
+
puts 'success:'
|
71
|
+
puts
|
72
|
+
res.each do |key, value|
|
73
|
+
puts "#{key.rjust(label_length)}: #{value}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
register_command('iedit', :alias => 'ie', :help => ['iedit,ie NO', 'edit issue']) do |no|
|
78
|
+
if no.empty?
|
79
|
+
warn 'need issue no'
|
80
|
+
next
|
81
|
+
end
|
82
|
+
no = no.to_i
|
83
|
+
target = gi_project.show(no)
|
84
|
+
if target.has_key?('error')
|
85
|
+
warn 'no such issue'
|
86
|
+
next
|
87
|
+
end
|
88
|
+
issue_body = target['issue']['body']
|
89
|
+
login
|
90
|
+
body = input_editor(issue_body)
|
91
|
+
res = login.edit(no, body)
|
92
|
+
if res.has_key?('error')
|
93
|
+
warn 'failed'
|
94
|
+
next
|
95
|
+
end
|
96
|
+
res = res['issue']
|
97
|
+
label_length = res.keys.map(&:size).max
|
98
|
+
puts 'success:'
|
99
|
+
puts
|
100
|
+
res.each do |key, value|
|
101
|
+
puts "#{key.rjust(label_length)}: #{value}"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
register_command('icommand', :alias => 'icom', :help => ['icommand, icom NO', 'write comment to issue']) do |no|
|
106
|
+
if no.empty?
|
107
|
+
warn 'need issue no'
|
108
|
+
next
|
109
|
+
end
|
110
|
+
login
|
111
|
+
comment = input_editor
|
112
|
+
res = login.comment(no.to_i, comment)
|
113
|
+
res.has_key?('error') ? warn('failed') : puts('success')
|
114
|
+
end
|
115
|
+
|
116
|
+
register_command('ilabel', :alias => 'ilab', :help => ['ilabel,ilab (add | remove) LABEL NO', 'add or remove label to issue']) do |args|
|
117
|
+
op, label, no = args.split(/\s/)
|
118
|
+
unless [op, label, no].all?
|
119
|
+
warn 'need op, label, no'
|
120
|
+
next
|
121
|
+
end
|
122
|
+
case op
|
123
|
+
when 'add'
|
124
|
+
res = login.add_label(label, no)
|
125
|
+
res.has_key?('error') ? warn('failed') : puts('success')
|
126
|
+
when 'remove'
|
127
|
+
res = login.remove_label(label, no)
|
128
|
+
res.has_key?('error') ? warn('failed') : puts('success')
|
129
|
+
else
|
130
|
+
warn 'no such operate'
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
register_command('iclose', :alias => 'ic', :help => ['iclose,ic NO', 'close issue']) do |no|
|
135
|
+
if no.empty?
|
136
|
+
warn 'need issue title'
|
137
|
+
next
|
138
|
+
end
|
139
|
+
res = login.close(no.to_i)
|
140
|
+
res.has_key?('error') ? warn('failed') : puts('success')
|
141
|
+
end
|
142
|
+
|
143
|
+
register_command('ireopen', :alias => 'iro', :help => ['ireopen,ire NO', 'reopen closed issue']) do |no|
|
144
|
+
if no.empty?
|
145
|
+
warn 'need issue title'
|
146
|
+
next
|
147
|
+
end
|
148
|
+
res = login.reopen(no.to_i)
|
149
|
+
res.has_key?('error') ? warn('failed') : puts('success')
|
150
|
+
end
|
151
|
+
|
152
|
+
register_command('irepo', :alias => 'ir', :help => ['irepo, ir USER REPO', 'change user and repo']) do |user_repo|
|
153
|
+
user, repo = user_repo.split(/\s/)
|
154
|
+
unless [user, repo].all?
|
155
|
+
puts "now: user => #{gi_config.user}, repo => #{gi_config.repo}"
|
156
|
+
next
|
157
|
+
end
|
158
|
+
gi_config.user = user
|
159
|
+
gi_config.repo = repo
|
160
|
+
puts "changed: user => #{user}, repo => #{repo}"
|
161
|
+
end
|
162
|
+
|
163
|
+
private
|
164
|
+
|
165
|
+
def self.gi_config; config.plugins.github_issues end
|
166
|
+
def self.gi_project; Giic.new(gi_config.user, gi_config.repo) end
|
167
|
+
|
168
|
+
def self.login
|
169
|
+
if config.plugins.github_issues.login.empty?
|
170
|
+
print 'login > '; $stdout.flush
|
171
|
+
config.plugins.github_issues.login = gets.chomp
|
172
|
+
end
|
173
|
+
if config.plugins.github_issues.token.empty?
|
174
|
+
print 'token > '; $stdout.flush
|
175
|
+
config.plugins.github_issues.token = gets.chomp
|
176
|
+
end
|
177
|
+
gi_project.login(gi_config.login, gi_config.token)
|
178
|
+
end
|
179
|
+
|
180
|
+
def self.input_editor(body = nil)
|
181
|
+
file = Tempfile.new('termtter')
|
182
|
+
editor = config.plugins.github_issues.editor
|
183
|
+
file.write body if body
|
184
|
+
file.close
|
185
|
+
system("#{editor} #{file.path}")
|
186
|
+
result = file.open.read
|
187
|
+
file.flush
|
188
|
+
file.close(false)
|
189
|
+
result
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
data/lib/plugins/group.rb
CHANGED
@@ -4,9 +4,9 @@ module Termtter
|
|
4
4
|
class Status
|
5
5
|
def is_member?(group = nil)
|
6
6
|
if group
|
7
|
-
config.plugins.group.groups[group].include? self.
|
7
|
+
config.plugins.group.groups[group].include? self.user.screen_name
|
8
8
|
else
|
9
|
-
config.plugins.group.groups.values.flatten.include? self.
|
9
|
+
config.plugins.group.groups.values.flatten.include? self.user.screen_name
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -15,6 +15,8 @@ end
|
|
15
15
|
module Termtter::Client
|
16
16
|
config.plugins.group.
|
17
17
|
set_default(:groups, {})
|
18
|
+
config.plugins.group.
|
19
|
+
set_default(:default_filter, nil)
|
18
20
|
|
19
21
|
def self.find_group_candidates(a, b)
|
20
22
|
config.plugins.group.groups.keys.map {|k| k.to_s}.
|
@@ -52,11 +54,35 @@ module Termtter::Client
|
|
52
54
|
},
|
53
55
|
:help => ['group,g GROUPNAME', 'Filter by group members']
|
54
56
|
)
|
55
|
-
|
57
|
+
|
58
|
+
def self.is_member?(status, group = nil)
|
59
|
+
if group
|
60
|
+
config.plugins.group.groups[group].include? status.user.screen_name
|
61
|
+
else
|
62
|
+
config.plugins.group.groups.values.flatten.include? status.user.screen_name
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
register_hook(
|
67
|
+
:name => :group_filter,
|
68
|
+
:point => :filter_for_output,
|
69
|
+
:exec_proc => lambda do |statuses, event|
|
70
|
+
return statuses unless event == :update_friends_timeline
|
71
|
+
return statuses unless config.plugins.group.default_filter
|
72
|
+
skip_group = config.plugins.group.default_filter
|
73
|
+
r = []
|
74
|
+
statuses.each do |s|
|
75
|
+
unless self.is_member?(s, :dqn)
|
76
|
+
r << s
|
77
|
+
end
|
78
|
+
end
|
79
|
+
r
|
80
|
+
end
|
81
|
+
)
|
56
82
|
end
|
57
83
|
|
58
84
|
# group.rb
|
59
|
-
#
|
85
|
+
# t.plug 'group'
|
60
86
|
# config.plugins.group.groups = {
|
61
87
|
# :rits => %w(hakobe isano hitode909)
|
62
88
|
# }
|
data/lib/plugins/growl.rb
CHANGED
@@ -13,6 +13,8 @@ rescue LoadError
|
|
13
13
|
growl = nil
|
14
14
|
end
|
15
15
|
|
16
|
+
config.plugins.growl.set_default(:sticky, false)
|
17
|
+
config.plugins.growl.set_default(:priority, 0)
|
16
18
|
config.plugins.growl.set_default(:icon_cache_dir, "#{Termtter::CONF_DIR}/tmp/user_profile_images")
|
17
19
|
FileUtils.mkdir_p(config.plugins.growl.icon_cache_dir) unless File.exist?(config.plugins.growl.icon_cache_dir)
|
18
20
|
|
@@ -41,9 +43,16 @@ Termtter::Client.register_hook(
|
|
41
43
|
Thread.start do
|
42
44
|
statuses.each do |s|
|
43
45
|
unless growl
|
46
|
+
# TODO: Add option for priority and sticky
|
44
47
|
system 'growlnotify', s.user.screen_name, '-m', s.text.gsub("\n",''), '-n', 'termtter', '--image', get_icon_path(s)
|
45
48
|
else
|
46
|
-
growl.notify
|
49
|
+
growl.notify(
|
50
|
+
"update_friends_timeline",
|
51
|
+
s.user.screen_name,
|
52
|
+
CGI.unescapeHTML(s.text),
|
53
|
+
config.plugins.growl.priority,
|
54
|
+
config.plugins.growl.sticky
|
55
|
+
)
|
47
56
|
end
|
48
57
|
sleep 0.1
|
49
58
|
end
|
Binary file
|
@@ -0,0 +1,117 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
4
|
+
<head>
|
5
|
+
<title>Termtter</title>
|
6
|
+
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript"></script>
|
7
|
+
</head>
|
8
|
+
<style type="text/css">
|
9
|
+
body {
|
10
|
+
margin: 0;
|
11
|
+
padding: 0;
|
12
|
+
font-size: 12px;
|
13
|
+
font-family: Verdana,Helvetica;
|
14
|
+
color: #98FF68;
|
15
|
+
background-color: #141414;
|
16
|
+
}
|
17
|
+
img {
|
18
|
+
border: none;
|
19
|
+
}
|
20
|
+
#wrap {
|
21
|
+
padding: 8px;
|
22
|
+
}
|
23
|
+
.error_message {
|
24
|
+
color: red;
|
25
|
+
}
|
26
|
+
#execute_text {
|
27
|
+
width: 96%;
|
28
|
+
color: #98FF68;
|
29
|
+
background-color: #141414;
|
30
|
+
border: none;
|
31
|
+
font-size: 12px;
|
32
|
+
}
|
33
|
+
.status_line {
|
34
|
+
margin: 1px 0;
|
35
|
+
}
|
36
|
+
.profile_image {
|
37
|
+
margin: 0 4px;
|
38
|
+
}
|
39
|
+
.status_info {
|
40
|
+
color: #5C5C5C;
|
41
|
+
}
|
42
|
+
.status_text {
|
43
|
+
margin-right: 4px;
|
44
|
+
}
|
45
|
+
</style>
|
46
|
+
<body>
|
47
|
+
<div id="wrap">
|
48
|
+
<div id="result"></div>
|
49
|
+
<div id="input_area">
|
50
|
+
<form id="execute_command">
|
51
|
+
<span id="prompt">> </span><input id="execute_text" type="text" size="80" autocomplete=off />
|
52
|
+
</form>
|
53
|
+
</div>
|
54
|
+
<div id="loading" style="display: none;">...</div>
|
55
|
+
</div>
|
56
|
+
<script type="text/javascript">
|
57
|
+
<!--
|
58
|
+
$(document).ready(function(){
|
59
|
+
$("#execute_text").focus();
|
60
|
+
execute_command('reload.html');
|
61
|
+
setInterval(function(){
|
62
|
+
execute_command('reload.html');
|
63
|
+
}, 10 * 1000)
|
64
|
+
})
|
65
|
+
|
66
|
+
$("#result").bind("ajaxError", function(event, reqest){
|
67
|
+
$('<div class="error_message"/>').text(reqest.responseText).appendTo(this);
|
68
|
+
scrollTo(0, document.height);
|
69
|
+
$("#prompt").show();
|
70
|
+
});
|
71
|
+
|
72
|
+
$("#execute_command").submit(function () {
|
73
|
+
var command = $("#execute_text").val();
|
74
|
+
$('<div class="status_line"/>').text('> ' + command).appendTo('#result');
|
75
|
+
scrollTo(0, document.height);
|
76
|
+
if (command.match(/^\s*$/)) {
|
77
|
+
return false;
|
78
|
+
}
|
79
|
+
$("#execute_text").val('');
|
80
|
+
$("#prompt").hide();
|
81
|
+
execute_command(command);
|
82
|
+
return false;
|
83
|
+
});
|
84
|
+
|
85
|
+
function execute_command(command) {
|
86
|
+
var path = "/" + command
|
87
|
+
$.getJSON(path,
|
88
|
+
function(data){
|
89
|
+
$.each(data, function(i, status){
|
90
|
+
var status_line = $('<div class="status_line"/>');
|
91
|
+
$('<span class="status_info"/>').text('(' + format_datetime(status.created_at) + ') ').appendTo(status_line);
|
92
|
+
var user_link = $('<a/>').attr('href', 'http://twitter.com/' + status.user.screen_name).attr('target', '_blank');
|
93
|
+
$('<img class="profile_image"/>').attr('src', status.user.profile_image_url).attr('height', '14').attr('width', '14').appendTo(user_link);
|
94
|
+
user_link.appendTo(status_line);
|
95
|
+
$('<span class="status_text"/>').text(' ' + status.user.screen_name + ': ' + status.text).appendTo(status_line);
|
96
|
+
$('<span class="status_info"/>').text(' ' + status.id).appendTo(status_line);
|
97
|
+
status_line.appendTo("#result");
|
98
|
+
});
|
99
|
+
scrollTo(0, document.height);
|
100
|
+
$("#prompt").show();
|
101
|
+
}
|
102
|
+
);
|
103
|
+
}
|
104
|
+
|
105
|
+
function format_datetime(time_value) {
|
106
|
+
var values = time_value.split(/\s+/);
|
107
|
+
time_value = values[1] + " " + values[2] + ", " + values[5] + " " + values[3];
|
108
|
+
var date = new Date(time_value);
|
109
|
+
date.setMinutes(date.getMinutes() - (new Date()).getTimezoneOffset());
|
110
|
+
return (date.getHours() < 10 ? '0' : '') + date.getHours() + ':' +
|
111
|
+
(date.getMinutes() < 10 ? '0' : '') + date.getMinutes() + ':' +
|
112
|
+
(date.getSeconds() < 10 ? '0' : '') + date.getSeconds();
|
113
|
+
}
|
114
|
+
-->
|
115
|
+
</script>
|
116
|
+
</body>
|
117
|
+
</html>
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# http_server
|
2
|
+
#
|
3
|
+
# = REQUIREMENTS
|
4
|
+
# * mime-types
|
5
|
+
# * rubytter >= 0.8.0 (for web client)
|
6
|
+
#
|
7
|
+
|
8
|
+
require 'mime/types'
|
9
|
+
require 'pathname'
|
10
|
+
require 'webrick'
|
11
|
+
require 'logger'
|
12
|
+
|
13
|
+
config.plugins.http_server.set_default(:port, 5678)
|
14
|
+
config.plugins.http_server.set_default(:reload_max_count, 100)
|
15
|
+
|
16
|
+
module Termtter::Client
|
17
|
+
if @http_server
|
18
|
+
@http_server.shutdown # for reload
|
19
|
+
end
|
20
|
+
|
21
|
+
@http_server_statuses_store = []
|
22
|
+
|
23
|
+
register_hook(:http_server_output, :point => :output) do |statuses, event|
|
24
|
+
@http_server_output = statuses.to_json
|
25
|
+
if event == :update_friends_timeline
|
26
|
+
@http_server_statuses_store += statuses
|
27
|
+
max = config.plugins.http_server.reload_max_count
|
28
|
+
if @http_server_statuses_store.size > max
|
29
|
+
from = @http_server_statuses_store.size - max
|
30
|
+
@http_server_statuses_store = @http_server_statuses_store[from..-1]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
register_hook(:http_server_shutdown, :point => :exit) do
|
36
|
+
@http_server.shutdown
|
37
|
+
end
|
38
|
+
|
39
|
+
@http_server_logger = Logger.new(nil)
|
40
|
+
@http_server_logger.level = Logger::WARN
|
41
|
+
@http_server = WEBrick::HTTPServer.new(
|
42
|
+
:BindAddress => '127.0.0.1',
|
43
|
+
:Port => config.plugins.http_server.port,
|
44
|
+
:Logger => @http_server_logger,
|
45
|
+
:AccessLog => []
|
46
|
+
)
|
47
|
+
|
48
|
+
@http_server.mount_proc('/reload.html') do |req, res|
|
49
|
+
# MEMO: ブラウザで画面を二つ開いてるとデータの取り合いになっておかしな感じになる。。。
|
50
|
+
res['Content-Type'] = 'text/javascript; charset=utf-8';
|
51
|
+
res.body = @http_server_statuses_store.to_json
|
52
|
+
@http_server_statuses_store.clear
|
53
|
+
end
|
54
|
+
|
55
|
+
@http_server.mount_proc('/') do |req, res|
|
56
|
+
request_path = req.path == '/' ? 'index.html' : req.path
|
57
|
+
base_name = Pathname.new(request_path).basename.to_s
|
58
|
+
file_path = File.dirname(__FILE__) + '/http_server/' + base_name
|
59
|
+
|
60
|
+
if File.file?(file_path)
|
61
|
+
# send a file
|
62
|
+
res.header["Content-Type"] = MIME::Types.type_for(file_path).first.content_type
|
63
|
+
res.body = File.open(file_path, 'rb').read
|
64
|
+
else
|
65
|
+
# execute a command
|
66
|
+
@http_server_output = ''
|
67
|
+
begin
|
68
|
+
command = req.path.sub(/^\//, '')
|
69
|
+
call_commands(command)
|
70
|
+
res['Content-Type'] = 'text/javascript; charset=utf-8';
|
71
|
+
res.body = @http_server_output
|
72
|
+
rescue Termtter::CommandNotFound => e
|
73
|
+
res.status = 404
|
74
|
+
res.body = "Command Not Found!!"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
Thread.start do
|
80
|
+
@http_server.start
|
81
|
+
end
|
82
|
+
end
|
data/lib/plugins/irb.rb
ADDED
data/lib/plugins/l2.rb
CHANGED
data/lib/plugins/log.rb
CHANGED
@@ -34,8 +34,8 @@ module Termtter::Client
|
|
34
34
|
)
|
35
35
|
|
36
36
|
register_command(
|
37
|
-
|
38
|
-
|
37
|
+
:name => :log,
|
38
|
+
:exec_proc => lambda{|arg|
|
39
39
|
if arg.empty?
|
40
40
|
# log
|
41
41
|
statuses = public_storage[:log]
|
@@ -44,19 +44,16 @@ module Termtter::Client
|
|
44
44
|
output(statuses[-print_max..-1], :search)
|
45
45
|
else
|
46
46
|
# log (user) (max)
|
47
|
-
vars = arg.split(
|
47
|
+
vars = arg.split(/\s/).map{ |i| normalize_as_user_name(i) }
|
48
48
|
print_max = vars.last =~ /^\d+$/ ? vars.pop.to_i : config.plugins.log.print_max_size
|
49
49
|
id = vars
|
50
50
|
statuses = id.first ? public_storage[:log].select{ |s| id.include? s.user.screen_name} : public_storage[:log]
|
51
51
|
print_max = 0 if statuses.size < print_max
|
52
52
|
output(statuses[-print_max..-1], :search)
|
53
53
|
end
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
},
|
58
|
-
:help => [ 'log (USER(S)) (MAX)', 'Show local log of the user(s)']
|
59
|
-
)
|
54
|
+
},
|
55
|
+
:help => [ 'log (USER(S)) (MAX)', 'Show local log of the user(s)']
|
56
|
+
)
|
60
57
|
|
61
58
|
register_command(
|
62
59
|
:name => :search_log, :aliases => [:sl],
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
|
-
Termtter::Client.register_hook(
|
4
|
-
|
5
|
-
|
6
|
-
:exec_proc => lambda {|cmd, arg| arg + '\(^o^)/'}
|
7
|
-
)
|
3
|
+
Termtter::Client.register_hook(:modify_arg_hook_sample, :point => :modify_arg_for_update) do |cmd, arg|
|
4
|
+
arg + ' \(^o^)/'
|
5
|
+
end
|
data/lib/plugins/multi_reply.rb
CHANGED
data/lib/plugins/notify-send.rb
CHANGED
data/lib/plugins/notify-send2.rb
CHANGED
@@ -43,7 +43,7 @@ Termtter::Client.register_hook(
|
|
43
43
|
statuses.each do |s|
|
44
44
|
text = CGI.escapeHTML(s.text)
|
45
45
|
text.gsub!(%r{https?://[-_.!~*\'()a-zA-Z0-9;\/?:\@&=+\$,%#]+},'<a href="\0">\0</a>')
|
46
|
-
system 'notify-send',
|
46
|
+
system 'notify-send', '-i', get_icon_path(s), '--', s.user.screen_name, text
|
47
47
|
sleep 0.1
|
48
48
|
end
|
49
49
|
end
|
data/lib/plugins/notify-send3.rb
CHANGED
@@ -14,11 +14,19 @@ def get_icon_path(s)
|
|
14
14
|
if !File.exist?(cache_file) || (File.atime(cache_file) + 24*60*60) < Time.now
|
15
15
|
File.open(cache_file, "wb") do |f|
|
16
16
|
begin
|
17
|
-
|
17
|
+
http_class = Net::HTTP
|
18
|
+
unless config.proxy.host.nil? or config.proxy.host.empty?
|
19
|
+
http_class = Net::HTTP::Proxy(config.proxy.host,
|
20
|
+
config.proxy.port,
|
21
|
+
config.proxy.user_name,
|
22
|
+
config.proxy.password)
|
23
|
+
end
|
24
|
+
uri = URI.parse(URI.escape(s.user.profile_image_url))
|
25
|
+
image = http_class.get(uri.host, uri.path, uri.port)
|
18
26
|
rimage = Magick::Image.from_blob(image).first
|
19
27
|
rimage = rimage.resize_to_fill(48, 48)
|
20
28
|
f << rimage.to_blob
|
21
|
-
rescue
|
29
|
+
rescue Net::ProtocolError
|
22
30
|
return nil
|
23
31
|
end
|
24
32
|
end
|
@@ -37,7 +45,7 @@ Termtter::Client.register_hook(
|
|
37
45
|
text = %Q{"#{text}"} if text =~ /^-/
|
38
46
|
text.gsub!(URI.regexp,'<a href="\0">\0</a>')
|
39
47
|
begin
|
40
|
-
system 'notify-send',
|
48
|
+
system 'notify-send', '-i', get_icon_path(s), '--', s.user.screen_name, text
|
41
49
|
sleep 0.05
|
42
50
|
rescue
|
43
51
|
end
|