termtter 0.8.3

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 (93) hide show
  1. data/History.txt +4 -0
  2. data/README.rdoc +97 -0
  3. data/Rakefile +46 -0
  4. data/bin/kill_termtter +22 -0
  5. data/bin/termtter +7 -0
  6. data/lib/filter/en2ja.rb +11 -0
  7. data/lib/filter/english.rb +8 -0
  8. data/lib/filter/expand-tinyurl.rb +24 -0
  9. data/lib/filter/fib.rb +15 -0
  10. data/lib/filter/ignore.rb +19 -0
  11. data/lib/filter/reply.rb +8 -0
  12. data/lib/filter/reverse.rb +13 -0
  13. data/lib/filter/url_addspace.rb +16 -0
  14. data/lib/filter/yhara.rb +20 -0
  15. data/lib/plugin/april_fool.rb +15 -0
  16. data/lib/plugin/bomb.rb +29 -0
  17. data/lib/plugin/clear.rb +14 -0
  18. data/lib/plugin/confirm.rb +9 -0
  19. data/lib/plugin/cool.rb +10 -0
  20. data/lib/plugin/devel.rb +13 -0
  21. data/lib/plugin/english.rb +59 -0
  22. data/lib/plugin/erb.rb +17 -0
  23. data/lib/plugin/favorite.rb +75 -0
  24. data/lib/plugin/fib.rb +8 -0
  25. data/lib/plugin/filter.rb +69 -0
  26. data/lib/plugin/follow.rb +56 -0
  27. data/lib/plugin/graduatter.rb +9 -0
  28. data/lib/plugin/grass.rb +27 -0
  29. data/lib/plugin/group.rb +60 -0
  30. data/lib/plugin/growl.rb +62 -0
  31. data/lib/plugin/hatebu.rb +59 -0
  32. data/lib/plugin/history.rb +82 -0
  33. data/lib/plugin/keyword.rb +18 -0
  34. data/lib/plugin/log.rb +63 -0
  35. data/lib/plugin/modify_arg_hook_sample.rb +7 -0
  36. data/lib/plugin/msagent.rb +26 -0
  37. data/lib/plugin/multi_reply.rb +36 -0
  38. data/lib/plugin/notify-send.rb +17 -0
  39. data/lib/plugin/otsune.rb +21 -0
  40. data/lib/plugin/outputz.rb +35 -0
  41. data/lib/plugin/pause.rb +3 -0
  42. data/lib/plugin/plugin.rb +53 -0
  43. data/lib/plugin/post_exec_hook_sample.rb +9 -0
  44. data/lib/plugin/pre_exec_hook_sample.rb +9 -0
  45. data/lib/plugin/primes.rb +23 -0
  46. data/lib/plugin/quicklook.rb +38 -0
  47. data/lib/plugin/reblog.rb +40 -0
  48. data/lib/plugin/reload.rb +3 -0
  49. data/lib/plugin/say.rb +24 -0
  50. data/lib/plugin/scrape.rb +41 -0
  51. data/lib/plugin/screen.rb +24 -0
  52. data/lib/plugin/shell.rb +14 -0
  53. data/lib/plugin/sl.rb +48 -0
  54. data/lib/plugin/spam.rb +9 -0
  55. data/lib/plugin/standard_plugins.rb +269 -0
  56. data/lib/plugin/stdout.rb +62 -0
  57. data/lib/plugin/system_status.rb +33 -0
  58. data/lib/plugin/translation.rb +28 -0
  59. data/lib/plugin/update_editor.rb +53 -0
  60. data/lib/plugin/uri-open.rb +69 -0
  61. data/lib/plugin/wassr_post.rb +22 -0
  62. data/lib/plugin/yhara.rb +148 -0
  63. data/lib/plugin/yonda.rb +20 -0
  64. data/lib/termtter/api.rb +14 -0
  65. data/lib/termtter/client.rb +399 -0
  66. data/lib/termtter/command.rb +77 -0
  67. data/lib/termtter/connection.rb +39 -0
  68. data/lib/termtter/hook.rb +18 -0
  69. data/lib/termtter/status.rb +26 -0
  70. data/lib/termtter/task.rb +16 -0
  71. data/lib/termtter/task_manager.rb +116 -0
  72. data/lib/termtter/twitter.rb +173 -0
  73. data/lib/termtter/user.rb +13 -0
  74. data/lib/termtter/version.rb +3 -0
  75. data/lib/termtter.rb +157 -0
  76. data/spec/plugin/cool_spec.rb +10 -0
  77. data/spec/plugin/fib_spec.rb +16 -0
  78. data/spec/plugin/filter_spec.rb +18 -0
  79. data/spec/plugin/plugin_spec.rb +25 -0
  80. data/spec/plugin/shell_spec.rb +10 -0
  81. data/spec/plugin/spam_spec.rb +17 -0
  82. data/spec/plugin/standard_plugins_spec.rb +31 -0
  83. data/spec/spec_helper.rb +4 -0
  84. data/spec/termtter/client_spec.rb +175 -0
  85. data/spec/termtter/command_spec.rb +161 -0
  86. data/spec/termtter/task_manager_spec.rb +78 -0
  87. data/spec/termtter/task_spec.rb +22 -0
  88. data/spec/termtter/user_spec.rb +27 -0
  89. data/spec/termtter_spec.rb +43 -0
  90. data/test/friends_timeline.json +5 -0
  91. data/test/search.json +8 -0
  92. data/test/test_termtter.rb +86 -0
  93. metadata +177 -0
@@ -0,0 +1,56 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Termtter::Client
4
+ register_command(
5
+ :name => :follow, :aliases => [],
6
+ :exec_proc => lambda {|arg|
7
+ if arg =~ /^(\w+)/
8
+ res = Termtter::API::twitter.social($1.strip, :follow)
9
+ if res.code == '200'
10
+ puts "Followed user @#{$1}"
11
+ else
12
+ puts "Failed: #{res}"
13
+ end
14
+ end
15
+ },
16
+ :completion_proc => lambda {|cmd, args|
17
+ find_user_candidates args, "#{cmd} %s"
18
+ },
19
+ :help => ['follow USER', 'Follow user']
20
+ )
21
+
22
+ register_command(
23
+ :name => :leave, :aliases => [],
24
+ :exec_proc => lambda {|arg|
25
+ if arg =~ /^(\w+)/
26
+ res = Termtter::API::twitter.social($1.strip, :leave)
27
+ if res.code == '200'
28
+ puts "Leaved user @#{$1}"
29
+ else
30
+ puts "Failed: #{res}"
31
+ end
32
+ end
33
+ },
34
+ :completion_proc => lambda {|cmd, args|
35
+ find_user_candidates args, "#{cmd} %s"
36
+ },
37
+ :help => ['leave USER', 'Leave user']
38
+ )
39
+ end
40
+
41
+ module Termtter
42
+ class Twitter
43
+ def social(user, type)
44
+ type =
45
+ case type.to_sym
46
+ when :follow then 'create'
47
+ when :leave then 'destroy'
48
+ end
49
+ uri = "#{@connection.protocol}://twitter.com/friendships/#{type}/#{user}.json"
50
+
51
+ @connection.start('twitter.com', @connection.port) do |http|
52
+ http.request(post_request(uri))
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,9 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ twitter = Termtter::Twitter.new(configatron.user_name, configatron.password)
4
+ Thread.start do
5
+ 100.times do |i|
6
+ twitter.update_status(
7
+ "I decided not to use twitter so as not to leave university before I complete the dissertation#{i.odd? ? '!' : '.'}")
8
+ end
9
+ end
@@ -0,0 +1,27 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Termtter
3
+ module Client
4
+
5
+ configatron.plugins.grass.set_default(:rate, 0)
6
+
7
+ register_command(
8
+ :name => :w, :aliases => [:grass],
9
+ :exec_proc => lambda {|arg|
10
+ arg, rate = arg.split(/ /)
11
+ count = arg =~ /^[0-9]+$/ ? arg.to_i : 3
12
+ rate ||= configatron.plugins.grass.rate
13
+ grow = (count * rate.to_i).quo(100).round
14
+ grasses = ('w' * (count-grow) + 'W' * grow).split(//).shuffle.join
15
+ call_commands("update #{grasses}")
16
+ },
17
+ :help => ['grass, w', 'Grass it!']
18
+ )
19
+ end
20
+ end
21
+
22
+ # usage
23
+ # > w 10
24
+ # => wwwwwwwwww
25
+ #
26
+ # see also
27
+ # http://d.hatena.ne.jp/tomisima/20090204/1233762301
@@ -0,0 +1,60 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Termtter
4
+ class Status
5
+ def is_member?(group = nil)
6
+ if group
7
+ configatron.plugins.group.groups[group].include? self.user_screen_name
8
+ else
9
+ configatron.plugins.group.groups.values.flatten.include? self.user_screen_name
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ module Termtter::Client
16
+ configatron.plugins.group.
17
+ set_default(:groups, {})
18
+
19
+ def self.find_group_candidates(a, b)
20
+ configatron.plugins.group.groups.keys.map {|k| k.to_s}.
21
+ grep(/^#{Regexp.quote a}/).
22
+ map {|u| b % u }
23
+ end
24
+
25
+ register_command(
26
+ :name => :group,
27
+ :aliases => [:g],
28
+ :exec_proc => lambda {|arg|
29
+ unless arg.empty?
30
+ group_name = arg.to_sym
31
+ if group_name == :all
32
+ group = configatron.plugins.group.groups.values.flatten.uniq
33
+ else
34
+ group = configatron.plugins.group.groups[group_name]
35
+ end
36
+ statuses = group ? public_storage[:log].select { |s|
37
+ group.include?(s.user_screen_name)
38
+ } : []
39
+ call_hooks(statuses, :search)
40
+ else
41
+ configatron.plugins.group.groups.each_pair do |key, value|
42
+ puts "#{key}: #{value.join(',')}"
43
+ end
44
+ end
45
+ },
46
+ :completion_proc => lambda {|cmd, arg|
47
+ find_group_candidates arg, "#{cmd} %s"
48
+ },
49
+ :help => ['group,g GROUPNAME', 'Filter by group members']
50
+ )
51
+
52
+ end
53
+
54
+ # group.rb
55
+ # plugin 'group'
56
+ # configatron.plugins.group.groups = {
57
+ # :rits => %w(hakobe isano hitode909)
58
+ # }
59
+ # NOTE: group.rb needs plugin/log
60
+
@@ -0,0 +1,62 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'tmpdir'
4
+ require 'open-uri'
5
+ require 'uri'
6
+ require 'fileutils'
7
+
8
+ begin
9
+ require 'ruby-growl'
10
+ growl = Growl.new "localhost", "termtter", "termtter status notification"
11
+ rescue LoadError
12
+ growl = nil
13
+ end
14
+
15
+ configatron.plugins.growl.set_default(:icon_cache_dir, "#{Dir.tmpdir}/termtter-icon-cache-dir")
16
+ FileUtils.mkdir_p(configatron.plugins.growl.icon_cache_dir) unless File.exist?(configatron.plugins.growl.icon_cache_dir)
17
+
18
+ def get_icon_path(s)
19
+ cache_file = "%s/%s%s" % [ configatron.plugins.growl.icon_cache_dir,
20
+ s.user_screen_name,
21
+ File.extname(s.user_profile_image_url) ]
22
+ if File.exist?(cache_file) && (File.atime(cache_file) + 24*60*60) > Time.now
23
+ return cache_file
24
+ else
25
+ Thread.new do
26
+ File.open(cache_file, "wb") do |f|
27
+ f << open(URI.escape(s.user_profile_image_url)).read
28
+ end
29
+ end
30
+ return nil
31
+ end
32
+ end
33
+
34
+ queue = []
35
+ Thread.new do
36
+ loop do
37
+ begin
38
+ if s = queue.pop
39
+ unless growl
40
+ arg = ['growlnotify', s.user_screen_name, '-m', s.text.gsub("\n",''), '-n', 'termtter']
41
+ #icon_path = get_icon_path(s)
42
+ #arg += ['--image', icon_path] if icon_path
43
+ system *arg
44
+ else
45
+ growl.notify "termtter status notification", s.text, s.user_screen_name
46
+ end
47
+ end
48
+ rescue => e
49
+ puts e
50
+ puts e.backtrace.join("\n")
51
+ end
52
+ sleep 0.1
53
+ end
54
+ end
55
+
56
+ Termtter::Client.add_hook do |statuses, event|
57
+ if !statuses.empty? && event == :update_friends_timeline
58
+ statuses.reverse.each do |s|
59
+ queue << s
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,59 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'rubygems'
4
+ require 'atomutil'
5
+
6
+ module Termtter::Client
7
+ register_command(
8
+ :name => :hatebu, :aliases => [],
9
+ :exec_proc => lambda {|arg|
10
+ if arg =~ /^(\d+)(.*)$/
11
+ id = $1.strip
12
+ comment = $2.strip
13
+ statuses = public_storage[:log].select { |s| s.id == id }
14
+ unless statuses.empty?
15
+ status = statuses.first
16
+ else
17
+ status = t.show(id).first
18
+ end
19
+ auth = auth = Atompub::Auth::Wsse.new({
20
+ :username => configatron.plugins.hatebu.username,
21
+ :password => configatron.plugins.hatebu.password,
22
+ })
23
+ link = Atom::Link.new({
24
+ :href => "http://twitter.com/#{status.user_screen_name}/status/#{status.id}",
25
+ :rel => 'related',
26
+ :type => 'text/html',
27
+ })
28
+ entry = Atom::Entry.new({
29
+ :link => link,
30
+ :title => 'dummy',
31
+ :summary => comment,
32
+ })
33
+ req = Net::HTTP::Post.new 'http://b.hatena.ne.jp/atom/post'
34
+ req['User-Agent'] = 'Mozilla/5.0'
35
+ req['Content-Type'] = 'application/atom+xml'
36
+ req['Slug'] = 'termtter'
37
+ req.body = entry.to_s
38
+ auth.authorize(req)
39
+ Net::HTTP.start('b.hatena.ne.jp', 80) do |http|
40
+ res = http.request(req)
41
+ end
42
+ end
43
+ },
44
+ :completion_proc => lambda {|cmd, args|
45
+ if args =~ /^(\d*)$/
46
+ find_status_id_candidates $1, "#{cmd} %s"
47
+ end
48
+ },
49
+ :help => ['hatebu ID', 'Hatena bookmark a status']
50
+ )
51
+ end
52
+
53
+ # hatebu.rb
54
+ # hatena bookmark it!
55
+ #
56
+ # configatron.plugins.hatebu.username = 'your-username-on-hatena'
57
+ # configatron.plugins.hatebu.password = 'your-password-on-hatena'
58
+ #
59
+ # hatebu 1114860346 [termtter][����͂�����]mattn++
@@ -0,0 +1,82 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'zlib'
4
+
5
+ configatron.plugins.history.
6
+ set_default(:filename, '~/.termtter_history')
7
+ configatron.plugins.history.
8
+ set_default(:keys, [:log, :users, :status_ids])
9
+ configatron.plugins.history.
10
+ set_default(:max_of_history, 100)
11
+ configatron.plugins.history.
12
+ set_default(:enable_autosave, true)
13
+ configatron.plugins.history.
14
+ set_default(:autosave_interval, 3600)
15
+
16
+ module Termtter::Client
17
+ def self.load_history
18
+ filename = File.expand_path(configatron.plugins.history.filename)
19
+ keys = configatron.plugins.history.keys
20
+
21
+ if File.exist?(filename)
22
+ begin
23
+ history = Marshal.load Zlib::Inflate.inflate(File.read(filename))
24
+ end
25
+ if history
26
+ keys.each do |key|
27
+ public_storage[key] = history[key] if history[key]
28
+ end
29
+ Readline::HISTORY.push *history[:history] if history[:history]
30
+ puts "history loaded(#{File.size(filename)/1000}kb)"
31
+ end
32
+ end
33
+ end
34
+
35
+ def self.save_history
36
+ filename = File.expand_path(configatron.plugins.history.filename)
37
+ keys = configatron.plugins.history.keys
38
+ history = { }
39
+ keys.each do |key|
40
+ history[key] = public_storage[key]
41
+ end
42
+ max_of_history = configatron.plugins.history.max_of_history
43
+ history[:history] = Readline::HISTORY.to_a.reverse.uniq.reverse
44
+ if history[:history].size > max_of_history
45
+ history[:history] = history[:history][-max_of_history..-1]
46
+ end
47
+
48
+ File.open(filename, 'w') do |f|
49
+ f.write Zlib::Deflate.deflate(Marshal.dump(history))
50
+ end
51
+ puts "history saved(#{File.size(filename)/1000}kb)"
52
+ end
53
+
54
+ add_hook do |statuses, event|
55
+ case event
56
+ when :initialize
57
+ load_history
58
+ when :exit
59
+ save_history
60
+ end
61
+ end
62
+
63
+ if configatron.plugins.history.enable_autosave
64
+ Termtter::Client.add_task(:interval => configatron.plugins.history.autosave_interval,
65
+ :after => configatron.plugins.history.autosave_interval) do
66
+ save_history
67
+ end
68
+ end
69
+
70
+ register_command(
71
+ :name => :save,
72
+ :exec_proc => lambda{|arg|
73
+ save_history
74
+ },
75
+ :help => ['save', 'Save hisory']
76
+ )
77
+
78
+
79
+ end
80
+
81
+ # history.rb
82
+ # save log to file
@@ -0,0 +1,18 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ configatron.set_default('plugins.keyword.keywords', [])
4
+
5
+ module Termtter
6
+ class Status
7
+ def has_keyword?
8
+ configatron.plugins.keyword.keywords.find { |k| k === self.text }
9
+ end
10
+ alias :has_keyword :has_keyword?
11
+ end
12
+ end
13
+
14
+ # keyword.rb
15
+ # provides a keyword watching method
16
+ # example config
17
+ # configatron.plugins.stdout.timeline_format = '<%= color(time, 90) %> <%= color(status, s.has_keyword ? 4 : status_color) %> <%= color(id, 90) %>'
18
+ # configatron.plugins.keyword.keywords = [ /motemen/ ]
data/lib/plugin/log.rb ADDED
@@ -0,0 +1,63 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Termtter::Client
4
+ public_storage[:log] = []
5
+ configatron.plugins.log.set_default('max_size', 1/0.0)
6
+ configatron.plugins.log.set_default('print_max_size', 30)
7
+
8
+ add_hook do |statuses, event|
9
+ case event
10
+ when :pre_filter
11
+ public_storage[:log] += statuses
12
+ max_size = configatron.plugins.log.max_size
13
+ if public_storage[:log].size > max_size
14
+ public_storage[:log] = public_storage[:log][-max_size..-1]
15
+ end
16
+ public_storage[:log] = public_storage[:log].uniq.sort_by{|a| a.created_at} if statuses.first
17
+ end
18
+ end
19
+
20
+ register_command(
21
+ :name => :log,
22
+ :exec_proc => lambda{|arg|
23
+ if arg.empty?
24
+ # log
25
+ statuses = public_storage[:log]
26
+ print_max = configatron.plugins.log.print_max_size
27
+ print_max = 0 if statuses.size < print_max
28
+ call_hooks(statuses[-print_max..-1], :search)
29
+ else
30
+ # log (user) (max)
31
+ vars = arg.split(' ')
32
+ print_max = vars.last =~ /^\d+$/ ? vars.pop.to_i : configatron.plugins.log.print_max_size
33
+ id = vars
34
+ statuses = id.first ? public_storage[:log].select{ |s| id.include? s.user_screen_name} : public_storage[:log]
35
+ print_max = 0 if statuses.size < print_max
36
+ call_hooks(statuses[-print_max..-1], :search)
37
+ end
38
+ },
39
+ :completion_proc => lambda {|cmd, arg|
40
+ find_user_candidates arg, "#{cmd} %s"
41
+ },
42
+ :help => [ 'log (USER(S)) (MAX)', 'Show local log of the user(s)']
43
+ )
44
+
45
+ register_command(
46
+ :name => :search_log, :aliases => [:sl],
47
+ :exec_proc => lambda{|arg|
48
+ unless arg.strip.empty?
49
+ pat = Regexp.new arg
50
+ statuses = public_storage[:log].select { |s| s.text =~ pat }
51
+ call_hooks(statuses, :search)
52
+ end
53
+ },
54
+ :help => [ 'search_log WORD', 'Search log for WORD' ]
55
+ )
56
+
57
+ add_command %r'^/(.+)' do |m, t|
58
+ warn '/WORD command will be removed. Use search_log command instead.'
59
+ pat = Regexp.new(m[1])
60
+ statuses = public_storage[:log].select { |s| s.text =~ pat }
61
+ call_hooks(statuses, :search, t)
62
+ end
63
+ end
@@ -0,0 +1,7 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ Termtter::Client.register_hook(
4
+ :name => :modify_arg_hook_sample,
5
+ :points => [:modify_arg_for_update],
6
+ :exec_proc => lambda {|cmd, arg| arg + '\(^o^)/'}
7
+ )
@@ -0,0 +1,26 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ raise 'msagent.rb runs only in windows' if RUBY_PLATFORM.downcase !~ /mswin(?!ce)|mingw|bccwin/
4
+ require 'win32ole'
5
+ require 'kconv'
6
+
7
+ agent = WIN32OLE.new('Agent.Control.2')
8
+ agent.connected = true
9
+ agent.characters.load("Merlin", ENV['WINDIR'] + "\\msagent\\chars\\Merlin.acs")
10
+ achar = agent.characters.character("Merlin")
11
+ achar.languageID = 0x411
12
+ achar.show
13
+
14
+ Termtter::Client.add_hook do |statuses, event, t|
15
+ if event == :exit
16
+ achar.hide
17
+ GC.start
18
+ elsif !statuses.empty? && event == :update_friends_timeline
19
+ statuses.reverse.each do |s|
20
+ req = achar.speak("#{s.user_screen_name}: #{s.text}".tosjis)
21
+ sleep 3
22
+ WIN32OLE_EVENT.message_loop
23
+ achar.stop(req)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,36 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Termtter::Client
4
+ add_help 'multi_reply, mp TEXT', 'reply to multi user'
5
+ add_command /^(multi_reply|mr)\s+(.*)/ do |m, t|
6
+ text = ERB.new(m[2]).result(binding).gsub(/\n/, ' ')
7
+ unless text.empty?
8
+ #targets, _, msg = text.match /(@(.+))*\s+(.+)/
9
+ #targets.split(/\s+/).
10
+ # map {|u| "#{u} #{msg}" }.
11
+ # each do |post|
12
+ # t.update_status(post)
13
+ # puts "=> #{post}"
14
+ # end
15
+ /(@(.+))*\s+(.+)/ =~ text
16
+ if $1
17
+ msg = $3
18
+ text = $1.split(/\s+/).map {|u| "#{u} #{msg}" }
19
+ end
20
+ Array(text).each do |post|
21
+ t.update_status(post)
22
+ puts "=> #{post}"
23
+ end
24
+ #
25
+ end
26
+ end
27
+
28
+ add_completion do |input|
29
+ case input
30
+ when /^(multi_reply|mr)\s+(.*)@([^\s]*)$/
31
+ find_user_candidates $3, "#{$1} #{$2}@%s"
32
+ else
33
+ %w[ mreply mp ].grep(/^#{Regexp.quote input}/)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,17 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ Termtter::Client.add_hook do |statuses, event|
4
+ if !statuses.empty? && event == :update_friends_timeline
5
+ max = 10
6
+
7
+ text = statuses.take(max).map {|s|
8
+ status_text = CGI.escapeHTML(s.text)
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>"
11
+ }.join("\n")
12
+
13
+ text << %Q|\n<a href="http://twitter.com/">more...</a>| if statuses.size > max
14
+
15
+ system 'notify-send', 'Termtter', text, '-t', '60000'
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Termtter::Client
4
+ register_macro(:otsune, "update @%s 頭蓋骨の中身がお気の毒です.",
5
+ :help => ['otsune {SCREENNAME}', 'update "@{SCREENNAME} 頭蓋骨の中身がお気の毒です"'],
6
+ :completion_proc => lambda {|cmd, args|
7
+ find_user_candidates args, "#{cmd} %s"
8
+ }
9
+ )
10
+ end
11
+
12
+ module Termtter::Client
13
+ register_macro(:otsnue, "update @%s 頭蓋骨の中身がお気の毒です.",
14
+ :help => ['otsnue {SCREENNAME}', 'update @%s 頭が気の毒です.'],
15
+ :completion_proc => lambda {|cmd, args|
16
+ find_user_candidates args, "#{cmd} %s"
17
+ }
18
+ )
19
+ end
20
+
21
+ # vim: fenc=utf8
@@ -0,0 +1,35 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+
4
+ module Termtter::Client
5
+ configatron.plugins.outputz.set_default(:uri, 'termtter://twitter.com/status/update')
6
+
7
+ key = configatron.plugins.outputz.secret_key
8
+ if key.instance_of? Configatron::Store
9
+ puts 'Need your secret key'
10
+ puts 'please set configatron.plugins.outputz.secret_key'
11
+ else
12
+ add_command /^(update|u)\s+(.*)/ do |m, t|
13
+ text = ERB.new(m[2]).result(binding).gsub(/\n/, ' ')
14
+ unless text.empty?
15
+ t.update_status(text)
16
+ puts "=> #{text}"
17
+ end
18
+ t.instance_variable_get('@connection').
19
+ start('outputz.com', 80) do |http|
20
+ key = CGI.escape key
21
+ uri = CGI.escape configatron.plugins.outputz.uri
22
+ size = text.split(//).size
23
+ http.post('/api/post', "key=#{key}&uri=#{uri}&size=#{size}")
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ # outputz.rb
30
+ # a plugin that report to outputz your post
31
+ #
32
+ # settings (note: must this order)
33
+ # configatron.plugins.outputz.secret_key = 'your secret key'
34
+ # plugin 'outputz'
35
+
@@ -0,0 +1,3 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ Termtter::Client.pause
@@ -0,0 +1,53 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Termtter::Client
4
+
5
+ public_storage[:plugins] = Dir["#{File.dirname(__FILE__)}/*.rb"].map do |f|
6
+ f.match(%r|([^/]+).rb$|)[1]
7
+ end
8
+
9
+ register_command(
10
+ :name => :plugin, :aliases => [],
11
+ :exec_proc => lambda {|arg|
12
+ begin
13
+ result = plugin arg.strip
14
+ rescue LoadError
15
+ ensure
16
+ puts "=> #{result.inspect}"
17
+ end
18
+ },
19
+ :completion_proc => lambda {|cmd, args|
20
+ find_user_candidates args, "#{cmd} %s"
21
+ unless args.empty?
22
+ find_plugin_candidates args, "#{cmd} %s"
23
+ else
24
+ public_storage[:plugins].sort
25
+ end
26
+ },
27
+ :help => ['plugin FILE', 'Load a plugin']
28
+ )
29
+
30
+ register_command(
31
+ :name => :plugins, :aliases => [],
32
+ :exec_proc => lambda {|arg|
33
+ puts public_storage[:plugins].sort.join("\n")
34
+ },
35
+ :help => ['plugins', 'Show list of plugins']
36
+ )
37
+
38
+ def self.find_plugin_candidates(a, b)
39
+ public_storage[:plugins].
40
+ grep(/^#{Regexp.quote a}/i).
41
+ map {|u| b % u }
42
+ end
43
+ end
44
+
45
+ # plugin.rb
46
+ # a dynamic plugin loader
47
+ # example
48
+ # > u <%= not erbed %>
49
+ # => <%= not erbed %>
50
+ # > plugin erb
51
+ # => true
52
+ # > u <%= 1 + 2 %>
53
+ # => 3
@@ -0,0 +1,9 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ Termtter::Client.register_hook(
4
+ :name => :post_exec_hook_sample,
5
+ :points => [:post_exec_list],
6
+ :exec_proc => lambda {|cmd, arg, result|
7
+ p result
8
+ }
9
+ )
@@ -0,0 +1,9 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ Termtter::Client.register_hook(
4
+ :name => :pre_exec_hook_sample,
5
+ :points => [:pre_exec_update],
6
+ :exec_proc => lambda {|cmd, arg|
7
+ false if /^y?$/i !~ Readline.readline("update? #{arg} [Y/n] ", false)
8
+ }
9
+ )