termtter 1.0.7 → 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -26,7 +26,7 @@ Gem::Specification.new do |s|
26
26
  s.add_dependency("json_pure", ">= 1.1.3")
27
27
  s.add_dependency("highline", ">= 1.5.0")
28
28
  s.add_dependency("termcolor", ">= 0.3.1")
29
- s.add_dependency("rubytter", ">= 0.6.5")
29
+ s.add_dependency("rubytter", ">= 0.6.4")
30
30
  s.authors = %w(jugyo ujihisa)
31
31
  s.email = 'jugyo.org@gmail.com'
32
32
  s.homepage = 'http://wiki.github.com/jugyo/termtter'
@@ -0,0 +1,47 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Termtter::Client
3
+ class << self
4
+ def delete_command(arg)
5
+ if @commands.delete(arg.to_sym)
6
+ puts "#{arg} command is deleted."
7
+ else
8
+ raise "#{arg} command is not found."
9
+ end
10
+ end
11
+
12
+ def alias_command(arg)
13
+ original, new = arg.split(/\s+/)
14
+ if @commands[original.to_sym]
15
+ @commands[new.to_sym] = @commands[original.to_sym].clone
16
+ @commands[new.to_sym].name = new.to_sym
17
+ @commands[new.to_sym].aliases = []
18
+ @commands[new.to_sym].help = ''
19
+ puts "alias '#{original}' to '#{new}'."
20
+ else
21
+ raise "#{original} command is not found."
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ module Termtter::Client
28
+ register_command(
29
+ :name => :delete_command,
30
+ :exec_proc => lambda {|arg|
31
+ Termtter::Client.delete_command(arg)
32
+ },
33
+ :completion_proc => lambda {|cmd, arg|
34
+ },
35
+ :help => ['delete_command command', 'delete command from command list (this command is experimental!)']
36
+ )
37
+
38
+ register_command(
39
+ :name => :alias_command,
40
+ :exec_proc => lambda {|arg|
41
+ Termtter::Client.alias_command(arg)
42
+ },
43
+ :completion_proc => lambda {|cmd, arg|
44
+ },
45
+ :help => ['alias_command A B', 'alias command A to B (this command is experimental!)']
46
+ )
47
+ end
@@ -1,12 +1,33 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
+ config.plugins.confirm.set_default(:commands, [:update, :reply, :direct])
4
+ config.plugins.confirm.set_default(
5
+ :conditions,
6
+ [
7
+ lambda { |cmd_name, arg|
8
+ if cmd_name == :direct && arg =~ /^(list|sent_list)$/
9
+ false
10
+ else
11
+ true
12
+ end
13
+ }
14
+ ]
15
+ )
16
+
3
17
  Termtter::Client.register_hook(
4
18
  :name => :confirm,
5
- :points => [:pre_exec_update],
19
+ :points => [/^pre_exec_/],
6
20
  :exec_proc => lambda {|cmd, arg|
7
- if /^y?$/i !~ Readline.readline("update? #{arg} [Y/n] ", false)
8
- puts 'canceled.'
9
- raise Termtter::CommandCanceled
21
+ if config.plugins.confirm.commands.include?(cmd.name) &&
22
+ config.plugins.confirm.conditions.any? { |cond| cond.call(cmd.name, arg) }
23
+
24
+ prompt = "\"#{cmd.name} #{arg}".strip + "\" [Y/n] "
25
+
26
+ if /^y?$/i !~ Readline.readline(prompt, false)
27
+ puts 'canceled.'
28
+ raise Termtter::CommandCanceled
29
+ end
30
+
10
31
  end
11
32
  }
12
33
  )
@@ -0,0 +1,23 @@
1
+ module Termtter::Client
2
+ register_command(
3
+ :name => :countter,
4
+ :exec_proc => lambda {|arg|
5
+ count = {}
6
+ public_storage[:log].each do |l|
7
+ source = l.source =~ /(?:<a href=\".+?\">)(.+)(?:<\/a>)/ ? $1 : l.source
8
+ count[source] = 0 unless count[source]
9
+ count[source] += 1
10
+ end
11
+
12
+ format = "%24s %6s"
13
+ puts format % %w(sources count)
14
+ puts format % ['-'*24, '-'*6]
15
+ count.to_a.sort{|a,b|b[1]<=>a[1]}.each do |k,v|
16
+ puts format % [k, v]
17
+ end
18
+ },
19
+ :completion_proc => lambda {|cmd, arg|
20
+ },
21
+ :help => ['countter', 'count sources']
22
+ )
23
+ end
data/lib/plugins/devel.rb CHANGED
@@ -1,5 +1,10 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
+ begin
4
+ require 'ruby-debug'
5
+ rescue LoadError
6
+ end
7
+
3
8
  module Termtter::Client
4
9
  register_command(
5
10
  :name => :eval,
@@ -0,0 +1,36 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Termtter::Client
3
+ register_command(
4
+ :name => :direct_messages,
5
+ :aliases => [:ds],
6
+ :exec_proc => lambda {|arg|
7
+ event = :list_user_timeline
8
+ ds = Termtter::API.twitter.direct_messages
9
+ DM = Struct.new :id, :text, :user, :created_at, :in_reply_to_status_id
10
+ statuses = ds.map do |d|
11
+ DM.new(d.id, d.text, d.sender, d.created_at)
12
+ end
13
+ output(statuses, event)
14
+ },
15
+ :completion_proc => lambda {|cmd, arg|
16
+ },
17
+ :help => ['direct_messages,ds', 'List direct messages for you']
18
+ )
19
+
20
+ register_command(
21
+ :name => :sent_direct_messages,
22
+ :aliases => [:sds],
23
+ :exec_proc => lambda {|arg|
24
+ event = :list_user_timeline
25
+ ds = Termtter::API.twitter.sent_direct_messages
26
+ DM = Struct.new :id, :text, :user, :created_at, :in_reply_to_status_id
27
+ statuses = ds.map do |d|
28
+ DM.new(d.id, "@#{d.recipient.screen_name} #{d.text}", d.sender, d.created_at)
29
+ end
30
+ output(statuses, event)
31
+ },
32
+ :completion_proc => lambda {|cmd, arg|
33
+ },
34
+ :help => ['sent_direct_messages, sds', 'List direct messages from you']
35
+ )
36
+ end
data/lib/plugins/erb.rb CHANGED
@@ -4,7 +4,7 @@ require 'erb'
4
4
 
5
5
  Termtter::Client.register_hook(
6
6
  :name => :erb,
7
- :points => [:pre_exec_update],
7
+ :point => :modify_arg_for_update,
8
8
  :exec_proc => lambda {|cmd, arg|
9
9
  ERB.new(arg).result(binding)
10
10
  }
@@ -0,0 +1,17 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Termtter::Client
4
+ register_command(
5
+ :name => :exec,
6
+ :exec_proc => lambda{|arg|
7
+ return unless arg
8
+ begin
9
+ pause
10
+ system *arg.split(/\s+/)
11
+ ensure
12
+ resume
13
+ end
14
+ },
15
+ :help => ['exec SHELL_COMMAND', 'execute a shell command']
16
+ )
17
+ end
@@ -0,0 +1,14 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ Termtter::Client.register_command(
4
+ :name => :exec_and_update,
5
+ :exec_proc => lambda{|arg|
6
+ return unless arg
7
+ `#{arg}`.each_line do |line|
8
+ next if line =~ /^\s*$/
9
+ Termtter::API.twitter.update(line)
10
+ puts "=> #{line}"
11
+ end
12
+ },
13
+ :help => ['exec_and_update COMMAND', 'execute the command']
14
+ )
@@ -0,0 +1,143 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'open-uri'
4
+ require 'uri'
5
+ require 'fileutils'
6
+ require 'cgi'
7
+
8
+ begin
9
+ require 'meow'
10
+ growl = Meow.new('termtter', 'update_friends_timeline')
11
+ rescue LoadError
12
+ growl = nil
13
+ end
14
+
15
+ config.plugins.growl.set_default(:icon_cache_dir, "#{Termtter::CONF_DIR}/tmp/user_profile_images")
16
+ config.plugins.growl.set_default(:growl_user, [])
17
+ config.plugins.growl.set_default(:growl_keyword, [])
18
+ config.plugins.growl.set_default(:priority_veryhigh_user, [])
19
+ config.plugins.growl.set_default(:priority_high_user, [])
20
+ config.plugins.growl.set_default(:priority_normal_user, [])
21
+ config.plugins.growl.set_default(:priority_low_user, [])
22
+ config.plugins.growl.set_default(:priority_verylow_user, [])
23
+ config.plugins.growl.set_default(:priority_veryhigh_keyword, [])
24
+ config.plugins.growl.set_default(:priority_high_keyword, [])
25
+ config.plugins.growl.set_default(:priority_normal_keyword, [])
26
+ config.plugins.growl.set_default(:priority_low_keyword, [])
27
+ config.plugins.growl.set_default(:priority_verylow_keyword, [])
28
+ config.plugins.growl.set_default(:sticky_user, [])
29
+ config.plugins.growl.set_default(:sticky_keyword, [])
30
+ growl_keys = { 'user' => config.plugins.growl.growl_user,
31
+ 'keyword' => Regexp.union(*config.plugins.growl.growl_keyword) }
32
+ priority_keys = { 'user' => [config.plugins.growl.priority_veryhigh_user,
33
+ config.plugins.growl.priority_high_user,
34
+ config.plugins.growl.priority_normal_user,
35
+ config.plugins.growl.priority_low_user,
36
+ config.plugins.growl.priority_verylow_user],
37
+ 'keyword' => [Regexp.union(*config.plugins.growl.priority_veryhigh_keyword),
38
+ Regexp.union(*config.plugins.growl.priority_high_keyword),
39
+ Regexp.union(*config.plugins.growl.priority_normal_keyword),
40
+ Regexp.union(*config.plugins.growl.priority_low_keyword),
41
+ Regexp.union(*config.plugins.growl.priority_verylow_keyword) ] }
42
+ sticky_keys = { 'user' => config.plugins.growl.sticky_user,
43
+ 'keyword' => Regexp.union(*config.plugins.growl.sticky_keyword) }
44
+
45
+ FileUtils.mkdir_p(config.plugins.growl.icon_cache_dir) unless File.exist?(config.plugins.growl.icon_cache_dir)
46
+ Dir.glob("#{config.plugins.growl.icon_cache_dir}/*") {|f| File.delete(f) unless File.size?(f) }
47
+ unless File.exist?("#{config.plugins.growl.icon_cache_dir}/default.png")
48
+ File.open("#{config.plugins.growl.icon_cache_dir}/default.png", "wb") do |f|
49
+ f << open("http://static.twitter.com/images/default_profile_normal.png").read
50
+ end
51
+ end
52
+
53
+ def get_icon_path(s)
54
+ /https?:\/\/.+\/(\d+)\/.*?$/ =~ s.user.profile_image_url
55
+ cache_file = "%s/%s-%s%s" % [ config.plugins.growl.icon_cache_dir,
56
+ s.user.screen_name,
57
+ $+,
58
+ File.extname(s.user.profile_image_url) ]
59
+ unless File.exist?(cache_file)
60
+ Thread.new(s,cache_file) do |s,cache_file|
61
+ Dir.glob("#{config.plugins.growl.icon_cache_dir}/#{s.user.screen_name}-*") {|f| File.delete(f) }
62
+ begin
63
+ s.user.profile_image_url.sub!(/^https/,'http')
64
+ File.open(cache_file, 'wb') do |f|
65
+ f << open(URI.escape(s.user.profile_image_url)).read
66
+ end
67
+ rescue OpenURI::HTTPError
68
+ cache_file = "#{config.plugins.growl.icon_cache_dir}/default.png"
69
+ end
70
+ end
71
+ end
72
+ return cache_file
73
+ end
74
+
75
+ def get_priority(s,priority_keys)
76
+ priority = 2
77
+ 5.times {|n|
78
+ return priority.to_s if priority_keys['user'][n].include?(s.user.screen_name) ||
79
+ priority_keys['keyword'][n] =~ s.text
80
+ priority -= 1
81
+ }
82
+ return '0'
83
+ end
84
+
85
+ def is_growl(s,growl_keys)
86
+ return true if (growl_keys['user'].empty? && growl_keys['keyword'] == /(?!)/) ||
87
+ (growl_keys['user'].include?(s.user.screen_name) || growl_keys['keyword'] =~ s.text)
88
+ return false
89
+ end
90
+
91
+ def is_sticky(s,sticky_keys)
92
+ return true if sticky_keys['user'].include?(s.user.screen_name) || sticky_keys['keyword'] =~ s.text
93
+ return false
94
+ end
95
+
96
+ Termtter::Client.register_hook(
97
+ :name => :growl2,
98
+ :points => [:output],
99
+ :exec_proc => lambda {|statuses, event|
100
+ return unless event == :update_friends_timeline
101
+ Thread.start do
102
+ statuses.each do |s|
103
+ next unless is_growl(s,growl_keys)
104
+ growl_title = s.user.screen_name
105
+ growl_title += " (#{s.user.name})" unless s.user.screen_name == s.user.name
106
+ unless growl
107
+ arg = ['growlnotify', growl_title, '-m', s.text.gsub("\n",''), '-n', 'termtter', '-p', get_priority(s,priority_keys), '--image', get_icon_path(s)]
108
+ arg.push('-s') if is_sticky(s,sticky_keys)
109
+ system *arg
110
+ else
111
+ begin
112
+ icon = Meow.import_image(get_icon_path(s))
113
+ rescue
114
+ icon = Meow.import_image("#{config.plugins.growl.icon_cache_dir}/default.png")
115
+ end
116
+ growl.notify(growl_title, CGI.unescape(CGI.unescapeHTML(s.text)),
117
+ {:icon => icon,
118
+ :priority => get_priority(s,priority_keys),
119
+ :sticky => is_sticky(s,sticky_keys) }) do
120
+ s.text.gsub(URI.regexp) {|uri| system "open #{uri}"}
121
+ end
122
+ end
123
+ sleep 0.1
124
+ end
125
+ end
126
+ }
127
+ )
128
+ #Optional setting example.
129
+ # Growl ON setting.
130
+ # config.plugins.growl.growl_user = ['p2pquake', 'jihou']
131
+ # config.plugins.growl.growl_keyword = ['地震', /^@screen_name/]
132
+ # Priority setting.
133
+ # config.plugins.growl.priority_veryhigh_user = ['veryhigh_user']
134
+ # config.plugins.growl.priority_veryhigh_keyword = ['veryhigh_keyword', /^@screen_name']
135
+ # config.plugins.growl.priority_high_user = ['high_user']
136
+ # config.plugins.growl.priority_high_keyword = ['high_keyword']
137
+ # config.plugins.growl.priority_low_user = ['low_user']
138
+ # config.plugins.growl.priority_low_keyword = ['low_keyword']
139
+ # config.plugins.growl.priority_verylow_user = ['verylow_user']
140
+ # config.plugins.growl.priority_verylow_keyword = ['verylow_keyword']
141
+ # Sticky setting.
142
+ # config.plugins.growl.sticky_user = ['screen_name']
143
+ # config.plugins.growl.sticky_keyword = [/^@screen_name/, '#termtter']
@@ -43,10 +43,10 @@ module Termtter::Client
43
43
  },
44
44
  :completion_proc => lambda {|cmd, args|
45
45
  if args =~ /^(\d*)$/
46
- find_status_id_candidates $1, "#{cmd} %s"
46
+ find_status_ids($1){|id| "#{cmd} #{id}"}
47
47
  end
48
48
  },
49
- :help => ['hatebu ID', 'Hatena bookmark a status']
49
+ :help => ['hatebu ID', 'Hatena bookmark a status']
50
50
  )
51
51
  end
52
52
 
@@ -0,0 +1,58 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'rubygems'
4
+ require 'atomutil'
5
+ require 'nokogiri'
6
+
7
+ module Termtter::Client
8
+ register_command(
9
+ :name => :hatebu_and_update, :aliases => [:hau],
10
+ :exec_proc => lambda {|arg|
11
+ url, comment = arg.split(/\s/)
12
+ if url =~ URI.regexp
13
+ auth = auth = Atompub::Auth::Wsse.new({
14
+ :username => config.plugins.hatebu.username,
15
+ :password => config.plugins.hatebu.password,
16
+ })
17
+ link = Atom::Link.new({
18
+ :href => url,
19
+ :rel => 'related',
20
+ :type => 'text/html',
21
+ })
22
+ entry = Atom::Entry.new({
23
+ :link => link,
24
+ :title => 'dummy',
25
+ :summary => comment,
26
+ })
27
+ req = Net::HTTP::Post.new 'http://b.hatena.ne.jp/atom/post'
28
+ req['User-Agent'] = 'Mozilla/5.0'
29
+ req['Content-Type'] = 'application/atom+xml'
30
+ req['Slug'] = 'termtter'
31
+ req.body = entry.to_s
32
+ auth.authorize(req)
33
+ title = nil
34
+ tinyurl = nil
35
+ Termtter::API.connection.start('b.hatena.ne.jp', 80) do |http|
36
+ res = http.request(req)
37
+ title = Nokogiri::XML(res.body).search('link[title]').first['title'] rescue nil
38
+ end
39
+ if title
40
+ Termtter::API.connection.start('tinyurl.com', 80) do |http|
41
+ tinyurl = http.get('/api-create.php?url=' + URI.escape(url)).body
42
+ end
43
+
44
+ Termtter::API.twitter.update("[はてぶ] #{title} #{tinyurl}")
45
+ end
46
+ end
47
+ },
48
+ :help => ['hatebu2 URL', 'Hatena bookmark a URL, and update']
49
+ )
50
+ end
51
+
52
+ # hatebu.rb
53
+ # hatena bookmark it, and post
54
+ #
55
+ # config.plugins.hatebu.username = 'your-username-on-hatena'
56
+ # config.plugins.hatebu.password = 'your-password-on-hatena'
57
+ #
58
+ # hatebu_and_update http://www.yahoo.co.jp/ [yahoo]
data/lib/plugins/l2.rb ADDED
@@ -0,0 +1,25 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Termtter::Client
4
+ register_command(
5
+ :name => :list2,
6
+ :aliases => [:l2],
7
+ :exec_proc => lambda {|arg|
8
+ unless arg.empty?
9
+ targets = arg.split.uniq
10
+ statuses = targets ? targets.map { |target|
11
+ public_storage[:tweet][target]
12
+ }.flatten.uniq.compact.sort_by{ |s| s[:id]} : []
13
+ output(statuses, :search)
14
+ end
15
+ },
16
+ :completion_proc => lambda {|cmd, arg|
17
+ #todo
18
+ },
19
+ :help => ['list2,l2 A B (C..)', "List statuses of A's and B's (and C's..)"]
20
+ )
21
+ end
22
+
23
+ # l2.rb
24
+ # plugin 'l2'
25
+ # NOTE: l2.rb needs plugin/log
@@ -2,23 +2,36 @@
2
2
 
3
3
  require 'fileutils'
4
4
 
5
- # notify-send.rb からコピペ。共通化したいところ。
6
5
  config.plugins.notify_send.set_default(:icon_cache_dir, "#{Termtter::CONF_DIR}/tmp/user_profile_images")
6
+
7
+ FileUtils.mkdir_p(config.plugins.notify_send.icon_cache_dir) unless File.exist?(config.plugins.notify_send.icon_cache_dir)
8
+ Dir.glob("#{config.plugins.notify_send.icon_cache_dir}/*") {|f| File.delete(f) unless File.size?(f) }
9
+ unless File.exist?("#{config.plugins.notify_send.icon_cache_dir}/default.png")
10
+ File.open("#{config.plugins.notify_send.icon_cache_dir}/default.png", "wb") do |f|
11
+ f << open("http://static.twitter.com/images/default_profile_normal.png").read
12
+ end
13
+ end
14
+
7
15
  def get_icon_path(s)
8
- FileUtils.mkdir_p(config.plugins.notify_send.icon_cache_dir) unless File.exist?(config.plugins.notify_send.icon_cache_dir)
9
- cache_file = "%s/%s%s" % [ config.plugins.notify_send.icon_cache_dir,
10
- s.user.screen_name,
11
- File.extname(s.user.profile_image_url) ]
12
- if !File.exist?(cache_file) || (File.atime(cache_file) + 24*60*60) < Time.now
13
- File.open(cache_file, "wb") do |f|
16
+ /https?:\/\/.+\/(\d+)\/.*?$/ =~ s.user.profile_image_url
17
+ cache_file = "%s/%s-%s%s" % [ config.plugins.notify_send.icon_cache_dir,
18
+ s.user.screen_name,
19
+ $+,
20
+ File.extname(s.user.profile_image_url) ]
21
+ unless File.exist?(cache_file)
22
+ Thread.new(s,cache_file) do |s,cache_file|
23
+ Dir.glob("#{config.plugins.notify_send.icon_cache_dir}/#{s.user.screen_name}-*") {|f| File.delete(f) }
14
24
  begin
15
- f << open(URI.escape(s.user.profile_image_url)).read
25
+ s.user.profile_image_url.sub!(/^https/,'http')
26
+ File.open(cache_file, 'wb') do |f|
27
+ f << open(URI.escape(s.user.profile_image_url)).read
28
+ end
16
29
  rescue OpenURI::HTTPError
17
- return nil
30
+ cache_file = "#{config.plugins.notify_send.icon_cache_dir}/default.png"
18
31
  end
19
32
  end
20
33
  end
21
- cache_file
34
+ return cache_file
22
35
  end
23
36
 
24
37
  Termtter::Client.register_hook(
@@ -0,0 +1,45 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'fileutils'
4
+ require 'RMagick'
5
+
6
+ # Copy from notify-send2.rb
7
+ config.plugins.notify_send.set_default(:icon_cache_dir, "#{Termtter::CONF_DIR}/tmp/user_profile_images")
8
+ def get_icon_path(s)
9
+ FileUtils.mkdir_p(config.plugins.notify_send.icon_cache_dir) unless File.exist?(config.plugins.notify_send.icon_cache_dir)
10
+ cache_file = "%s/%s%s" % [ config.plugins.notify_send.icon_cache_dir,
11
+ s.user.screen_name,
12
+ File.extname(s.user.profile_image_url) ]
13
+ if !File.exist?(cache_file) || (File.atime(cache_file) + 24*60*60) < Time.now
14
+ File.open(cache_file, "wb") do |f|
15
+ begin
16
+ image = open(URI.escape(s.user.profile_image_url)).read
17
+ rimage = Magick::Image.from_blob(image).first
18
+ rimage = rimage.resize_to_fill(48, 48)
19
+ f << rimage.to_blob
20
+ rescue OpenURI::HTTPError
21
+ return nil
22
+ end
23
+ end
24
+ end
25
+ cache_file
26
+ end
27
+
28
+ Termtter::Client.register_hook(
29
+ :name => :notify_send3,
30
+ :points => [:output],
31
+ :exec_proc => lambda {|statuses, event|
32
+ return unless event == :update_friends_timeline
33
+ Thread.start do
34
+ statuses.each do |s|
35
+ text = CGI.escapeHTML(s.text)
36
+ text.gsub!(%r{https?://[-_.!~*\'()a-zA-Z0-9;\/?:\@&=+\$,%#]+},'<a href="\0">\0</a>')
37
+ system 'notify-send', s.user.screen_name, text, '-i', get_icon_path(s)
38
+ sleep 0.1
39
+ end
40
+ end
41
+ }
42
+ )
43
+
44
+ # notify-send3.rb
45
+ # caching resized profile image.
@@ -0,0 +1,59 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'uri'
4
+
5
+ module Termtter::Client
6
+ def self.open_uri(uri)
7
+ unless config.plugins.open_url.browser.empty?
8
+ system config.plugins.open_url.browser, uri
9
+ else
10
+ case RUBY_PLATFORM
11
+ when /linux/
12
+ system 'firefox', uri
13
+ when /mswin(?!ce)|mingw|bccwin/
14
+ system 'explorer', uri
15
+ else
16
+ system 'open', uri
17
+ end
18
+ end
19
+ end
20
+
21
+ register_command(
22
+ :name => :open_url,
23
+ :help => ['open_url (TYPABLE|ID|@USER)', 'Open url'],
24
+ :exec_proc => lambda {|arg|
25
+ Thread.new(arg) do |arg|
26
+ if public_storage[:typable_id] && status = typable_id_status(arg)
27
+ status.text.gsub(URI.regexp) {|uri|
28
+ open_uri(uri)
29
+ }
30
+ else
31
+ case arg
32
+ when /^@([A-Za-z0-9_]+)/
33
+ user = $1
34
+ statuses = Termtter::API.twitter.user_timeline(user)
35
+ return if statuses.empty?
36
+ statuses[0].text.gsub(URI.regexp) {|uri| open_uri(uri) }
37
+ when /^\d+/
38
+ Termtter::API.twitter.show(arg).text.gsub(URI.regexp) {|uri| open_uri(uri) }
39
+ end
40
+ end
41
+ end
42
+ },
43
+ :completion_proc => lambda {|cmd, arg|
44
+ if public_storage[:typable_id] && typable_id?(arg)
45
+ "#{cmd} #{typable_id_convert(arg)}"
46
+ else
47
+ case arg
48
+ when /@(.*)/
49
+ find_user_candidates $1, "#{cmd} @%s"
50
+ when /(\d+)/
51
+ find_status_ids(arg).map{|id| "#{cmd} #{$1}"}
52
+ end
53
+ end
54
+ }
55
+ )
56
+ end
57
+
58
+ #Optional Setting
59
+ # config.plugins.open_url.browser = firefox
@@ -16,7 +16,7 @@ module Termtter::Client
16
16
  else
17
17
  status = t.show(id).first
18
18
  end
19
-
19
+
20
20
  Tumblr::API.write(config.plugins.reblog.email, config.plugins.reblog.password) do
21
21
  quote("#{status.text}", "<a href=\"http://twitter.com/#{status.user_screen_name}/status/#{status.id}\">Twitter / #{status.user_name}</a>")
22
22
  end
@@ -24,7 +24,7 @@ module Termtter::Client
24
24
  },
25
25
  :completion_proc => lambda {|cmd, args|
26
26
  if args =~ /^(\d*)$/
27
- find_status_id_candidates $1, "#{cmd} %s"
27
+ find_status_ids($1){|id| "#{cmd} #{id}"}
28
28
  end
29
29
  },
30
30
  :help => ['reblog ID', 'Tumblr Reblog a status']
@@ -0,0 +1,46 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ config.plugins.retweet.set_default(:format, 'RT @<%=s.user.screen_name%>: <%=s.text%>')
4
+
5
+ module Termtter::Client
6
+ def self.post_retweet(s)
7
+ text = ERB.new(config.plugins.retweet.format).result(binding)
8
+ Termtter::API.twitter.update(text)
9
+ puts "=> #{text}"
10
+ end
11
+
12
+ register_command(
13
+ :name => :retweet,
14
+ :aliases => [:rt],
15
+ :help => ['retweet,rt (TYPABLE|ID|@USER)', 'Post a retweet message'],
16
+ :exec_proc => lambda {|arg|
17
+ if public_storage[:typable_id] && s = typable_id_status(arg)
18
+ post_retweet(s)
19
+ else
20
+ case arg
21
+ when /(\d+)/
22
+ post_retweet(Termtter::API.twitter.show(arg))
23
+ #s = Twitter::API.twitter.show(arg)
24
+ #post_retweet(s)
25
+ when /@([A-Za-z0-9_]+)/
26
+ user = $1
27
+ statuses = Termtter::API.twitter.user_timeline(user)
28
+ return if statuses.empty?
29
+ post_retweet(statuses[0])
30
+ end
31
+ end
32
+ },
33
+ :completion_proc => lambda {|cmd, arg|
34
+ if public_storage[:typable_id] && s = typable_id_status(arg)
35
+ "u #{ERB.new(config.plugins.retweet.format).result(binding)}"
36
+ else
37
+ case arg
38
+ when /@(.*)/
39
+ find_user_candidates $1, "#{cmd} @%s"
40
+ when /(\d+)/
41
+ find_status_ids(arg).map{|id| "#{cmd} #{$1}"}
42
+ end
43
+ end
44
+ }
45
+ )
46
+ end