termtter 0.8.3
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/README.rdoc +97 -0
- data/Rakefile +46 -0
- data/bin/kill_termtter +22 -0
- data/bin/termtter +7 -0
- data/lib/filter/en2ja.rb +11 -0
- data/lib/filter/english.rb +8 -0
- data/lib/filter/expand-tinyurl.rb +24 -0
- data/lib/filter/fib.rb +15 -0
- data/lib/filter/ignore.rb +19 -0
- data/lib/filter/reply.rb +8 -0
- data/lib/filter/reverse.rb +13 -0
- data/lib/filter/url_addspace.rb +16 -0
- data/lib/filter/yhara.rb +20 -0
- data/lib/plugin/april_fool.rb +15 -0
- data/lib/plugin/bomb.rb +29 -0
- data/lib/plugin/clear.rb +14 -0
- data/lib/plugin/confirm.rb +9 -0
- data/lib/plugin/cool.rb +10 -0
- data/lib/plugin/devel.rb +13 -0
- data/lib/plugin/english.rb +59 -0
- data/lib/plugin/erb.rb +17 -0
- data/lib/plugin/favorite.rb +75 -0
- data/lib/plugin/fib.rb +8 -0
- data/lib/plugin/filter.rb +69 -0
- data/lib/plugin/follow.rb +56 -0
- data/lib/plugin/graduatter.rb +9 -0
- data/lib/plugin/grass.rb +27 -0
- data/lib/plugin/group.rb +60 -0
- data/lib/plugin/growl.rb +62 -0
- data/lib/plugin/hatebu.rb +59 -0
- data/lib/plugin/history.rb +82 -0
- data/lib/plugin/keyword.rb +18 -0
- data/lib/plugin/log.rb +63 -0
- data/lib/plugin/modify_arg_hook_sample.rb +7 -0
- data/lib/plugin/msagent.rb +26 -0
- data/lib/plugin/multi_reply.rb +36 -0
- data/lib/plugin/notify-send.rb +17 -0
- data/lib/plugin/otsune.rb +21 -0
- data/lib/plugin/outputz.rb +35 -0
- data/lib/plugin/pause.rb +3 -0
- data/lib/plugin/plugin.rb +53 -0
- data/lib/plugin/post_exec_hook_sample.rb +9 -0
- data/lib/plugin/pre_exec_hook_sample.rb +9 -0
- data/lib/plugin/primes.rb +23 -0
- data/lib/plugin/quicklook.rb +38 -0
- data/lib/plugin/reblog.rb +40 -0
- data/lib/plugin/reload.rb +3 -0
- data/lib/plugin/say.rb +24 -0
- data/lib/plugin/scrape.rb +41 -0
- data/lib/plugin/screen.rb +24 -0
- data/lib/plugin/shell.rb +14 -0
- data/lib/plugin/sl.rb +48 -0
- data/lib/plugin/spam.rb +9 -0
- data/lib/plugin/standard_plugins.rb +269 -0
- data/lib/plugin/stdout.rb +62 -0
- data/lib/plugin/system_status.rb +33 -0
- data/lib/plugin/translation.rb +28 -0
- data/lib/plugin/update_editor.rb +53 -0
- data/lib/plugin/uri-open.rb +69 -0
- data/lib/plugin/wassr_post.rb +22 -0
- data/lib/plugin/yhara.rb +148 -0
- data/lib/plugin/yonda.rb +20 -0
- data/lib/termtter/api.rb +14 -0
- data/lib/termtter/client.rb +399 -0
- data/lib/termtter/command.rb +77 -0
- data/lib/termtter/connection.rb +39 -0
- data/lib/termtter/hook.rb +18 -0
- data/lib/termtter/status.rb +26 -0
- data/lib/termtter/task.rb +16 -0
- data/lib/termtter/task_manager.rb +116 -0
- data/lib/termtter/twitter.rb +173 -0
- data/lib/termtter/user.rb +13 -0
- data/lib/termtter/version.rb +3 -0
- data/lib/termtter.rb +157 -0
- data/spec/plugin/cool_spec.rb +10 -0
- data/spec/plugin/fib_spec.rb +16 -0
- data/spec/plugin/filter_spec.rb +18 -0
- data/spec/plugin/plugin_spec.rb +25 -0
- data/spec/plugin/shell_spec.rb +10 -0
- data/spec/plugin/spam_spec.rb +17 -0
- data/spec/plugin/standard_plugins_spec.rb +31 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/termtter/client_spec.rb +175 -0
- data/spec/termtter/command_spec.rb +161 -0
- data/spec/termtter/task_manager_spec.rb +78 -0
- data/spec/termtter/task_spec.rb +22 -0
- data/spec/termtter/user_spec.rb +27 -0
- data/spec/termtter_spec.rb +43 -0
- data/test/friends_timeline.json +5 -0
- data/test/search.json +8 -0
- data/test/test_termtter.rb +86 -0
- 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
|
data/lib/plugin/grass.rb
ADDED
@@ -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
|
data/lib/plugin/group.rb
ADDED
@@ -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
|
+
|
data/lib/plugin/growl.rb
ADDED
@@ -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,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
|
+
|
data/lib/plugin/pause.rb
ADDED
@@ -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
|