termtter 0.8.3

Sign up to get free protection for your applications and to get access to all the features.
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
+ )