termtter 0.8.14 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. data/README.rdoc +8 -8
  2. data/Rakefile +3 -5
  3. data/lib/{plugin → plugins}/april_fool.rb +0 -0
  4. data/lib/plugins/bomb.rb +42 -0
  5. data/lib/{plugin → plugins}/clear.rb +0 -0
  6. data/lib/{plugin → plugins}/confirm.rb +0 -0
  7. data/lib/{plugin → plugins}/cool.rb +0 -0
  8. data/lib/{plugin → plugins}/devel.rb +0 -0
  9. data/lib/{filter → plugins}/en2ja.rb +1 -1
  10. data/lib/plugins/english.rb +25 -0
  11. data/lib/{plugin → plugins}/erb.rb +0 -0
  12. data/lib/{filter → plugins}/expand-tinyurl.rb +6 -6
  13. data/lib/plugins/favorite.rb +63 -0
  14. data/lib/plugins/fib.rb +28 -0
  15. data/lib/{filter/fib.rb → plugins/fib_filter.rb} +1 -2
  16. data/lib/{plugin → plugins}/filter.rb +0 -0
  17. data/lib/{plugin → plugins}/graduatter.rb +1 -2
  18. data/lib/{plugin → plugins}/grass.rb +2 -2
  19. data/lib/{plugin → plugins}/group.rb +9 -9
  20. data/lib/{plugin → plugins}/growl.rb +11 -12
  21. data/lib/{plugin → plugins}/hatebu.rb +5 -5
  22. data/lib/{plugin → plugins}/history.rb +13 -13
  23. data/lib/plugins/ignore.rb +19 -0
  24. data/lib/plugins/keyword.rb +18 -0
  25. data/lib/{plugin → plugins}/log.rb +18 -12
  26. data/lib/{plugin → plugins}/me.rb +1 -2
  27. data/lib/{plugin → plugins}/modify_arg_hook_sample.rb +0 -0
  28. data/lib/{plugin → plugins}/msagent.rb +1 -1
  29. data/lib/plugins/multi_reply.rb +27 -0
  30. data/lib/{plugin → plugins}/notify-send.rb +1 -1
  31. data/lib/{plugin → plugins}/otsune.rb +0 -0
  32. data/lib/plugins/outputz.rb +33 -0
  33. data/lib/{plugin → plugins}/pause.rb +0 -0
  34. data/lib/{plugin → plugins}/plugin.rb +0 -0
  35. data/lib/{plugin → plugins}/post_exec_hook_sample.rb +0 -0
  36. data/lib/{plugin → plugins}/pre_exec_hook_sample.rb +0 -0
  37. data/lib/{plugin → plugins}/primes.rb +9 -2
  38. data/lib/plugins/quicklook.rb +41 -0
  39. data/lib/{plugin → plugins}/random.rb +0 -0
  40. data/lib/{plugin → plugins}/reblog.rb +3 -3
  41. data/lib/{plugin → plugins}/reload.rb +0 -0
  42. data/lib/{filter → plugins}/reply.rb +0 -0
  43. data/lib/{filter → plugins}/reverse.rb +1 -1
  44. data/lib/{plugin → plugins}/say.rb +1 -1
  45. data/lib/{plugin → plugins}/scrape.rb +4 -4
  46. data/lib/plugins/screen-notify.rb +13 -0
  47. data/lib/plugins/screen.rb +24 -0
  48. data/lib/{plugin → plugins}/shell.rb +0 -0
  49. data/lib/{plugin → plugins}/sl.rb +4 -4
  50. data/lib/plugins/spam.rb +13 -0
  51. data/lib/{plugin → plugins}/standard_plugins.rb +72 -18
  52. data/lib/plugins/stdout.rb +80 -0
  53. data/lib/plugins/storage/DB.rb +37 -0
  54. data/lib/plugins/storage/status.rb +48 -0
  55. data/lib/plugins/storage/status_mook.rb +30 -0
  56. data/lib/plugins/storage.rb +47 -0
  57. data/lib/plugins/system_status.rb +33 -0
  58. data/lib/{plugin → plugins}/translation.rb +15 -5
  59. data/lib/{plugin → plugins}/update_editor.rb +6 -6
  60. data/lib/plugins/uri-open.rb +64 -0
  61. data/lib/{filter → plugins}/url_addspace.rb +0 -0
  62. data/lib/{plugin → plugins}/wassr_post.rb +1 -1
  63. data/lib/{plugin → plugins}/yhara.rb +1 -1
  64. data/lib/plugins/yhara_filter.rb +8 -0
  65. data/lib/plugins/yonda.rb +21 -0
  66. data/lib/termtter/api.rb +28 -2
  67. data/lib/termtter/client.rb +91 -102
  68. data/lib/termtter/command.rb +32 -31
  69. data/lib/termtter/config.rb +64 -0
  70. data/lib/termtter/connection.rb +9 -7
  71. data/lib/termtter/hook.rb +11 -2
  72. data/lib/termtter/optparse.rb +14 -0
  73. data/lib/termtter/version.rb +1 -1
  74. data/lib/termtter.rb +19 -22
  75. data/spec/plugin/english_spec.rb +19 -0
  76. data/spec/plugin/favorite_spec.rb +10 -0
  77. data/spec/plugin/fib_spec.rb +1 -2
  78. data/spec/plugin/pause_spec.rb +8 -0
  79. data/spec/plugin/plugin_spec.rb +1 -1
  80. data/spec/plugin/primes_spec.rb +15 -0
  81. data/spec/plugin/sl_spec.rb +8 -0
  82. data/spec/plugin/spam_spec.rb +0 -13
  83. data/spec/plugin/standard_plugins_spec.rb +0 -7
  84. data/spec/plugin/storage/DB_spec.rb +12 -0
  85. data/spec/plugin/storage/status_spec.rb +24 -0
  86. data/spec/spec_helper.rb +3 -0
  87. data/spec/termtter/client_spec.rb +63 -1
  88. data/spec/termtter/command_spec.rb +6 -68
  89. data/spec/termtter/config_spec.rb +111 -0
  90. data/spec/termtter/hook_spec.rb +69 -0
  91. data/spec/termtter_spec.rb +22 -34
  92. metadata +82 -73
  93. data/lib/filter/english.rb +0 -8
  94. data/lib/filter/ignore.rb +0 -19
  95. data/lib/filter/yhara.rb +0 -20
  96. data/lib/plugin/bomb.rb +0 -29
  97. data/lib/plugin/english.rb +0 -59
  98. data/lib/plugin/favorite.rb +0 -75
  99. data/lib/plugin/fib.rb +0 -8
  100. data/lib/plugin/follow.rb +0 -60
  101. data/lib/plugin/keyword.rb +0 -18
  102. data/lib/plugin/multi_reply.rb +0 -36
  103. data/lib/plugin/outputz.rb +0 -35
  104. data/lib/plugin/quicklook.rb +0 -38
  105. data/lib/plugin/screen.rb +0 -24
  106. data/lib/plugin/spam.rb +0 -9
  107. data/lib/plugin/stdout.rb +0 -63
  108. data/lib/plugin/system_status.rb +0 -33
  109. data/lib/plugin/uri-open.rb +0 -69
  110. data/lib/plugin/yonda.rb +0 -20
  111. data/lib/termtter/status.rb +0 -26
  112. data/lib/termtter/twitter.rb +0 -188
  113. data/lib/termtter/user.rb +0 -13
  114. data/spec/termtter/user_spec.rb +0 -27
  115. data/test/test_termtter.rb +0 -86
@@ -0,0 +1,27 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Termtter::Client
4
+ register_command(
5
+ :name => :multi_reply, :aliases => [:mr],
6
+ :exec_proc => lambda {|arg|
7
+ text = ERB.new(arg).result(binding).gsub(/\n/, ' ')
8
+ unless text.empty?
9
+ /(@(.+))*\s+(.+)/ =~ text
10
+ if $1
11
+ msg = $3
12
+ text = $1.split(/\s+/).map {|u| "#{u} #{msg}" }
13
+ end
14
+ Array(text).each do |post|
15
+ Termtter::API.twitter.update(post)
16
+ puts "=> #{post}"
17
+ end
18
+ end
19
+ },
20
+ :completion_proc => lambda {|cmd, args|
21
+ if /(.*)@([^\s]*)$/ =~ args
22
+ find_user_candidates $2, "#{cmd} #{$1}@%s"
23
+ end
24
+ },
25
+ :help => ["multi_reply,mp TEXT", "Reply to multi user"]
26
+ )
27
+ end
@@ -7,7 +7,7 @@ Termtter::Client.add_hook do |statuses, event|
7
7
  text = statuses.take(max).map {|s|
8
8
  status_text = CGI.escapeHTML(s.text)
9
9
  status_text.gsub!(%r{https?://[-_.!~*\'()a-zA-Z0-9;\/?:\@&=+\$,%#]+},'<a href="\0">\0</a>')
10
- "<b>#{s.user_screen_name}:</b> <span font=\"9.0\">#{status_text}</span>"
10
+ "<b>#{s.user.screen_name}:</b> <span font=\"9.0\">#{status_text}</span>"
11
11
  }.join("\n")
12
12
 
13
13
  text << %Q|\n<a href="http://twitter.com/">more...</a>| if statuses.size > max
File without changes
@@ -0,0 +1,33 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Termtter::Client
4
+ config.plugins.outputz.set_default(:uri, 'termtter://twitter.com/status/update')
5
+
6
+ key = config.plugins.outputz.secret_key
7
+ if key.empty?
8
+ puts 'Need your secret key'
9
+ puts 'please set config.plugins.outputz.secret_key'
10
+ else
11
+ register_hook(
12
+ :name => :outputz,
13
+ :points => [:pre_exec_update],
14
+ :exec_proc => lambda {|cmd, arg|
15
+ Thread.new do
16
+ Termtter::API.connection.start('outputz.com', 80) do |http|
17
+ key = CGI.escape key
18
+ uri = CGI.escape config.plugins.outputz.uri
19
+ size = arg.split(//).size
20
+ http.post('/api/post', "key=#{key}&uri=#{uri}&size=#{size}")
21
+ end
22
+ end
23
+ }
24
+ )
25
+ end
26
+ end
27
+
28
+ # outputz.rb
29
+ # a plugin that report to outputz your post
30
+ #
31
+ # settings (note: must this order)
32
+ # config.plugins.outputz.secret_key = 'your secret key'
33
+ # plugin 'outputz'
File without changes
File without changes
File without changes
File without changes
@@ -1,6 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  def primes(n)
4
+ return "" if n < 3
4
5
  table = []
5
6
  (2 .. n).each do |i|
6
7
  table << i
@@ -18,6 +19,12 @@ def primes(n)
18
19
  end
19
20
 
20
21
  module Termtter::Client
21
- add_command /^primes\s(\d+)/ do|m,t|t.update_status x="primes(#{n=m[1].to_i}) = {#{primes n}}"
22
- puts "=> #{x}" end
22
+ register_command(
23
+ :name => :primes,
24
+ :exec_proc => lambda {|arg|
25
+ n = arg.to_i
26
+ text = "primes(#{n}) = {#{primes n}}}"
27
+ puts "=> " << text
28
+ }
29
+ )
23
30
  end
@@ -0,0 +1,41 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'uri'
4
+ require 'open-uri'
5
+ require 'pathname'
6
+ require 'tmpdir'
7
+
8
+ config.plugins.quicklook.set_default(:quicklook_tmpdir, "#{Dir.tmpdir}/termtter-quicklook-tmpdir")
9
+ tmpdir = Pathname.new(config.plugins.quicklook.quicklook_tmpdir)
10
+ tmpdir.mkdir unless tmpdir.exist?
11
+
12
+ def quicklook(url)
13
+ tmpdir = Pathname.new(config.plugins.quicklook.quicklook_tmpdir)
14
+ path = tmpdir + Pathname.new(url).basename
15
+
16
+ Thread.new do
17
+ open(path, 'w') do |f|
18
+ f.write(open(url).read)
19
+ end
20
+ system("qlmanage -p #{path} > /dev/null 2>&1")
21
+ end
22
+ end
23
+
24
+ module Termtter::Client
25
+ register_command(
26
+ :name => :quicklook, :aliases => [:ql],
27
+ :exec_proc => proc{|arg|
28
+ status = Termtter::API.twitter.show(arg)
29
+ if (status)
30
+ uris = URI.regexp.match(status.text).to_a
31
+ quicklook(uris.first) unless uris.empty?
32
+ end
33
+ }
34
+ )
35
+ end
36
+
37
+ # quicklook.rb
38
+ # REQUIREMENTS:
39
+ # plugin 'expand-tinyurl'
40
+ # TODO:
41
+ # Close quicklook window automatically.
File without changes
@@ -17,7 +17,7 @@ module Termtter::Client
17
17
  status = t.show(id).first
18
18
  end
19
19
 
20
- Tumblr::API.write(configatron.plugins.reblog.email, configatron.plugins.reblog.password) do
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
23
23
  end
@@ -34,7 +34,7 @@ end
34
34
  # reblog.rb
35
35
  # tumblr reblog it!
36
36
  #
37
- # configatron.plugins.reblog.email = 'your-email-on-tumblr'
38
- # configatron.plugins.reblog.password = 'your-password-on-tumblr'
37
+ # config.plugins.reblog.email = 'your-email-on-tumblr'
38
+ # config.plugins.reblog.password = 'your-password-on-tumblr'
39
39
  #
40
40
  # reblog 1114860346
File without changes
File without changes
@@ -1,7 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  module Termtter::Client
4
- add_filter do |statuses|
4
+ add_filter do |statuses, _|
5
5
  statuses.map do |s|
6
6
  s.text = s.text.split(//).reverse.to_s
7
7
  s
@@ -14,7 +14,7 @@ module Termtter::Client
14
14
  if !statuses.empty? && event == :update_friends_timeline
15
15
  statuses.reverse.each do |s|
16
16
  text_without_uri = s.text.gsub(%r|https?://[^\s]+|, 'U.R.I.')
17
- say s.user_screen_name, text_without_uri
17
+ say s.user.screen_name, text_without_uri
18
18
  end
19
19
  end
20
20
  end
@@ -6,13 +6,13 @@ module Termtter::Client
6
6
  statuses = []
7
7
  members.each_with_index do |member, index|
8
8
  puts "member #{index+1}/#{members.size} #{member}"
9
- statuses += Termtter::API.twitter.get_user_timeline(member)
9
+ statuses += Termtter::API.twitter.user_timeline(member)
10
10
  end
11
11
  statuses
12
12
  end
13
13
 
14
14
  def self.scrape_group(group)
15
- members = configatron.plugins.group.groups[group] || []
15
+ members = config.plugins.group.groups[group] || []
16
16
  scrape_members(members)
17
17
  end
18
18
 
@@ -21,12 +21,12 @@ module Termtter::Client
21
21
  :exec_proc => lambda{ |args|
22
22
  groups = args.split(' ').map{|g| g.to_sym}
23
23
  if groups.include? :all
24
- groups = configatron.plugins.group.groups.keys
24
+ groups = config.plugins.group.groups.keys
25
25
  puts "get all groups..."
26
26
  end
27
27
  members = []
28
28
  groups.each do |group|
29
- members += configatron.plugins.group.groups[group]
29
+ members += config.plugins.group.groups[group]
30
30
  end
31
31
  statuses = scrape_members(members.uniq.compact.sort)
32
32
  call_hooks(statuses, :pre_filter)
@@ -0,0 +1,13 @@
1
+
2
+ if config.screen_notify.format.nil? or config.screen_notify.format.empty?
3
+ config.screen_notify.format = "[termtter] @%s"
4
+ end
5
+
6
+ Termtter::Client.add_hook do |statuses, event|
7
+ if !statuses.empty? && event == :update_friends_timeline
8
+ statuses.reverse.each do |s|
9
+ msg = config.screen_notify.format % [s.user.screen_name, s.text]
10
+ system 'screen', '-X', 'eval', "bell_msg '#{msg}'", 'bell'
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,24 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Termtter
4
+ module Plugin
5
+ module Screen
6
+ def self.set_title(title)
7
+ print "\033k#{title}\033\\\n"
8
+ end
9
+ end
10
+ end
11
+ end
12
+
13
+ # Add below to your ~/.termtter
14
+ #
15
+ # require 'plugins/yonda'
16
+ # require 'plugins/screen'
17
+ # module Termtter::Client
18
+ # register_hook(:name => :screen,
19
+ # :points => [:post_exec__update_timeline, :plugin_yonda_yonda, :post_exec_yonda],
20
+ # :exec_proc => lambda { |cmd, arg, result|
21
+ # Termtter::Plugin::Screen::set_title("termtter(#{public_storage[:unread_count]})")
22
+ # }
23
+ # )
24
+ # end
File without changes
@@ -5,8 +5,8 @@ module Termtter
5
5
  module Client
6
6
 
7
7
  public_storage[:current] = ''
8
- public_storage[:orig_prompt] = configatron.prompt
9
- configatron.prompt = "~/ #{public_storage[:orig_prompt]}"
8
+ public_storage[:orig_prompt] = config.prompt
9
+ config.prompt = "~/ #{public_storage[:orig_prompt]}"
10
10
 
11
11
  register_command(
12
12
  :name => :sl, :aliases => [],
@@ -23,7 +23,7 @@ module Termtter
23
23
  register_command(
24
24
  :name => :ls, :aliases => [],
25
25
  :exec_proc => lambda {|arg|
26
- call_commands("list #{arg.empty? ? public_storage[:current] : arg}", API.twitter)
26
+ call_commands("list #{arg.empty? ? public_storage[:current] : arg}")
27
27
  },
28
28
  :completion_proc => lambda {|cmd, args|
29
29
  find_user_candidates args, "#{cmd} %s"
@@ -36,7 +36,7 @@ module Termtter
36
36
  :exec_proc => lambda {|arg|
37
37
  public_storage[:current] =
38
38
  (arg.nil? || /\~/ =~ arg) ? '' : arg
39
- configatron.prompt = "~/#{public_storage[:current]} #{public_storage[:orig_prompt]}"
39
+ config.prompt = "~/#{public_storage[:current]} #{public_storage[:orig_prompt]}"
40
40
  },
41
41
  :completion_proc => lambda {|cmd, args|
42
42
  find_user_candidates args, "#{cmd} %s"
@@ -0,0 +1,13 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ Termtter::API.twitter.update('*super spam time*')
4
+ Termtter::Client.register_hook(
5
+ :name => :span,
6
+ :points => [/^pre_exec/],
7
+ :exec_proc => lambda{|*arg|
8
+ text = arg.join(' ')
9
+ Termtter::API.twitter.update(text)
10
+ puts "=> #{text}"
11
+ false
12
+ }
13
+ )
@@ -9,9 +9,12 @@ module Termtter::Client
9
9
  register_command(
10
10
  :name => :update, :aliases => [:u],
11
11
  :exec_proc => lambda {|arg|
12
- text = ERB.new(arg).result(binding).gsub(/\n/, ' ')
13
- Termtter::API.twitter.update_status(text)
14
- puts "=> #{text}"
12
+ unless arg =~ /^\s*$/
13
+ text = ERB.new(arg).result(binding).gsub(/\n/, ' ')
14
+ result = Termtter::API.twitter.update(text, :source=>Termtter::APP_NAME)
15
+ puts "=> #{text}"
16
+ result
17
+ end
15
18
  },
16
19
  :completion_proc => lambda {|cmd, args|
17
20
  if /(.*)@([^\s]*)$/ =~ args
@@ -39,7 +42,7 @@ module Termtter::Client
39
42
  register_command(
40
43
  :name => :profile, :aliases => [:p],
41
44
  :exec_proc => lambda {|arg|
42
- user = Termtter::API.twitter.get_user_profile(arg)
45
+ user = Termtter::API.twitter.user(arg.strip)
43
46
  attrs = %w[ name screen_name url description profile_image_url location protected following
44
47
  friends_count followers_count statuses_count favourites_count
45
48
  id time_zone created_at utc_offset notifications
@@ -58,19 +61,27 @@ module Termtter::Client
58
61
  register_command(
59
62
  :name => :followers,
60
63
  :exec_proc => lambda {|arg|
61
- followers = Termtter::API.twitter.followers
64
+ user_name = arg.strip
65
+ user_name = config.user_name if user_name.empty?
66
+
67
+ followers = []
68
+ page = 0
69
+ begin
70
+ followers += tmp = Termtter::API.twitter.followers(user_name, :page => page+=1)
71
+ end until tmp.empty?
62
72
  Termtter::Client.public_storage[:followers] = followers
63
73
  puts followers.map{|f|f.screen_name}.join(' ')
64
74
  }
75
+ # TODO :completion_proc
65
76
  )
66
77
 
67
78
  register_command(
68
79
  :name => :list, :aliases => [:l],
69
80
  :exec_proc => lambda {|arg|
70
81
  unless arg.empty?
71
- call_hooks(Termtter::API.twitter.get_user_timeline(arg), :list_user_timeline)
82
+ call_hooks(Termtter::API.twitter.user_timeline(arg), :list_user_timeline)
72
83
  else
73
- call_hooks(Termtter::API.twitter.get_friends_timeline(), :list_friends_timeline)
84
+ call_hooks(Termtter::API.twitter.friends_timeline(), :list_friends_timeline)
74
85
  end
75
86
  },
76
87
  :completion_proc => lambda {|cmd, arg|
@@ -122,13 +133,43 @@ module Termtter::Client
122
133
  :completion_proc => get_command(:show).completion_proc
123
134
  )
124
135
 
136
+ register_command(
137
+ :name => :follow, :aliases => [],
138
+ :exec_proc => lambda {|args|
139
+ args.split(' ').each do |arg|
140
+ if arg =~ /^(\w+)/
141
+ res = Termtter::API::twitter.follow($1.strip)
142
+ end
143
+ end
144
+ },
145
+ :completion_proc => lambda {|cmd, args|
146
+ find_user_candidates args, "#{cmd} %s"
147
+ },
148
+ :help => ['follow USER', 'Follow user']
149
+ )
150
+
151
+ register_command(
152
+ :name => :leave, :aliases => [],
153
+ :exec_proc => lambda {|args|
154
+ args.split(' ').each do |arg|
155
+ if arg =~ /^(\w+)/
156
+ res = Termtter::API::twitter.leave($1.strip)
157
+ end
158
+ end
159
+ },
160
+ :completion_proc => lambda {|cmd, args|
161
+ find_user_candidates args, "#{cmd} %s"
162
+ },
163
+ :help => ['leave USER', 'Leave user']
164
+ )
165
+
125
166
  # TODO: Change colors when remaining_hits is low.
126
167
  # TODO: Simmulate remaining_hits.
127
168
  register_command(
128
169
  :name => :limit, :aliases => [:lm],
129
170
  :exec_proc => lambda {|arg|
130
- limit = Termtter::API.twitter.get_rate_limit_status
131
- remaining_time = "%dmin %dsec" % (limit.reset_time - Time.now).divmod(60)
171
+ limit = Termtter::API.twitter.limit_status
172
+ remaining_time = "%dmin %dsec" % (Time.parse(limit.reset_time) - Time.now).divmod(60)
132
173
  remaining_color =
133
174
  case limit.remaining_hits / limit.hourly_limit.to_f
134
175
  when 0.2..0.4 then :yellow
@@ -162,10 +203,20 @@ module Termtter::Client
162
203
  :name => :default_error_handler,
163
204
  :points => [:on_error],
164
205
  :exec_proc => lambda {|e|
165
- puts "Error: #{e}"
166
- if configatron.devel == true
167
- puts e.backtrace.join("\n")
206
+ case e
207
+ when Rubytter::APIError
208
+ case e.response.code
209
+ when /401/
210
+ warn '[ERROR] Unauthorized: maybe you tried to show protected user status'
211
+ when /403/
212
+ warn '[ERROR] Access denied: maybe that user is protected'
213
+ when /404/
214
+ warn '[ERROR] Not found: maybe there is no such user'
215
+ end
216
+ else
217
+ warn "[ERROR] Something wrong: #{e.message}"
168
218
  end
219
+ raise e if config.system.devel == true
169
220
  }
170
221
  )
171
222
 
@@ -197,7 +248,7 @@ module Termtter::Client
197
248
  if arg
198
249
  `#{arg}`.each_line do |line|
199
250
  unless line.strip.empty?
200
- Termtter::API.twitter.update_status(line)
251
+ Termtter::API.twitter.update(line)
201
252
  puts "=> #{line}"
202
253
  end
203
254
  end
@@ -222,11 +273,14 @@ module Termtter::Client
222
273
  public_storage[:status_ids] ||= Set.new
223
274
 
224
275
  add_hook do |statuses, event, t|
225
- statuses.each do |s|
226
- public_storage[:users].add(s.user_screen_name)
227
- public_storage[:users] += s.text.scan(/@([a-zA-Z_0-9]*)/).flatten
228
- public_storage[:status_ids].add(s.id.to_s)
229
- public_storage[:status_ids].add(s.in_reply_to_status_id.to_s) if s.in_reply_to_status_id
276
+ case event
277
+ when :update_friends_timeline, :list_friends_timeline, :list_user_timeline, :replies
278
+ statuses.each do |s|
279
+ public_storage[:users].add(s.user.screen_name)
280
+ public_storage[:users] += s.text.scan(/@([a-zA-Z_0-9]*)/).flatten
281
+ public_storage[:status_ids].add(s.id.to_s)
282
+ public_storage[:status_ids].add(s.in_reply_to_status_id.to_s) if s.in_reply_to_status_id
283
+ end
230
284
  end
231
285
  end
232
286
 
@@ -0,0 +1,80 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'termcolor'
4
+ require 'erb'
5
+
6
+ config.plugins.stdout.set_default(
7
+ :colors,
8
+ [:none, :red, :green, :yellow, :blue, :magenta, :cyan])
9
+ config.plugins.stdout.set_default(
10
+ :timeline_format,
11
+ '<90><%=time%></90> <<%=status_color%>><%=status%></<%=status_color%>> <90><%=id%></90>')
12
+ config.plugins.stdout.set_default(:search_highlihgt_format, '<on_magenta><white>\1</white></on_magenta>')
13
+
14
+ $highline = HighLine.new
15
+
16
+ def color(str, value)
17
+ return str if value == :none
18
+ case value
19
+ when String, Symbol
20
+ $highline.color(str, value)
21
+ else
22
+ "\e[#{value}m#{str}\e[0m"
23
+ end
24
+ end
25
+
26
+ module Termtter::Client
27
+
28
+ def self.print_statuses(statuses, sort = true, time_format = '%H:%M:%S')
29
+ (sort ? statuses.sort_by{ |s| s.id} : statuses).each do |s|
30
+ text = s.text
31
+ status_color = config.plugins.stdout.colors[s.user.screen_name.hash % config.plugins.stdout.colors.size]
32
+ status = "#{s.user.screen_name}: #{text}"
33
+ if s.in_reply_to_status_id
34
+ status += " (repl. to #{s.in_reply_to_status_id})"
35
+ end
36
+
37
+ time = "(#{Time.parse(s.created_at).strftime(time_format)})"
38
+ id = s.id
39
+ erbed_text = ERB.new(config.plugins.stdout.timeline_format).result(binding)
40
+ puts TermColor.parse(erbed_text)
41
+ end
42
+ end
43
+
44
+ def self.print_statuses_with_date(statuses, sort = true)
45
+ print_statuses(statuses, sort, '%m-%d %H:%M')
46
+ end
47
+
48
+ def self.print_search_results(result, time_format = '%H:%M:%S')
49
+ result.results.sort_by{|r| r.created_at}.each do |r|
50
+ text = r.text.
51
+ gsub(/(\n|\r)/, '').
52
+ gsub(/(#{Regexp.escape(result.query)})/i, config.plugins.stdout.search_highlihgt_format)
53
+ status_color = config.plugins.stdout.colors[r.from_user_id.to_i.hash % config.plugins.stdout.colors.size]
54
+ status = "#{r.from_user}: #{text}"
55
+ time = "(#{Time.parse(r.created_at).strftime(time_format)})"
56
+ id = r.id
57
+ erbed_text = ERB.new(config.plugins.stdout.timeline_format).result(binding)
58
+ puts TermColor.parse(erbed_text)
59
+ end
60
+ end
61
+
62
+ add_hook do |result, event|
63
+ case event
64
+ when :update_friends_timeline, :list_friends_timeline
65
+ print_statuses(result) unless result.empty?
66
+ when :list_user_timeline, :replies
67
+ print_statuses_with_date(result) unless result.empty?
68
+ when :show
69
+ print_statuses_with_date([result])
70
+ when :search
71
+ print_search_results(result)
72
+ end
73
+ end
74
+
75
+ end
76
+ # stdout.rb
77
+ # output statuses to stdout
78
+ # example config
79
+ # config.plugins.stdout.colors = [:none, :red, :green, :yellow, :blue, :magenta, :cyan]
80
+ # config.plugins.stdout.timeline_format = '<90><%=time%></90> <<%=status_color%>><%=status%></<%=status_color%>> <90><%=id%></90>'
@@ -0,0 +1,37 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'sqlite3'
4
+ require 'singleton'
5
+
6
+ module Termtter::Storage
7
+ class DB
8
+ include Singleton
9
+ attr_reader :db
10
+
11
+ def initialize
12
+ @db = SQLite3::Database.new(Termtter::CONF_DIR + '/storage.db')
13
+ @db.type_translation = true
14
+ create_table
15
+ end
16
+
17
+ def create_table
18
+ sql =<<-SQL
19
+ CREATE TABLE IF NOT EXISTS user (
20
+ id int NOT NULL,
21
+ screen_name text,
22
+ PRIMARY KEY (id)
23
+ );
24
+ CREATE TABLE IF NOT EXISTS post (
25
+ post_id int NOT NULL, -- twitter側のpostのid
26
+ created_at int, -- 日付(RubyでUNIX時間に変換)
27
+ in_reply_to_status_id int, -- あったほうがよいらしい
28
+ in_reply_to_user_id int, -- あったほうがよいらしい
29
+ post_text text,
30
+ user_id int NOT NULL,
31
+ PRIMARY KEY (post_id)
32
+ );
33
+ SQL
34
+ @db.execute_batch(sql)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,48 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require File.dirname(__FILE__) + '/DB'
4
+ require 'sqlite3'
5
+
6
+ module Termtter::Storage
7
+ class Status
8
+ KEYS = %w[post_id created_at in_reply_to_status_id in_reply_to_user_id post_text user_id screen_name]
9
+
10
+ def size
11
+ DB.instance.db.get_first_value("select count(*) from post").to_i
12
+ end
13
+
14
+ def self.search(query)
15
+ raise "query must be Hash(#{query}, #{query.class})" unless query.kind_of? Hash
16
+
17
+ DB.instance.db.execute("select created_at, screen_name, post_text, in_reply_to_status_id, post_id from post inner join user on post.user_id = user.id where post_text like '%' || ? || '%' ", query[:post_text]) do |created_at, screen_name, post_text, in_reply_to_status_id, post_id|
18
+
19
+ # DB.instance.db.execute("select created_at, screen_name, post_text, in_reply_to_status_id, post_id from post inner join user on post.user_id = user.id where post_text like '%of%' ", query[:post_text]) do |created_at, screen_name, post_text, in_reply_to_status_id, post_id|
20
+ p [created_at, screen_name, post_text, in_reply_to_status_id, post_id]
21
+ end
22
+ end
23
+
24
+ def self.insert(data)
25
+ raise "data must be Hash(#{data}, #{data.class})" unless data.kind_of? Hash
26
+ # 条件しぼりたいけどやりかたがうまくわからない
27
+ # raise "unko" unless data.keys.all?{|c| KEYS.include? c}
28
+ begin
29
+ DB.instance.db.execute(
30
+ "insert into post values(?,?,?,?,?,?)",
31
+ data[:post_id],
32
+ data[:created_at],
33
+ data[:in_reply_to_status_id],
34
+ data[:in_reply_to_user_id],
35
+ data[:post_text],
36
+ data[:user_id])
37
+ begin
38
+ DB.instance.db.execute(
39
+ "insert into user values(?,?)",
40
+ data[:user_id],
41
+ data[:screen_name])
42
+ rescue # FIXME: specify exceptions here
43
+ end
44
+ rescue # FIXME: specify exceptions here
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,30 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'sqlite3'
4
+
5
+ module Termtter::Storage
6
+ class Status
7
+ def initialize
8
+ end
9
+
10
+ def self.create
11
+ end
12
+
13
+ def self.all
14
+ []
15
+ end
16
+
17
+ def self.search
18
+ end
19
+
20
+ private
21
+ def db
22
+ @db ||= connect
23
+ end
24
+
25
+ def connect
26
+ @db = SQLite3::Database.new(File.expand_path('~/test.db'))
27
+ @db.type_translation = true
28
+ end
29
+ end
30
+ end