termtter 1.5.0 → 1.6.0
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/Rakefile +2 -1
- data/bin/termtter +1 -0
- data/lib/plugins/another_prompt.rb +131 -0
- data/lib/plugins/async.rb +23 -0
- data/lib/plugins/confirm.rb +1 -1
- data/lib/plugins/db.rb +1 -1
- data/lib/plugins/defaults/auto_reload.rb +20 -19
- data/lib/plugins/defaults/command_line.rb +10 -5
- data/lib/plugins/defaults/hashtag.rb +35 -0
- data/lib/plugins/defaults/lists.rb +14 -0
- data/lib/plugins/defaults/retweet.rb +15 -15
- data/lib/plugins/defaults/standard_commands.rb +22 -28
- data/lib/plugins/defaults/standard_completion.rb +5 -5
- data/lib/plugins/defaults/switch.rb +34 -0
- data/lib/plugins/eject.rb +15 -0
- data/lib/plugins/expand-tinyurl.rb +1 -1
- data/lib/plugins/favotter.rb +77 -0
- data/lib/plugins/friends.rb +50 -0
- data/lib/plugins/g.rb +16 -0
- data/lib/plugins/gsub.rb +17 -0
- data/lib/plugins/haml.rb +55 -0
- data/lib/plugins/hatebu_and_update.rb +2 -2
- data/lib/plugins/history.rb +9 -0
- data/lib/plugins/irc_gw.rb +11 -4
- data/lib/plugins/linefeed.rb +31 -0
- data/lib/plugins/md5pass.rb +42 -0
- data/lib/plugins/outputz.rb +1 -1
- data/lib/plugins/primes.rb +1 -1
- data/lib/plugins/quote.rb +43 -0
- data/lib/plugins/reduce_text.rb +26 -0
- data/lib/plugins/reverse.rb +7 -6
- data/lib/plugins/source.rb +31 -0
- data/lib/plugins/storage/status.rb +2 -2
- data/lib/plugins/storage.rb +1 -1
- data/lib/plugins/stream.rb +192 -0
- data/lib/plugins/switch_user.rb +1 -22
- data/lib/plugins/truncate.rb +29 -0
- data/lib/plugins/uri-open.rb +23 -9
- data/lib/plugins/w3mimg.rb +76 -0
- data/lib/termtter/active_rubytter.rb +8 -0
- data/lib/termtter/api.rb +37 -13
- data/lib/termtter/client.rb +26 -47
- data/lib/termtter/command.rb +15 -9
- data/lib/termtter/config.rb +6 -2
- data/lib/termtter/hookable.rb +59 -0
- data/lib/termtter/optparse.rb +51 -39
- data/lib/termtter/rubytter_proxy.rb +32 -0
- data/lib/termtter/system_extensions/core_compatibles.rb +16 -0
- data/lib/termtter/system_extensions/termtter_compatibles.rb +19 -0
- data/lib/termtter/system_extensions/windows.rb +86 -0
- data/lib/termtter/system_extensions.rb +8 -121
- data/lib/termtter/task_manager.rb +4 -10
- data/lib/termtter/version.rb +1 -1
- data/lib/termtter.rb +5 -3
- data/spec/plugins/defaults/hashtag_spec.rb +41 -0
- data/spec/plugins/defaults/lists_spec.rb +34 -0
- data/spec/plugins/{english_spec.rb → english_spec_.rb} +0 -0
- data/spec/plugins/{filter_spec.rb → filter_spec_.rb} +0 -0
- data/spec/plugins/gsub_spec.rb +18 -0
- data/spec/plugins/haml_spec.rb +134 -0
- data/spec/plugins/md5pass_spec.rb +13 -0
- data/spec/plugins/{primes_spec.rb → primes_spec_.rb} +0 -0
- data/spec/plugins/{sl_spec.rb → sl_spec_.rb} +0 -0
- data/spec/plugins/standard_commands_spec.rb +1 -1
- data/spec/plugins/storage/{DB_spec.rb → DB_spec_.rb} +0 -0
- data/spec/plugins/storage/{status_spec.rb → status_spec_.rb} +0 -0
- data/spec/plugins/truncate_spec.rb +27 -0
- data/spec/plugins/whois_spec_.rb +20 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/termtter/active_rubytter_spec.rb +17 -0
- data/spec/termtter/api_spec.rb +107 -0
- data/spec/termtter/client_spec.rb +262 -73
- data/spec/termtter/command_spec.rb +31 -5
- data/spec/termtter/config_setup_spec.rb +19 -0
- data/spec/termtter/config_spec.rb +57 -27
- data/spec/termtter/hook_spec.rb +12 -0
- data/spec/termtter/hookable_spec.rb +53 -0
- data/spec/termtter/optparse_spec.rb +64 -9
- data/spec/termtter/rubytter_proxy_spec.rb +42 -0
- data/spec/termtter/system_extensions/windows_spec.rb +9 -0
- data/spec/termtter/system_extensions_spec.rb +61 -0
- data/spec/termtter/task_manager_spec.rb +58 -0
- data/spec/termtter_spec.rb +11 -0
- metadata +45 -20
- data/lib/termtter/connection.rb +0 -41
- data/spec/plugins/whois_spec.rb +0 -26
@@ -0,0 +1,50 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module Termtter::Client
|
3
|
+
|
4
|
+
class << self
|
5
|
+
def get_friends(user_name, max)
|
6
|
+
friends = []
|
7
|
+
page = 0
|
8
|
+
begin
|
9
|
+
friends += tmp = Termtter::API::twitter.friends(user_name,
|
10
|
+
:page => page += 1)
|
11
|
+
puts "#{friends.length}/#{max}"
|
12
|
+
rescue
|
13
|
+
end until (tmp.empty? or friends.length > max)
|
14
|
+
friends.take(max)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
register_command(
|
19
|
+
:name => :friends, :aliases => [:following],
|
20
|
+
:exec_proc => lambda {|arg|
|
21
|
+
user_name = arg.empty? ? config.user_name : arg
|
22
|
+
public_storage[:friends] = friends = get_friends(user_name, 2000)
|
23
|
+
puts friends.map(&:screen_name).join(' ')
|
24
|
+
},
|
25
|
+
:help => ["friends,following [USERNAME]", "Show user's friends."]
|
26
|
+
)
|
27
|
+
|
28
|
+
register_command(
|
29
|
+
:name => :diff_follow, :aliases => [:diff],
|
30
|
+
:exec_proc => lambda {|arg|
|
31
|
+
user_name = arg.empty? ? config.user_name : arg
|
32
|
+
friends = public_storage[:friends]
|
33
|
+
followers = public_storage[:followers]
|
34
|
+
if friends.nil? || followers.nil?
|
35
|
+
puts 'Do followers and friends first.'
|
36
|
+
return
|
37
|
+
end
|
38
|
+
friends = friends.map(&:screen_name)
|
39
|
+
followers = followers.map(&:screen_name)
|
40
|
+
puts "friends - followers:"
|
41
|
+
puts (friends - followers).map{|s|"http://#{config.host}/#{s}"}.join("\n")
|
42
|
+
puts
|
43
|
+
puts "followers - friends:"
|
44
|
+
puts (followers - friends).map{|s|"http://#{config.host}/#{s}"}.join("\n")
|
45
|
+
},
|
46
|
+
:help => ["diff_follow,diff",
|
47
|
+
"Show difference between frineds and followers."]
|
48
|
+
)
|
49
|
+
|
50
|
+
end
|
data/lib/plugins/g.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module Termtter::Client
|
2
|
+
begin
|
3
|
+
require 'g'
|
4
|
+
register_command(
|
5
|
+
:name => :g,
|
6
|
+
:help => ['g obj', "Do you know 'g'? It's like 'p'."],
|
7
|
+
:exec_proc => lambda {|arg|
|
8
|
+
# we get arg as String, so without eval() it is not very useful
|
9
|
+
# but we shouldn't blindly eval user-supplied string like this, either
|
10
|
+
g eval(arg)
|
11
|
+
}
|
12
|
+
)
|
13
|
+
rescue e
|
14
|
+
handle_error(e)
|
15
|
+
end
|
16
|
+
end
|
data/lib/plugins/gsub.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
config.plugins.gsub.set_default(:table, [
|
4
|
+
[/([★☆△▽…□♪♬])(?=\S)/, '\1 '],
|
5
|
+
[/(?=\S)(https?:\/\/)/, ' \1'],
|
6
|
+
])
|
7
|
+
|
8
|
+
Termtter::Client.register_hook(
|
9
|
+
:name => :gsub,
|
10
|
+
:point => :filter_for_output,
|
11
|
+
:exec => lambda {|statuses, event|
|
12
|
+
statuses.each do |s|
|
13
|
+
t = s.text
|
14
|
+
config.plugins.gsub.table.each {|a, b| t.gsub!(a, b || '') }
|
15
|
+
end
|
16
|
+
}
|
17
|
+
)
|
data/lib/plugins/haml.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'haml'
|
4
|
+
require 'tempfile'
|
5
|
+
|
6
|
+
module Termtter::Plugins
|
7
|
+
class Haml
|
8
|
+
def initialize(config = Termtter::Config.instance, logger = Termtter::Client.logger)
|
9
|
+
@config, @logger = config, logger
|
10
|
+
|
11
|
+
plugin_config.set_default :options, {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def plugin_config
|
15
|
+
@config.plugins.haml
|
16
|
+
end
|
17
|
+
|
18
|
+
def run(arg)
|
19
|
+
begin
|
20
|
+
hamlified = haml(arg)
|
21
|
+
rescue => e
|
22
|
+
@logger.error e
|
23
|
+
return
|
24
|
+
end
|
25
|
+
|
26
|
+
return if hamlified.nil? || hamlified.empty?
|
27
|
+
|
28
|
+
Termtter::API.twitter.update(hamlified)
|
29
|
+
puts "=> #{hamlified}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def haml(format)
|
33
|
+
return unless input = editor(:haml)
|
34
|
+
|
35
|
+
opts = plugin_config.options.merge(format.empty? ? {} : {:format => format.to_sym})
|
36
|
+
::Haml::Engine.new(input, opts).render.chomp
|
37
|
+
end
|
38
|
+
|
39
|
+
def editor(extname)
|
40
|
+
unless cmd = ENV['VISUAL'] || ENV['EDITOR']
|
41
|
+
raise 'Please set VISUAL or EDITOR variable.'
|
42
|
+
end
|
43
|
+
|
44
|
+
# XXX: works only in Ruby 1.8.7 or later
|
45
|
+
Tempfile.open(['tmp', ".#{extname}"]) do |f|
|
46
|
+
system cmd, f.path
|
47
|
+
return f.read
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
Termtter::Client.register_command(:haml) do |arg|
|
54
|
+
Termtter::Plugins::Haml.new.run(arg)
|
55
|
+
end
|
@@ -32,12 +32,12 @@ module Termtter::Client
|
|
32
32
|
auth.authorize(req)
|
33
33
|
title = nil
|
34
34
|
tinyurl = nil
|
35
|
-
|
35
|
+
Net::HTTP.start('b.hatena.ne.jp', 80) do |http|
|
36
36
|
res = http.request(req)
|
37
37
|
title = Nokogiri::XML(res.body).search('link[title]').first['title'] rescue nil
|
38
38
|
end
|
39
39
|
if title
|
40
|
-
|
40
|
+
Net::HTTP.start('tinyurl.com', 80) do |http|
|
41
41
|
tinyurl = http.get('/api-create.php?url=' + URI.escape(url)).body
|
42
42
|
end
|
43
43
|
|
data/lib/plugins/history.rb
CHANGED
@@ -21,6 +21,15 @@ module Termtter::Client
|
|
21
21
|
if File.exist?(filename)
|
22
22
|
begin
|
23
23
|
history = Marshal.load Zlib::Inflate.inflate(File.read(filename))
|
24
|
+
rescue Zlib::BufError => e
|
25
|
+
ui = create_highline
|
26
|
+
delete = ui.ask("Unable to read #{filename}. Do you wish to remove it?")
|
27
|
+
if delete =~ /^y/i
|
28
|
+
if File.delete(filename) > 1
|
29
|
+
puts "Removed #{filename}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
history = nil
|
24
33
|
end
|
25
34
|
if history
|
26
35
|
keys.each do |key|
|
data/lib/plugins/irc_gw.rb
CHANGED
@@ -8,7 +8,7 @@ config.plugins.irc_gw.set_default(:logger_level, Logger::ERROR)
|
|
8
8
|
|
9
9
|
module Termtter::Client
|
10
10
|
class << self
|
11
|
-
def
|
11
|
+
def following_friends
|
12
12
|
user_name = config.user_name
|
13
13
|
|
14
14
|
frinends = []
|
@@ -92,8 +92,15 @@ class TermtterIrcGateway < Net::IRC::Server::Session
|
|
92
92
|
|
93
93
|
def on_privmsg(m)
|
94
94
|
target, message = *m.params
|
95
|
-
|
96
|
-
|
95
|
+
if message =~ / +\//
|
96
|
+
termtter_command = message.gsub(/ +\//, '')
|
97
|
+
return if Termtter::Client.find_commands(termtter_command).empty?
|
98
|
+
post '#termtter', NOTICE, main_channel, '> ' + termtter_command
|
99
|
+
Termtter::Client.call_commands(termtter_command)
|
100
|
+
else
|
101
|
+
Termtter::Client.call_commands('update ' + message)
|
102
|
+
post @prefix, TOPIC, main_channel, message
|
103
|
+
end
|
97
104
|
rescue Exception => e
|
98
105
|
post '#termtter', NOTICE, main_channel, "#{e.class.to_s}: #{e.message}"
|
99
106
|
Termtter::Client.handle_error(e)
|
@@ -108,7 +115,7 @@ class TermtterIrcGateway < Net::IRC::Server::Session
|
|
108
115
|
def check_friends
|
109
116
|
params = []
|
110
117
|
max_params_count = 3
|
111
|
-
Termtter::Client.
|
118
|
+
Termtter::Client.following_friends.each do |name|
|
112
119
|
prefix = Prefix.new("#{name}!#{name}@localhost")
|
113
120
|
post prefix, JOIN, main_channel
|
114
121
|
params << prefix.nick
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
config.plugins.linefeed.set_default(:width, 50)
|
3
|
+
config.plugins.linefeed.set_default(:right, 10)
|
4
|
+
|
5
|
+
Termtter::Client.register_hook(
|
6
|
+
:name => :linefeed,
|
7
|
+
:point => :filter_for_output,
|
8
|
+
:exec => lambda {|statuses, event|
|
9
|
+
width = config.plugins.linefeed.width
|
10
|
+
right = config.plugins.linefeed.right
|
11
|
+
statuses.each do |s|
|
12
|
+
t = s.text
|
13
|
+
ocs = []
|
14
|
+
sz = nil
|
15
|
+
t.gsub!(%r{(https?://)}, "\n\\1")
|
16
|
+
t.split("\n").each do |line|
|
17
|
+
cs = line.unpack 'U*'
|
18
|
+
while cs.size > 0
|
19
|
+
sz = 0
|
20
|
+
l = cs.take_while{|c| sz += c < 0x100 ? 1 : 2; sz < width}
|
21
|
+
ocs += l
|
22
|
+
cs = cs.drop(l.size)
|
23
|
+
ocs += [0x0a]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
t2 = ocs.pack('U*')
|
27
|
+
t2.chop! if sz < (width - right)
|
28
|
+
s.text[0, t.size] = t2
|
29
|
+
end
|
30
|
+
}
|
31
|
+
)
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'digest/md5'
|
3
|
+
require 'base64'
|
4
|
+
|
5
|
+
config.plugins.md5pass.set_default(:salt, 'salt')
|
6
|
+
config.plugins.md5pass.set_default(:len, 12)
|
7
|
+
config.plugins.md5pass.set_default(:times, 10)
|
8
|
+
|
9
|
+
module Termtter::Client
|
10
|
+
|
11
|
+
def self.gen_pass(master_pass)
|
12
|
+
salt = config.plugins.md5pass.salt
|
13
|
+
len = config.plugins.md5pass.len
|
14
|
+
times = config.plugins.md5pass.times
|
15
|
+
url = "http://#{config.host}/"
|
16
|
+
user = config.user_name
|
17
|
+
str = (url + salt + user + master_pass) * (2 ** times);
|
18
|
+
Base64.encode64(Digest::MD5.digest(str))[0, len]
|
19
|
+
end
|
20
|
+
|
21
|
+
hl = create_highline
|
22
|
+
mp = hl.ask('your master password for md5pass: ') { |q| q.echo = false }
|
23
|
+
config.password = gen_pass(mp)
|
24
|
+
|
25
|
+
register_command(
|
26
|
+
:name => :show_md5pass,
|
27
|
+
:exec_proc => lambda {|arg| puts "=> #{gen_pass(arg)}" },
|
28
|
+
:help => ["show_md5pass MASTER_PASSWORD", "Show your md5 password."]
|
29
|
+
)
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
# config example:
|
34
|
+
# config.system.load_plugins = 'md5pass'
|
35
|
+
# config.plugins.md5pass.salt = 'set_random_string'
|
36
|
+
#
|
37
|
+
# 1. Decide your master password and salt.
|
38
|
+
# 2. Configure. (see above setting)
|
39
|
+
# 3. Start termtter.
|
40
|
+
# 4. Check your generated password using 'show_md5pass MASTER_PASSWORD'
|
41
|
+
# 5. Change your Twitter password to it.
|
42
|
+
# 6. Restart termtter.
|
data/lib/plugins/outputz.rb
CHANGED
@@ -13,7 +13,7 @@ module Termtter::Client
|
|
13
13
|
:points => [:pre_exec_update],
|
14
14
|
:exec_proc => lambda {|cmd, arg|
|
15
15
|
Thread.new do
|
16
|
-
|
16
|
+
Net::HTTP.start('outputz.com', 80) do |http|
|
17
17
|
key = CGI.escape key
|
18
18
|
uri = CGI.escape config.plugins.outputz.uri
|
19
19
|
size = arg.split(//).size
|
data/lib/plugins/primes.rb
CHANGED
@@ -0,0 +1,43 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
config.plugins.quote.set_default(:format, '<%= comment %>QT @<%=s.user.screen_name%>: <%=s.text%>')
|
4
|
+
config.plugins.quote.set_default(:confirm_protected, true)
|
5
|
+
|
6
|
+
module Termtter::Client
|
7
|
+
def self.post_quote(s, comment = nil)
|
8
|
+
if s.user.protected && config.plugins.quote.confirm_protected &&
|
9
|
+
!confirm("#{s.user.screen_name} is protected! Are you sure?", false)
|
10
|
+
return
|
11
|
+
end
|
12
|
+
|
13
|
+
comment += ' ' unless comment.nil?
|
14
|
+
text = ERB.new(config.plugins.quote.format).result(binding)
|
15
|
+
Termtter::API.twitter.update(text)
|
16
|
+
puts "=> #{text}"
|
17
|
+
|
18
|
+
return text
|
19
|
+
end
|
20
|
+
|
21
|
+
register_command(
|
22
|
+
:name => :quote,
|
23
|
+
:aliases => [:qt],
|
24
|
+
:help => ['quote,qt (ID|@USER)', 'Post a quote message'],
|
25
|
+
:exec_proc => lambda {|arg|
|
26
|
+
arg, comment = arg.split(/\s/, 2)
|
27
|
+
|
28
|
+
if public_storage[:typable_id] && s = typable_id_status(arg)
|
29
|
+
post_quote(s, comment)
|
30
|
+
else
|
31
|
+
case arg
|
32
|
+
when /(\d+)/
|
33
|
+
post_quote(Termtter::API.twitter.show(arg), comment)
|
34
|
+
when /@([A-Za-z0-9_]+)/
|
35
|
+
user = $1
|
36
|
+
statuses = Termtter::API.twitter.user_timeline(user)
|
37
|
+
return if statuses.empty?
|
38
|
+
post_quote(statuses[0], comment)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
}
|
42
|
+
)
|
43
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module Termtter::Client
|
3
|
+
@last_screen_name = nil
|
4
|
+
@last_source = nil
|
5
|
+
@last_time = nil
|
6
|
+
|
7
|
+
register_hook(
|
8
|
+
:name => :reduce_screenname,
|
9
|
+
:point => :prepare_screenname,
|
10
|
+
:exec => lambda {|n, event|
|
11
|
+
@last_screen_name == n ? '' : @last_screen_name = n
|
12
|
+
}
|
13
|
+
)
|
14
|
+
|
15
|
+
register_hook(
|
16
|
+
:name => :reduce_source,
|
17
|
+
:point => :prepare_source,
|
18
|
+
:exec => lambda {|n, event| @last_source == n ? '' : @last_source = n }
|
19
|
+
)
|
20
|
+
|
21
|
+
register_hook(
|
22
|
+
:name => :reduce_time,
|
23
|
+
:point => :prepare_time,
|
24
|
+
:exec => lambda {|n, event| @last_time == n ? '' : @last_time = n }
|
25
|
+
)
|
26
|
+
end
|
data/lib/plugins/reverse.rb
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
Termtter::Client.register_hook(
|
4
|
+
:name => :reverse,
|
5
|
+
:point => :filter_for_output,
|
6
|
+
:exec => lambda {|statuses, event|
|
7
|
+
statuses.each do |s|
|
6
8
|
s.text = s.text.split(//).reverse.to_s
|
7
|
-
s
|
8
9
|
end
|
9
|
-
|
10
|
-
|
10
|
+
}
|
11
|
+
)
|
11
12
|
|
12
13
|
# filter-reverse.rb
|
13
14
|
# reverse texts
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
def __dir__
|
3
|
+
File.dirname(File.expand_path(__FILE__))
|
4
|
+
end
|
5
|
+
|
6
|
+
def let(o)
|
7
|
+
yield o
|
8
|
+
end
|
9
|
+
|
10
|
+
def source(pluginname)
|
11
|
+
File.read(
|
12
|
+
let(
|
13
|
+
Pathname(__dir__) + "#{pluginname}.rb") {|a|
|
14
|
+
File.exist?(a) ? a : Pathname(__dir__) + "defaults/#{pluginname}.rb" })
|
15
|
+
end
|
16
|
+
|
17
|
+
def truncate(s)
|
18
|
+
s.each_char.take(140).join
|
19
|
+
end
|
20
|
+
|
21
|
+
module Termtter::Client
|
22
|
+
register_command(:source, :help => ["source {plugin-name}", "shows the source code of the plugin"]) do |arg|
|
23
|
+
puts source(arg)
|
24
|
+
end
|
25
|
+
|
26
|
+
register_command(:sourceyou, :help => ["sourceyou @username {plugin-name}", "gives the source code of the plugin"]) do |arg|
|
27
|
+
/(\w+)\s(\w+)/ =~ arg
|
28
|
+
text = truncate("@#{normalize_as_user_name($1)} #{source($2)}")
|
29
|
+
Termtter::API.twitter.update(text)
|
30
|
+
end
|
31
|
+
end
|
@@ -37,7 +37,7 @@ module Termtter::Storage
|
|
37
37
|
}
|
38
38
|
}
|
39
39
|
end
|
40
|
-
Rubytter.
|
40
|
+
Rubytter.structize(result)
|
41
41
|
end
|
42
42
|
|
43
43
|
def self.search_user(query)
|
@@ -60,7 +60,7 @@ module Termtter::Storage
|
|
60
60
|
}
|
61
61
|
}
|
62
62
|
end
|
63
|
-
Rubytter.
|
63
|
+
Rubytter.structize(result)
|
64
64
|
end
|
65
65
|
|
66
66
|
def self.insert(data)
|
data/lib/plugins/storage.rb
CHANGED
@@ -44,7 +44,7 @@ module Termtter::Client
|
|
44
44
|
:aliases => [:ssu],
|
45
45
|
:exec_proc => lambda {|arg|
|
46
46
|
unless arg.strip.empty?
|
47
|
-
key = arg.strip
|
47
|
+
key = arg.strip.gsub(/^@/, '')
|
48
48
|
statuses = Termtter::Storage::Status.search_user({:user => key})
|
49
49
|
output(statuses, :search)
|
50
50
|
end
|
@@ -0,0 +1,192 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'tweetstream'
|
4
|
+
require File.dirname(__FILE__) + '/../termtter/active_rubytter'
|
5
|
+
|
6
|
+
config.plugins.stream.set_default :max_following, 400
|
7
|
+
config.plugins.stream.set_default :timeline_format, '<yellow>[S]</yellow> $orig'
|
8
|
+
config.plugins.stream.set_default :retry_wait_base, 60
|
9
|
+
config.plugins.stream.set_default :retry_wait_max, 3600
|
10
|
+
|
11
|
+
module Termtter::Client
|
12
|
+
|
13
|
+
config.plugins.stream.keywords = []
|
14
|
+
|
15
|
+
class << self
|
16
|
+
if defined?(DB)
|
17
|
+
def friends(max)
|
18
|
+
Status.group(:user_id).
|
19
|
+
select(:user_id, :screen_name).
|
20
|
+
join(:users, :id => :user_id).
|
21
|
+
order(:COUNT.sql_function.desc).take(max)
|
22
|
+
end
|
23
|
+
else
|
24
|
+
def friends(max)
|
25
|
+
friends = []
|
26
|
+
page = 0
|
27
|
+
begin
|
28
|
+
friends += tmp = Termtter::API::twitter.friends(config.user_name, :page => page+=1)
|
29
|
+
p friends.length
|
30
|
+
rescue
|
31
|
+
end until (tmp.empty? or friends.length > max)
|
32
|
+
friends.take(max)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def swap_timeline_format(format)
|
37
|
+
original = config.plugins.stdout.timeline_format
|
38
|
+
if /\$orig/ =~ format
|
39
|
+
format.gsub!(/\$orig/, original)
|
40
|
+
end
|
41
|
+
config.plugins.stdout.timeline_format = format
|
42
|
+
yield
|
43
|
+
config.plugins.stdout.timeline_format = original
|
44
|
+
end
|
45
|
+
|
46
|
+
def kill_thread(name)
|
47
|
+
config.plugins.stream.__send__(name).kill rescue nil
|
48
|
+
config.plugins.stream.__assign__(name, nil)
|
49
|
+
end
|
50
|
+
def alive_thread?(name)
|
51
|
+
config.plugins.stream.__send__(name).alive? rescue false
|
52
|
+
end
|
53
|
+
private :kill_thread
|
54
|
+
private :alive_thread?
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
help = ['keyword_stream [:stop|:show|:add|:delete] [KEYWORDS]',
|
59
|
+
'Tracking keyword using Stream API']
|
60
|
+
register_command(:keyword_stream, :help => help) do |arg|
|
61
|
+
catch(:exit) do
|
62
|
+
throw :exit if arg.empty?
|
63
|
+
args = arg.split /[, ]/
|
64
|
+
case args[0]
|
65
|
+
when ':stop'
|
66
|
+
kill_thread :keyword_stream if alive_thread? :keywor_stream
|
67
|
+
config.plugins.stream.keywords.clear
|
68
|
+
puts 'keyword_stream has stopped'
|
69
|
+
throw :exit
|
70
|
+
when ':show'
|
71
|
+
puts alive_thread?(:keyword_stream) ? 'streaming alive' : 'not alive'
|
72
|
+
unless config.plugins.stream.keywords.empty?
|
73
|
+
puts config.plugins.stream.keywords.join(', ')
|
74
|
+
end
|
75
|
+
throw :exit
|
76
|
+
when ':add'
|
77
|
+
args.shift
|
78
|
+
config.plugins.stream.keywords |= args
|
79
|
+
when ':delete'
|
80
|
+
args.shift
|
81
|
+
config.plugins.stream.keywords -= args
|
82
|
+
if config.plugins.stream.keywords.empty?
|
83
|
+
kill_thread :keyword_stream if alive_thread? :keywor_stream
|
84
|
+
puts 'keyword_stream has stopped'
|
85
|
+
throw :exit
|
86
|
+
end
|
87
|
+
when ':start'
|
88
|
+
when /^:.*/
|
89
|
+
puts "Unknown keyword_stream options"
|
90
|
+
throw :exit
|
91
|
+
else
|
92
|
+
config.plugins.stream.keywords = args
|
93
|
+
end
|
94
|
+
|
95
|
+
kill_thread :keyword_stream if alive_thread? :keywor_stream
|
96
|
+
|
97
|
+
keywords = config.plugins.stream.keywords
|
98
|
+
|
99
|
+
puts "streaming: #{keywords.join(', ')}"
|
100
|
+
config.plugins.stream.keyword_stream = Thread.new do
|
101
|
+
retry_wait = config.plugins.stream.retry_wait_base,
|
102
|
+
begin
|
103
|
+
TweetStream::Client.new(config.user_name, config.password).
|
104
|
+
filter(:track => keywords) do |status|
|
105
|
+
print "\e[0G" + "\e[K" unless win?
|
106
|
+
swap_timeline_format(config.plugins.stream.timeline_format) do
|
107
|
+
output [Termtter::ActiveRubytter.new(status)],
|
108
|
+
:update_friends_timeline
|
109
|
+
end
|
110
|
+
Readline.refresh_line
|
111
|
+
end
|
112
|
+
rescue
|
113
|
+
puts "stream is down"
|
114
|
+
puts "wait #{config.plugins.stream.retry_wait}sec"
|
115
|
+
sleep retry_wait
|
116
|
+
retry_wait = retry_wait * 2;
|
117
|
+
retry_wait = config.plugin.stream.retry_max unless
|
118
|
+
retry_max > config.plugin.stream.retry_max
|
119
|
+
retry
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
at_exit do
|
125
|
+
kill_thread :keyword_stream
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
help = ['hash_stream HASHTAG', 'Tracking hashtag using Stream API']
|
130
|
+
register_command(:hash_stream, :help => help) do |arg|
|
131
|
+
arg = "##{arg}" unless /^#/ =~ arg
|
132
|
+
call_commands("keyword_stream #{arg}")
|
133
|
+
end
|
134
|
+
|
135
|
+
help = ['stream USERNAME', 'Tracking users using Stream API']
|
136
|
+
register_command(:stream, :help => help) do |arg|
|
137
|
+
catch(:exit) do
|
138
|
+
args = arg.split
|
139
|
+
|
140
|
+
case args[0]
|
141
|
+
when ':stop'
|
142
|
+
kill_thread :thread
|
143
|
+
puts 'stream is down'
|
144
|
+
throw :exit
|
145
|
+
end
|
146
|
+
|
147
|
+
if config.plugins.stream.thread.class == Thread
|
148
|
+
puts 'already streaming'
|
149
|
+
throw :exit
|
150
|
+
end
|
151
|
+
|
152
|
+
targets = args.map { |name|
|
153
|
+
Termtter::API.twitter.user(name).id rescue nil
|
154
|
+
}
|
155
|
+
|
156
|
+
max = config.plugins.stream.max_following
|
157
|
+
unless targets and targets.length > 0
|
158
|
+
keys = [:user_id, :"`user_id`", :id, :"`id`"]
|
159
|
+
targets = friends(max).map{ |u|
|
160
|
+
keys.map{ |k| u[k] rescue nil}.compact.first
|
161
|
+
}.compact
|
162
|
+
end
|
163
|
+
|
164
|
+
config.plugins.stream.thread = Thread.new do
|
165
|
+
begin
|
166
|
+
current_targets = targets.take(max)
|
167
|
+
targets = targets.take(max)
|
168
|
+
message = "streaming #{current_targets.length} friend"
|
169
|
+
message << (current_targets.size == 1 ? '.' : 's.')
|
170
|
+
puts message
|
171
|
+
TweetStream::Client.new(config.user_name, config.password).
|
172
|
+
filter(:follow => current_targets) do |status|
|
173
|
+
print "\e[0G" + "\e[K" unless win?
|
174
|
+
swap_timeline_format(config.plugins.stream.timeline_format) do
|
175
|
+
output [Termtter::ActiveRubytter.new(status)], :update_friends_timeline
|
176
|
+
end
|
177
|
+
Readline.refresh_line
|
178
|
+
end
|
179
|
+
rescue(NoMethodError) => e # #<NoMethodError: private method `split' called for nil:NilClass>
|
180
|
+
puts "stream seems broken (#{e.inspect})."
|
181
|
+
max -= 10 if max > 10
|
182
|
+
retry
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
at_exit do
|
187
|
+
kill_thread :stream
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
data/lib/plugins/switch_user.rb
CHANGED
@@ -1,22 +1 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
module Termtter::Client
|
4
|
-
register_command(
|
5
|
-
:name => :switch_user,
|
6
|
-
:exec_proc => lambda {|arg|
|
7
|
-
Termtter::API.switch_user(arg)
|
8
|
-
},
|
9
|
-
:completion_proc => lambda {|cmd, arg|
|
10
|
-
# TODO
|
11
|
-
},
|
12
|
-
:help => ["switch_user USERNAME", "Switch twitter account."]
|
13
|
-
)
|
14
|
-
|
15
|
-
register_command(
|
16
|
-
:name => :restore_user,
|
17
|
-
:exec_proc => lambda {|arg|
|
18
|
-
Termtter::API.restore_user
|
19
|
-
},
|
20
|
-
:help => ["restore_user", "Restore default twitter account."]
|
21
|
-
)
|
22
|
-
end
|
1
|
+
puts 'Plugin "switch_user" was obsoleted, and use plugin "switch" that is loaded as default.'
|