termtter 1.3.1 → 1.4.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.
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)