termtter 1.3.1 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/README.rdoc +1 -8
  2. data/Rakefile +13 -3
  3. data/lib/plugins/command_plus.rb +14 -14
  4. data/lib/plugins/confirm.rb +10 -4
  5. data/lib/plugins/countter.rb +18 -18
  6. data/lib/plugins/db.rb +1 -1
  7. data/lib/plugins/defaults/alias.rb +69 -0
  8. data/lib/plugins/defaults/auto_reload.rb +2 -2
  9. data/lib/plugins/defaults/command_line.rb +9 -0
  10. data/lib/plugins/defaults/fib.rb +5 -23
  11. data/lib/plugins/defaults/retweet.rb +17 -13
  12. data/lib/plugins/defaults/standard_commands.rb +40 -63
  13. data/lib/plugins/defaults/standard_completion.rb +14 -9
  14. data/lib/plugins/defaults/stdout.rb +32 -19
  15. data/lib/plugins/defaults.rb +1 -0
  16. data/lib/plugins/erb.rb +4 -8
  17. data/lib/plugins/expand-tinyurl.rb +4 -0
  18. data/lib/plugins/fibyou.rb +12 -0
  19. data/lib/plugins/group.rb +19 -20
  20. data/lib/plugins/hi.rb +15 -0
  21. data/lib/plugins/hugeurl.rb +1 -1
  22. data/lib/plugins/irc_gw.rb +53 -5
  23. data/lib/plugins/itunes.rb +33 -0
  24. data/lib/plugins/jakigan.rb +30 -0
  25. data/lib/plugins/list_with_opts.rb +1 -1
  26. data/lib/plugins/multi_output.rb +34 -0
  27. data/lib/plugins/multi_post.rb +30 -15
  28. data/lib/plugins/open.rb +44 -0
  29. data/lib/plugins/paranoid.rb +11 -0
  30. data/lib/plugins/quick_exit.rb +9 -0
  31. data/lib/plugins/replace.rb +54 -0
  32. data/lib/plugins/saykanji.rb +1 -1
  33. data/lib/plugins/searchline.rb +44 -0
  34. data/lib/plugins/tinyurl.rb +7 -1
  35. data/lib/plugins/train.rb +24 -0
  36. data/lib/termtter/active_rubytter.rb +39 -0
  37. data/lib/termtter/api.rb +24 -21
  38. data/lib/termtter/client.rb +17 -29
  39. data/lib/termtter/config_setup.rb +27 -2
  40. data/lib/termtter/config_template.erb +2 -2
  41. data/lib/termtter/version.rb +1 -1
  42. data/lib/termtter.rb +9 -4
  43. data/spec/plugins/db_spec.rb +1 -1
  44. data/spec/plugins/fib_spec.rb +1 -1
  45. data/spec/plugins/standard_commands_spec.rb +4 -0
  46. data/spec/plugins/whois_spec.rb +7 -7
  47. data/spec/termtter/active_rubytter_spec.rb +70 -0
  48. metadata +29 -5
@@ -10,12 +10,14 @@ config.plugins.stdout.set_default(
10
10
  '<90><%=time%> [<%=status_id%>]</90> <<%=color%>><%=s.user.screen_name%>: <%=text%></<%=color%>> ' +
11
11
  '<90><%=reply_to_status_id ? " (reply_to [#{reply_to_status_id}]) " : ""%><%=source%><%=s.user.protected ? "[P]" : ""%></90>'
12
12
  )
13
+ config.plugins.stdout.set_default(:time_format_today, '%H:%M:%S')
14
+ config.plugins.stdout.set_default(:time_format_not_today, '%y/%m/%d %H:%M')
13
15
  config.plugins.stdout.set_default(:enable_pager, true)
14
16
  config.plugins.stdout.set_default(:pager, 'less -R -f +G')
15
17
  config.plugins.stdout.set_default(:window_height, 50)
16
18
  config.plugins.stdout.set_default(:typable_ids, ('aa'..'zz').to_a)
17
19
  config.plugins.stdout.set_default(:typable_id_prefix, '$')
18
- config.plugins.stdout.set_default(:show_as_thread, false)
20
+ config.plugins.stdout.set_default(:show_as_thread, false) # db plugin is required
19
21
 
20
22
  module Termtter
21
23
  class TypableIdGenerator
@@ -27,30 +29,49 @@ module Termtter
27
29
  end
28
30
  @ids = ids
29
31
  @table = {}
32
+ @rtable = {}
30
33
  end
31
34
 
32
35
  def next(data)
33
36
  id = @ids.shift
34
37
  @ids.push id
38
+ @rtable.delete(@table[id])
35
39
  @table[id] = data
40
+ @rtable[data] = id
36
41
  id
37
42
  end
38
43
 
39
44
  def get(id)
40
45
  @table[id]
41
46
  end
47
+
48
+ def get_id(data)
49
+ @rtable[data] || self.next(data)
50
+ end
42
51
  end
43
52
 
44
53
  module Client
45
54
  @typable_id_generator = TypableIdGenerator.new(config.plugins.stdout.typable_ids)
46
55
 
47
56
  def self.data_to_typable_id(data)
48
- id = config.plugins.stdout.typable_id_prefix + @typable_id_generator.next(data)
57
+ id = config.plugins.stdout.typable_id_prefix + @typable_id_generator.get_id(data)
49
58
  end
50
59
 
51
60
  def self.typable_id_to_data(id)
52
61
  @typable_id_generator.get(id)
53
62
  end
63
+
64
+ def self.time_format_for(statuses)
65
+ t0 = Time.now
66
+ t1 = Time.parse(statuses.first[:created_at])
67
+ t2 = Time.parse(statuses.last[:created_at])
68
+ if [t0.year, t0.month, t0.day] == [t1.year, t1.month, t1.day] \
69
+ and [t1.year, t1.month, t1.day] == [t2.year, t2.month, t2.day]
70
+ config.plugins.stdout.time_format_today
71
+ else
72
+ config.plugins.stdout.time_format_not_today
73
+ end
74
+ end
54
75
  end
55
76
 
56
77
  class StdOut < Hook
@@ -59,27 +80,16 @@ module Termtter
59
80
  end
60
81
 
61
82
  def call(statuses, event)
62
- print_statuses(statuses)
83
+ print_statuses(statuses, event)
63
84
  end
64
85
 
65
- def print_statuses(statuses, sort = true, time_format = nil)
86
+ def print_statuses(statuses, event, sort = true, time_format = nil)
66
87
  return unless statuses and statuses.first
67
- unless time_format
68
- t0 = Time.now
69
- t1 = Time.parse(statuses.first[:created_at])
70
- t2 = Time.parse(statuses.last[:created_at])
71
- time_format =
72
- if [t0.year, t0.month, t0.day] == [t1.year, t1.month, t1.day] \
73
- and [t1.year, t1.month, t1.day] == [t2.year, t2.month, t2.day]
74
- '%H:%M:%S'
75
- else
76
- '%y/%m/%d %H:%M'
77
- end
78
- end
88
+ time_format ||= Termtter::Client.time_format_for statuses
79
89
 
80
90
  output_text = ''
81
91
  statuses.each do |s|
82
- output_text << status_line(s, time_format)
92
+ output_text << status_line(s, time_format, event)
83
93
  end
84
94
 
85
95
  if config.plugins.stdout.enable_pager && ENV['LINES'] && statuses.size > ENV['LINES'].to_i
@@ -93,7 +103,7 @@ module Termtter
93
103
  end
94
104
  end
95
105
 
96
- def status_line(s, time_format, indent = 0)
106
+ def status_line(s, time_format, event, indent = 0)
97
107
  return '' unless s
98
108
  text = TermColor.escape(s.text)
99
109
  color = config.plugins.stdout.colors[s.user.id.to_i % config.plugins.stdout.colors.size]
@@ -114,10 +124,13 @@ module Termtter
114
124
 
115
125
  erbed_text = ERB.new(config.plugins.stdout.timeline_format).result(binding)
116
126
  indent_text = indent > 0 ? "#{' ' * (indent - 1)} ┗ " : ''
127
+
128
+ erbed_text = Client.get_hooks(:pre_coloring).inject(erbed_text){|result, hook| hook.call(result, event)}
129
+
117
130
  text = TermColor.parse(indent_text + erbed_text) + "\n"
118
131
  text = TermColor.unescape(text)
119
132
  if config.plugins.stdout.show_as_thread && s.in_reply_to_status_id
120
- text << status_line(Status[s.in_reply_to_status_id], time_format, indent + 1)
133
+ text << status_line(Status[s.in_reply_to_status_id], time_format, event, indent + 1)
121
134
  end
122
135
  text
123
136
  end
@@ -1,6 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  module Termtter::Client
4
+ # TODO: ↓不要な気もする
4
5
  config.set_default(:stdout, true)
5
6
  config.set_default(:standard_commands, true)
6
7
  config.set_default(:standard_completion, true)
data/lib/plugins/erb.rb CHANGED
@@ -1,14 +1,10 @@
1
1
  # -*- coding: utf-8 -*-
2
-
3
2
  require 'erb'
4
-
5
- Termtter::Client.register_hook(
6
- :name => :erb,
7
- :point => :modify_arg_for_update,
8
- :exec_proc => lambda {|cmd, arg|
3
+ module Termtter::Client
4
+ register_hook(:erb, :point => :modify_arg_for_update) do |cmd, arg|
9
5
  ERB.new(arg).result(binding)
10
- }
11
- )
6
+ end
7
+ end
12
8
 
13
9
  # erb.rb
14
10
  # enable to <%= %> in the command update
@@ -5,6 +5,8 @@ URL_SHORTTERS = [
5
5
  { :host => "is.gd", :pattern => %r'(http://is\.gd(/[\w/]+))' },
6
6
  { :host => "bit.ly", :pattern => %r'(http://bit\.ly(/[\w/]+))' },
7
7
  { :host => "ff.im", :pattern => %r'(http://ff\.im(/[-\w/]+))'},
8
+ { :host => "to.ly", :pattern => %r'(http://to\.ly(/[-\w/]+))'},
9
+ { :host => "j.mp", :pattern => %r'(http://j\.mp(/[\w/]+))' },
8
10
  ]
9
11
 
10
12
  config.plugins.expand_tinyurl.set_default(:shortters, [])
@@ -52,4 +54,6 @@ def expand_url(host, path)
52
54
  res = http_class.new(host).head(path)
53
55
  return nil unless res.code == "301" or res.code == "302"
54
56
  res['Location'].force_encoding(Encoding::UTF_8)
57
+ rescue
58
+ nil
55
59
  end
@@ -0,0 +1,12 @@
1
+ # It depends on defaults/fib.rb
2
+
3
+ module Termtter::Client
4
+ register_command(:fibyou) do |arg|
5
+ /(\w+)\s(\d+)/ =~ arg
6
+ name = normalize_as_user_name($1)
7
+ n = $2.to_i
8
+ text = "@#{name} fib(#{n}) = #{fib n}"
9
+ Termtter::API.twitter.update(text)
10
+ puts "=> " << text
11
+ end
12
+ end
data/lib/plugins/group.rb CHANGED
@@ -1,17 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- module Termtter
4
- class Status
5
- def is_member?(group = nil)
6
- if group
7
- config.plugins.group.groups[group].include? self.user.screen_name
8
- else
9
- config.plugins.group.groups.values.flatten.include? self.user.screen_name
10
- end
11
- end
12
- end
13
- end
14
-
15
3
  module Termtter::Client
16
4
  config.plugins.group.
17
5
  set_default(:groups, {})
@@ -34,15 +22,25 @@ module Termtter::Client
34
22
  :exec_proc => lambda {|arg|
35
23
  unless arg.empty?
36
24
  group_name = arg.to_sym
25
+ groups = config.plugins.group.groups
37
26
  if group_name == :all
38
- targets = config.plugins.group.groups.values.flatten.uniq
27
+ targets = groups.values.flatten.uniq
28
+ elsif groups.keys.include? group_name
29
+ targets = groups[group_name]
39
30
  else
40
- targets = config.plugins.group.groups[group_name]
31
+ ignore_cased = groups.keys.map(&:to_s).grep(/^#{group_name}$/i).map(&:to_sym)
32
+ if ignore_cased.length == 1
33
+ targets = groups[ignore_cased.first]
34
+ elsif ignore_cased.length > 1
35
+ puts "which? #{ignore_cased.inspect.gsub(':','')}"
36
+ end
37
+ end
38
+ if targets
39
+ statuses = targets ? targets.map { |target|
40
+ public_storage[:tweet][target]
41
+ }.flatten.uniq.compact.sort_by{ |s| s[:id]} : []
42
+ output(statuses, :search)
41
43
  end
42
- statuses = targets ? targets.map { |target|
43
- public_storage[:tweet][target]
44
- }.flatten.uniq.compact.sort_by{ |s| s[:id]} : []
45
- output(statuses, :search)
46
44
  else
47
45
  config.plugins.group.groups.each_pair do |key, value|
48
46
  puts "#{key}: #{value.join(',')}"
@@ -69,10 +67,10 @@ module Termtter::Client
69
67
  :exec_proc => lambda do |statuses, event|
70
68
  return statuses unless event == :update_friends_timeline
71
69
  return statuses unless config.plugins.group.default_filter
72
- skip_group = config.plugins.group.default_filter
70
+ filter_group = config.plugins.group.default_filter
73
71
  r = []
74
72
  statuses.each do |s|
75
- unless self.is_member?(s, :dqn)
73
+ unless self.is_member?(s, filter_group)
76
74
  r << s
77
75
  end
78
76
  end
@@ -86,5 +84,6 @@ end
86
84
  # config.plugins.group.groups = {
87
85
  # :rits => %w(hakobe isano hitode909)
88
86
  # }
87
+ # config.plugins.group.default_filter = :rits
89
88
  # NOTE: group.rb needs plugin/log
90
89
 
data/lib/plugins/hi.rb ADDED
@@ -0,0 +1,15 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Termtter::Client
3
+ [:hi, :hola].each do |hi|
4
+ register_command(hi, :help => ["#{hi} [(Optinal) USER]", "Post a #{hi}"]) do |arg|
5
+ result =
6
+ if arg.empty?
7
+ Termtter::API.twitter.update(hi.to_s)
8
+ else
9
+ name = normalize_as_user_name(arg)
10
+ Termtter::API.twitter.update("#{hi} @#{name}")
11
+ end
12
+ puts "=> " << result.text
13
+ end
14
+ end
15
+ end
@@ -26,7 +26,7 @@ Termtter::Client::register_hook(
26
26
  config.plugins.hugeurl.skip_users.include?(s.user.screen_name) and next
27
27
  s.text.gsub!(HUGEURL_TARGET_PATTERN) do |m|
28
28
  res = http.get('/hugeurl?url=' + m)
29
- res.code == '200' ? res.body : m
29
+ res.code == '200' && res.body !~ /^</ ? res.body : m
30
30
  end
31
31
  end
32
32
  end
@@ -2,10 +2,24 @@
2
2
 
3
3
  require 'net/irc'
4
4
 
5
- # TODO: post text of stdout too
6
-
7
5
  config.plugins.irc_gw.set_default(:port, 16669)
8
6
  config.plugins.irc_gw.set_default(:last_statuses_count, 100)
7
+ config.plugins.irc_gw.set_default(:logger_level, Logger::ERROR)
8
+
9
+ module Termtter::Client
10
+ class << self
11
+ def friends
12
+ user_name = config.user_name
13
+
14
+ frinends = []
15
+ page = 0
16
+ begin
17
+ frinends += tmp = Termtter::API::twitter.friends(user_name, :page => page+=1)
18
+ end until tmp.empty?
19
+ frinends.map(&:screen_name)
20
+ end
21
+ end
22
+ end
9
23
 
10
24
  class TermtterIrcGateway < Net::IRC::Server::Session
11
25
  @@listners = []
@@ -25,6 +39,13 @@ class TermtterIrcGateway < Net::IRC::Server::Session
25
39
  end
26
40
  }
27
41
  )
42
+ if Termtter::Client.respond_to? :register_output
43
+ Termtter::Client.register_output(:irc) do |message|
44
+ @@listners.each do |listener|
45
+ listener.log(message.gsub(/\e\[\d+m/, '')) # remove escape sequence
46
+ end
47
+ end
48
+ end
28
49
 
29
50
  def server_name; 'termtter' end
30
51
  def server_version; '0.0.0' end
@@ -41,11 +62,13 @@ class TermtterIrcGateway < Net::IRC::Server::Session
41
62
  when :update_friends_timeline
42
63
  PRIVMSG
43
64
  else
65
+ time_format = Termtter::Client.time_format_for statuses
44
66
  NOTICE
45
67
  end
46
-
47
68
  statuses.each do |s|
48
- post s.user.screen_name, msg_type, main_channel, [s.text, s.id].join(' ')
69
+ typable_id = Termtter::Client.data_to_typable_id(s.id)
70
+ time = Time.parse(s.created_at).strftime(time_format) if time_format
71
+ post s.user.screen_name, msg_type, main_channel, [time, s.text, typable_id].compact.join(' ')
49
72
  end
50
73
  end
51
74
 
@@ -61,21 +84,46 @@ class TermtterIrcGateway < Net::IRC::Server::Session
61
84
  super
62
85
  post @prefix, JOIN, main_channel
63
86
  post server_name, MODE, main_channel, "+o", @prefix.nick
87
+ check_friends
64
88
  self.call(@@last_statuses || [], :update_friends_timeline)
65
89
  end
66
90
 
67
91
  def on_privmsg(m)
68
92
  target, message = *m.params
69
93
  Termtter::Client.call_commands('update ' + message)
94
+ post @prefix, TOPIC, main_channel, message
95
+ end
96
+
97
+ def log(str)
98
+ str.each_line do |line|
99
+ post server_name, NOTICE, main_channel, line
100
+ end
101
+ end
102
+
103
+ def check_friends
104
+ params = []
105
+ max_params_count = 3
106
+ Termtter::Client.friends.each do |name|
107
+ prefix = Prefix.new("#{name}!#{name}@localhost")
108
+ post prefix, JOIN, main_channel
109
+ params << prefix.nick
110
+ next if params.size < max_params_count
111
+
112
+ post server_name, MODE, main_channel, "+#{"v" * params.size}", *params
113
+ params = []
114
+ end
115
+ post server_name, MODE, main_channel, "+#{"v" * params.size}", *params unless params.empty?
70
116
  end
71
117
  end
72
118
 
73
119
  unless defined? IRC_SERVER
120
+ logger = Logger.new($stdout)
121
+ logger.level = config.plugins.irc_gw.logger_level
74
122
  IRC_SERVER = Net::IRC::Server.new(
75
123
  'localhost',
76
124
  config.plugins.irc_gw.port,
77
125
  TermtterIrcGateway,
78
- :logger => Termtter::Client.logger
126
+ :logger => logger
79
127
  )
80
128
  Thread.start do
81
129
  IRC_SERVER.start
@@ -0,0 +1,33 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'appscript' or raise 'itunes plugin cannot run'
3
+
4
+ config.plugins.itunes.set_default(:prefix, 'Listening now:')
5
+ config.plugins.itunes.set_default(:suffix, '#iTunes #listening')
6
+ config.plugins.itunes.set_default(
7
+ :format,
8
+ '<%=prefix%> <%=track_name%> (<%=time%>) <%=artist%> <%=album%> <%=suffix%>')
9
+
10
+ module Termtter::Client
11
+ register_command :name => :listening_now, :aliases => [:ln],
12
+ :help => ['listening_now,ln', "Post the information of listening now."],
13
+ :exec_proc => lambda {|args|
14
+ begin
15
+ prefix = config.plugins.itunes.prefix
16
+ track_name = Appscript.app('iTunes').current_track.name.get
17
+ artist = Appscript.app('iTunes').current_track.artist.get
18
+ genre = Appscript.app('iTunes').current_track.genre.get
19
+ time = Appscript.app('iTunes').current_track.time.get
20
+ album = Appscript.app('iTunes').current_track.album.get
21
+ suffix = config.plugins.itunes.suffix
22
+ erbed_text = ERB.new(config.plugins.itunes.format).result(binding)
23
+ erbed_text.gsub!(/\s{2,}/, ' ')
24
+ if args.length > 0
25
+ erbed_text = args + ' ' + erbed_text
26
+ end
27
+ Termtter::API.twitter.update(erbed_text)
28
+ puts "=> " << erbed_text
29
+ rescue => e
30
+ p e
31
+ end
32
+ }
33
+ end
@@ -0,0 +1,30 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ if RUBY_VERSION >= '1.9'
4
+ # nop
5
+ elsif RUBY_VERSION >= '1.8.7'
6
+ class Array
7
+ alias sample choice
8
+ end
9
+ else
10
+ class Array
11
+ def sample
12
+ at(rand(size))
13
+ end
14
+ end
15
+ end
16
+
17
+ module Termtter::Client
18
+ module Jakigan
19
+ TEMPLATES = [
20
+ # http://twitter.com/yugui/status/3086394151
21
+ '%s、か。ククク、その真の意図、邪気眼を持たぬ者には分かるまい。',
22
+ # http://twitter.com/Sixeight/statuses/3705973751
23
+ '僕の邪気眼は%sです。'
24
+ ]
25
+ end
26
+ register_macro(:jkg, "update #{Jakigan::TEMPLATES.sample}",
27
+ :help => ['jkg {MESSAGE}', 'update "{MESSAGE}+something jkg."'],
28
+ :alias => :jk
29
+ )
30
+ end
@@ -3,7 +3,7 @@ module Termtter::Client
3
3
  register_command(
4
4
  :name => :list, :aliases => [:l],
5
5
  :exec_proc => lambda {|arg|
6
- _, options, user = */((?:\-[a-z][= ]\S+\s*)+)?(\w+)?/.match(arg)
6
+ _, options, user = */((?:\-[a-z][= ]\S+\s*)+)?(?:@?(\w+))?/.match(arg)
7
7
  params = {}
8
8
  options.scan(/(\-[a-z])[= ](\S+)/).each do |k,v|
9
9
  v = v.sub(/^['"]/,'').sub(/['"]$/,'')
@@ -0,0 +1,34 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Termtter::Client
4
+ @outputs = { }
5
+ class << self
6
+ def register_output(as, &block)
7
+ @outputs[as] = block
8
+ end
9
+
10
+ def delete_output(name)
11
+ @outputs.delete(name)
12
+ end
13
+
14
+ def puts message
15
+ @outputs.each_value do |block|
16
+ block.call(message)
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ module Termtter::Client
23
+ register_command(
24
+ :name => :outputs,
25
+ :exec_proc => lambda {|arg|
26
+ puts @outputs.keys.inspect
27
+ },
28
+ :help => ['outputs', 'Show outputs']
29
+ )
30
+
31
+ register_output(:stdout) do |msg|
32
+ STDOUT.puts(msg)
33
+ end
34
+ end
@@ -3,30 +3,45 @@
3
3
  module Termtter::Client
4
4
  class << self
5
5
  def wassr_update(text)
6
+ if text.match(/^(\d+)\s+(.+)$/) and
7
+ (s = Termtter::API.twitter.show($1) rescue nil)
8
+ tmp_text = "@#{s.user.screen_name} #{$2}"
9
+ else
10
+ tmp_text = text
11
+ end
12
+
6
13
  Net::HTTP.version_1_2
7
14
  req = Net::HTTP::Post.new("/statuses/update.json?")
8
15
  req.basic_auth config.plugins.wassr.username, config.plugins.wassr.password
9
16
  Net::HTTP.start('api.wassr.jp', 80) do |http|
10
- res = http.request(req, "status=#{URI.escape(text)}&source=Termtter")
17
+ res = http.request(req, "status=#{URI.escape(tmp_text)}&source=Termtter")
11
18
  end
12
19
  end
13
20
  end
14
- end
15
21
 
16
- Termtter::Client.register_hook(
17
- :name => :multi_post,
18
- :points => [:modify_arg_for_update, :modify_arg_for_reply],
19
- :exec_proc => lambda {|cmd, arg|
20
- begin
21
- wassr_arg = arg.gsub(/\d{10,}/, '')
22
- Termtter::Client.wassr_update(wassr_arg.strip)
23
- rescue
24
- puts "RuntimeError: #{$!}"
25
- end
22
+ register_hook(
23
+ :name => :multi_post,
24
+ :points => [:post_exec_update, :post_exec_reply, :post_exec_retweet],
25
+ :exec_proc => lambda {|cmd, arg, result|
26
+ prefix = config.plugins.stdout.typable_id_prefix
27
+ if result
28
+ wassr_arg = result
29
+ elsif arg.match(/(\$([a-z]{2}))/) and
30
+ s = Termtter::API.twitter.show(typable_id_to_data($2))
31
+ wassr_arg = arg.sub($1, "@" + s.user.screen_name)
32
+ else
33
+ wassr_arg = arg
34
+ end
35
+
36
+ begin
37
+ Termtter::Client.wassr_update(wassr_arg.strip)
38
+ rescue
39
+ puts "RuntimeError: #{$!}"
40
+ end
41
+ }
42
+ )
43
+ end
26
44
 
27
- return arg
28
- }
29
- )
30
45
 
31
46
  # multi_post.rb
32
47
  # One post, multi update.
@@ -0,0 +1,44 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Termtter
4
+ module Client
5
+ plug 'uri-open'
6
+ register_command(
7
+ :name => :open, :aliases => [:o],
8
+ :exec_proc => proc {|arg|
9
+ sid, n = arg.split(/ +/)
10
+ if sid.nil?
11
+ call_commands "uri-open"
12
+ else
13
+ target = (n || 1).to_i
14
+ target_uri = nil
15
+ ids = find_status_ids(sid) || []
16
+ ids.each do |id|
17
+ text = Termtter::API.twitter.show(id).text
18
+ URI.extract(text, %w[http https]).each_with_index do |uri, i|
19
+ print "#{i + 1}) #{uri}"
20
+ if i + 1 == target
21
+ target_uri = uri
22
+ print " <-"
23
+ end
24
+ puts ""
25
+ end
26
+ end
27
+ if target_uri
28
+ open_uri target_uri
29
+ end
30
+ end
31
+ },
32
+ :help => ['open,o', 'Open n-th URI in the message']
33
+ )
34
+ end
35
+ end
36
+
37
+ # usage
38
+ # > open $dq
39
+ # open 1st URI in $dq
40
+ # > open $dq 2
41
+ # open 2nd URI in $dq
42
+ #
43
+ # see also
44
+ # http://twitter.com/takiuchi
@@ -0,0 +1,11 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Termtter::Client
3
+ register_command(
4
+ :paranoid,
5
+ :help => ['paranoid message', 'Something like `update`'],
6
+ :alias => :pd) do |arg|
7
+ str = arg.gsub(/\w+/, '@\0').gsub(/\#@/, '#')
8
+ result = Termtter::API.twitter.update(str)
9
+ puts "paranoid'ed=> " << result.text
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #config.plugins.alias.aliases = { :e => 'exit', :q => 'exit'}
4
+ #
5
+
6
+ module Termtter::Client
7
+ register_alias(:e, 'exit')
8
+ register_alias(:q, 'exit')
9
+ end
@@ -0,0 +1,54 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Termtter::Client
4
+ def self.delete_and_replace(recent, pattern_reg, replace, global)
5
+ new_text =
6
+ if global
7
+ recent.text.gsub(pattern_reg, replace)
8
+ else
9
+ recent.text.sub(pattern_reg, replace)
10
+ end
11
+
12
+ param =
13
+ if recent.in_reply_to_status_id
14
+ {:in_reply_to_status_id => recent.in_reply_to_status_id}
15
+ else
16
+ {}
17
+ end
18
+
19
+ if new_text == recent.text
20
+ puts "It was not replaced."
21
+ raise Termtter::CommandCanceled
22
+ end
23
+
24
+ if /^y?$/i !~ Readline.readline("\"replace #{new_text}\" [Y/n] ", false)
25
+ puts 'canceled.'
26
+ raise Termtter::CommandCanceled
27
+ else
28
+ result = Termtter::API.twitter.remove_status(recent.id)
29
+ puts "deleted => #{result.text}"
30
+ result = Termtter::API.twitter.update(new_text, param)
31
+ puts "updated => #{result.text}"
32
+ end
33
+ end
34
+
35
+ register_command(:name => :replace,
36
+ :aliases => [:typo],
37
+ :help => ['replace,typo /PATTERN/REPLACE/',
38
+ 'Delete and replace most recent tweet.'],
39
+ :exec_proc => lambda {|arg|
40
+ recent =
41
+ Termtter::API.twitter.user_timeline(config.user_name)[0]
42
+ pattern, replace, mode =
43
+ /^s?\/(.*?(?:(?!\\).))\/(.*)\/$/.match(arg).to_a.values_at(1, 2, 3)
44
+
45
+ if pattern == ""
46
+ puts "PATTERN is empty."
47
+ raise Termtter::CommandCanceled
48
+ end
49
+
50
+ delete_and_replace(recent, Regexp.new(pattern, /i/.match(mode)),
51
+ replace, /g/ =~ mode)
52
+ }
53
+ )
54
+ end
@@ -40,7 +40,7 @@ def saykanji(text, say_speed)
40
40
  end
41
41
  }
42
42
  text_to_say = `echo #{text_wakati.join}|mecab -O yomi`
43
- system "SayKana", "-s", "#{say_speed}", "#{text_to_say}"
43
+ system "SayKana -s #{say_speed} \"#{text_to_say}\" 2>/dev/null"
44
44
  end
45
45
 
46
46
  def say(who, text)