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.
- 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,173 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'highline'
|
4
|
+
require 'time'
|
5
|
+
|
6
|
+
module Termtter
|
7
|
+
class Twitter
|
8
|
+
|
9
|
+
def initialize(user_name, password, connection, host = "twitter.com")
|
10
|
+
@user_name = user_name
|
11
|
+
@password = password
|
12
|
+
@connection = connection
|
13
|
+
@host = host
|
14
|
+
end
|
15
|
+
|
16
|
+
def update_status(status)
|
17
|
+
@connection.start(@host, @connection.port) do |http|
|
18
|
+
uri = '/statuses/update.xml'
|
19
|
+
http.request(post_request(uri), "status=#{CGI.escape(status)}&source=#{APP_NAME}")
|
20
|
+
end
|
21
|
+
status
|
22
|
+
end
|
23
|
+
|
24
|
+
def direct_message(user, status)
|
25
|
+
@connection.start(@host, @connection.port) do |http|
|
26
|
+
uri = '/direct_messages/new.xml'
|
27
|
+
http.request(post_request(uri), "user=#{CGI.escape(user)}&text=#{CGI.escape(status)}&source=#{APP_NAME}")
|
28
|
+
end
|
29
|
+
[user, status]
|
30
|
+
end
|
31
|
+
|
32
|
+
def get_user_profile(screen_name)
|
33
|
+
result = fetch_as_json(url_for("/users/show/#{screen_name}.json"))
|
34
|
+
return hash_to_user(result)
|
35
|
+
end
|
36
|
+
|
37
|
+
def get_friends_timeline(since_id = nil)
|
38
|
+
uri = url_for("/statuses/friends_timeline.json")
|
39
|
+
uri << "?since_id=#{since_id}" if since_id
|
40
|
+
return get_timeline(uri)
|
41
|
+
end
|
42
|
+
|
43
|
+
def get_user_timeline(screen_name)
|
44
|
+
return get_timeline(url_for("/statuses/user_timeline/#{screen_name}.json"))
|
45
|
+
rescue OpenURI::HTTPError => e
|
46
|
+
puts "No such user: #{screen_name}"
|
47
|
+
nears = near_users(screen_name)
|
48
|
+
puts "near users: #{nears}" unless nears.empty?
|
49
|
+
return []
|
50
|
+
end
|
51
|
+
|
52
|
+
def search(query)
|
53
|
+
results = fetch_as_json(search_url_for("/search.json?q=#{CGI.escape(query)}"))['results']
|
54
|
+
return results.map do |s|
|
55
|
+
status = Status.new
|
56
|
+
status.id = s['id']
|
57
|
+
status.text = CGI.unescapeHTML(s['text']).gsub(/(\n|\r)/, '').gsub(/#{Regexp.escape(query)}/i, color(color('\0', 41), 37))
|
58
|
+
status.created_at = Time.parse(s["created_at"])
|
59
|
+
status.user_screen_name = s['from_user']
|
60
|
+
status
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def show(id, rth = false)
|
65
|
+
get_status = lambda { get_timeline(url_for("/statuses/show/#{id}.json"))[0] }
|
66
|
+
statuses = []
|
67
|
+
statuses << status = Array(Client.public_storage[:log]).detect(get_status) {|s| s.id == id.to_i }
|
68
|
+
statuses << show(id, true) if rth && id = status.in_reply_to_status_id
|
69
|
+
statuses.flatten
|
70
|
+
end
|
71
|
+
|
72
|
+
def replies
|
73
|
+
return get_timeline(url_for("/statuses/replies.json"))
|
74
|
+
end
|
75
|
+
|
76
|
+
def followers
|
77
|
+
users = []
|
78
|
+
page = 0
|
79
|
+
begin
|
80
|
+
users += tmp = fetch_as_json(url_for("/statuses/followers.json?page=#{page+=1}"))
|
81
|
+
end until tmp.empty?
|
82
|
+
return users.map{|u| hash_to_user(u)}
|
83
|
+
end
|
84
|
+
|
85
|
+
def get_timeline(uri)
|
86
|
+
data = fetch_as_json(uri)
|
87
|
+
data = [data] unless data.instance_of? Array
|
88
|
+
return data.map do |s|
|
89
|
+
status = Status.new
|
90
|
+
status.created_at = Time.parse(s["created_at"])
|
91
|
+
%w(id text truncated in_reply_to_status_id in_reply_to_user_id in_reply_to_screen_name).each do |key|
|
92
|
+
status.__send__("#{key}=".to_sym, s[key])
|
93
|
+
end
|
94
|
+
%w(id name screen_name url profile_image_url).each do |key|
|
95
|
+
status.__send__("user_#{key}=".to_sym, s["user"][key])
|
96
|
+
end
|
97
|
+
status.text = CGI.unescapeHTML(status.text).gsub(/(\n|\r)/, '')
|
98
|
+
status
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# note: APILimit.reset_time_in_seconds == APILimit.reset_time.to_i
|
103
|
+
APILIMIT = Struct.new("APILimit", :reset_time, :reset_time_in_seconds, :remaining_hits, :hourly_limit)
|
104
|
+
def get_rate_limit_status
|
105
|
+
data = fetch_as_json(url_for("/account/rate_limit_status.json"))
|
106
|
+
reset_time = Time.parse(data['reset_time'])
|
107
|
+
reset_time_in_seconds = data['reset_time_in_seconds'].to_i
|
108
|
+
|
109
|
+
APILIMIT.new(reset_time, reset_time_in_seconds, data['remaining_hits'], data['hourly_limit'])
|
110
|
+
end
|
111
|
+
|
112
|
+
alias :api_limit :get_rate_limit_status
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
def hash_to_user(hash)
|
117
|
+
user = User.new
|
118
|
+
%w[ name favourites_count url id description protected utc_offset time_zone
|
119
|
+
screen_name notifications statuses_count followers_count friends_count
|
120
|
+
profile_image_url location following created_at
|
121
|
+
].each do |attr|
|
122
|
+
user.__send__("#{attr}=".to_sym, hash[attr])
|
123
|
+
end
|
124
|
+
return user
|
125
|
+
end
|
126
|
+
|
127
|
+
def fetch_as_json(uri)
|
128
|
+
JSON.parse(open_uri(uri).read)
|
129
|
+
end
|
130
|
+
|
131
|
+
def open_uri(uri)
|
132
|
+
return open(uri, :http_basic_authentication => [user_name, password], :proxy => @connection.proxy_uri)
|
133
|
+
end
|
134
|
+
|
135
|
+
def url_for(path)
|
136
|
+
return "#{@connection.protocol}://#{@host}/#{path.sub(/^\//, '')}"
|
137
|
+
end
|
138
|
+
|
139
|
+
def search_url_for(path)
|
140
|
+
return "#{@connection.protocol}://search.#{@host}/#{path.sub(/^\//, '')}"
|
141
|
+
end
|
142
|
+
|
143
|
+
def user_name
|
144
|
+
unless @user_name.instance_of? String
|
145
|
+
Termtter::Client.create_highline.ask('your twitter username: ')
|
146
|
+
end
|
147
|
+
@user_name
|
148
|
+
end
|
149
|
+
|
150
|
+
def password
|
151
|
+
unless @password.instance_of? String
|
152
|
+
@password = Termtter::Client.create_highline.ask('your twitter password: ') { |q| q.echo = false }
|
153
|
+
end
|
154
|
+
@password
|
155
|
+
end
|
156
|
+
|
157
|
+
def near_users(screen_name)
|
158
|
+
Client::public_storage[:users].select {|user|
|
159
|
+
/#{user}/i =~ screen_name || /#{screen_name}/i =~ user
|
160
|
+
}.join(', ')
|
161
|
+
end
|
162
|
+
|
163
|
+
def post_request(uri)
|
164
|
+
req = Net::HTTP::Post.new(uri)
|
165
|
+
req.basic_auth(user_name, password)
|
166
|
+
req.add_field('User-Agent', 'Termtter http://github.com/jugyo/termtter')
|
167
|
+
req.add_field('X-Twitter-Client', 'Termtter')
|
168
|
+
req.add_field('X-Twitter-Client-URL', 'http://github.com/jugyo/termtter')
|
169
|
+
req.add_field('X-Twitter-Client-Version', '0.1')
|
170
|
+
req
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Termtter
|
4
|
+
class User
|
5
|
+
%w[ name favourites_count url id description protected utc_offset time_zone
|
6
|
+
screen_name notifications statuses_count followers_count friends_count
|
7
|
+
profile_image_url location following created_at
|
8
|
+
].each do |attr|
|
9
|
+
attr_accessor attr.to_sym
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
data/lib/termtter.rb
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
4
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require 'json'
|
8
|
+
require 'net/https'
|
9
|
+
require 'open-uri'
|
10
|
+
require 'cgi'
|
11
|
+
require 'readline'
|
12
|
+
require 'enumerator'
|
13
|
+
require 'configatron'
|
14
|
+
|
15
|
+
Thread.abort_on_exception = true
|
16
|
+
|
17
|
+
configatron.set_default(:update_interval, 300)
|
18
|
+
configatron.set_default(:prompt, '> ')
|
19
|
+
configatron.set_default(:enable_ssl, false)
|
20
|
+
configatron.proxy.set_default(:port, '8080')
|
21
|
+
|
22
|
+
require 'termtter/twitter'
|
23
|
+
require 'termtter/connection'
|
24
|
+
require 'termtter/status'
|
25
|
+
require 'termtter/user'
|
26
|
+
require 'termtter/command'
|
27
|
+
require 'termtter/hook'
|
28
|
+
require 'termtter/task'
|
29
|
+
require 'termtter/task_manager'
|
30
|
+
require 'termtter/client'
|
31
|
+
require 'termtter/api'
|
32
|
+
require 'termtter/version'
|
33
|
+
|
34
|
+
module Termtter
|
35
|
+
APP_NAME = 'termtter'
|
36
|
+
CONF_FILE = '~/.termtterrc' # still does not use
|
37
|
+
CONF_DIR = '~/.termtter' # still does not use
|
38
|
+
end
|
39
|
+
|
40
|
+
if RUBY_VERSION < '1.8.7'
|
41
|
+
class Array
|
42
|
+
def take(n) self[0...n] end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def win?
|
47
|
+
RUBY_PLATFORM.downcase =~ /mswin(?!ce)|mingw|bccwin/
|
48
|
+
end
|
49
|
+
|
50
|
+
if win?
|
51
|
+
require 'iconv'
|
52
|
+
require 'Win32API'
|
53
|
+
$wGetACP = Win32API.new('kernel32','GetACP','','I')
|
54
|
+
|
55
|
+
module Readline
|
56
|
+
$iconv_sj_to_u8 = Iconv.new('UTF-8', "CP#{$wGetACP.call()}")
|
57
|
+
alias :old_readline :readline
|
58
|
+
def readline(*a)
|
59
|
+
str = old_readline(*a)
|
60
|
+
out = ''
|
61
|
+
loop do
|
62
|
+
begin
|
63
|
+
out << $iconv_sj_to_u8.iconv(str)
|
64
|
+
break
|
65
|
+
rescue Iconv::Failure
|
66
|
+
out << "#{$!.success}?"
|
67
|
+
str = $!.failed[1..-1]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
return out
|
71
|
+
end
|
72
|
+
module_function :old_readline, :readline
|
73
|
+
end
|
74
|
+
|
75
|
+
$wSetConsoleTextAttribute = Win32API.new('kernel32','SetConsoleTextAttribute','II','I')
|
76
|
+
$wGetConsoleScreenBufferInfo = Win32API.new("kernel32", "GetConsoleScreenBufferInfo", ['l', 'p'], 'i')
|
77
|
+
$wGetStdHandle = Win32API.new('kernel32','GetStdHandle','I','I')
|
78
|
+
$wGetACP = Win32API.new('kernel32','GetACP','','I')
|
79
|
+
|
80
|
+
$hStdOut = $wGetStdHandle.call(0xFFFFFFF5)
|
81
|
+
lpBuffer = ' ' * 22
|
82
|
+
$wGetConsoleScreenBufferInfo.call($hStdOut, lpBuffer)
|
83
|
+
$oldColor = lpBuffer.unpack('SSSSSssssSS')[4]
|
84
|
+
|
85
|
+
$colorMap = {
|
86
|
+
0 => 0x07|0x00|0x00|0x00, # black/white
|
87
|
+
37 => 0x08|0x00|0x00|0x00, # white/intensity
|
88
|
+
31 => 0x04|0x08|0x00|0x00, # red/red
|
89
|
+
32 => 0x02|0x08|0x00|0x00, # green/green
|
90
|
+
33 => 0x06|0x08|0x00|0x00, # yellow/yellow
|
91
|
+
34 => 0x01|0x08|0x00|0x00, # blue/blue
|
92
|
+
35 => 0x05|0x08|0x00|0x00, # magenta/purple
|
93
|
+
36 => 0x03|0x08|0x00|0x00, # cyan/aqua
|
94
|
+
39 => 0x07, # default
|
95
|
+
40 => 0x00|0x00|0xf0|0x00, # background:white
|
96
|
+
41 => 0x07|0x00|0x40|0x00, # background:red
|
97
|
+
42 => 0x07|0x00|0x20|0x00, # background:green
|
98
|
+
43 => 0x07|0x00|0x60|0x00, # background:yellow
|
99
|
+
44 => 0x07|0x00|0x10|0x00, # background:blue
|
100
|
+
45 => 0x07|0x00|0x50|0x80, # background:magenta
|
101
|
+
46 => 0x07|0x00|0x30|0x80, # background:cyan
|
102
|
+
47 => 0x07|0x00|0x70|0x80, # background:gray
|
103
|
+
49 => 0x70, # default
|
104
|
+
90 => 0x07|0x00|0x00|0x00, # erase/white
|
105
|
+
}
|
106
|
+
$iconv_u8_to_sj = Iconv.new("CP#{$wGetACP.call()}", 'UTF-8')
|
107
|
+
def print(str)
|
108
|
+
str.to_s.gsub("\xef\xbd\x9e", "\xe3\x80\x9c").split(/(\e\[\d*[a-zA-Z])/).each do |token|
|
109
|
+
case token
|
110
|
+
when /\e\[(\d+)m/
|
111
|
+
$wSetConsoleTextAttribute.call $hStdOut, $colorMap[$1.to_i].to_i
|
112
|
+
when /\e\[\d*[a-zA-Z]/
|
113
|
+
# do nothing
|
114
|
+
else
|
115
|
+
loop do
|
116
|
+
begin
|
117
|
+
STDOUT.print $iconv_u8_to_sj.iconv(token)
|
118
|
+
break
|
119
|
+
rescue Iconv::Failure
|
120
|
+
STDOUT.print "#{$!.success}?"
|
121
|
+
token = $!.failed[1..-1]
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
$wSetConsoleTextAttribute.call $hStdOut, $oldColor
|
127
|
+
$iconv_u8_to_sj.iconv(nil)
|
128
|
+
end
|
129
|
+
def puts(str)
|
130
|
+
print str
|
131
|
+
STDOUT.puts
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def plugin(s, init = {})
|
136
|
+
unless init.empty?
|
137
|
+
init.each do |key, value|
|
138
|
+
eval("configatron.plugins.#{s}").__send__("#{key}=", value)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
require "plugin/#{s}"
|
142
|
+
rescue => e
|
143
|
+
Termtter::Client.handle_error(e)
|
144
|
+
end
|
145
|
+
|
146
|
+
def filter(s)
|
147
|
+
load "filter/#{s}.rb"
|
148
|
+
rescue => e
|
149
|
+
Termtter::Client.handle_error(e)
|
150
|
+
else
|
151
|
+
Termtter::Client.public_storage[:filters] ||= []
|
152
|
+
Termtter::Client.public_storage[:filters] << s
|
153
|
+
true
|
154
|
+
end
|
155
|
+
|
156
|
+
$:.unshift(Termtter::CONF_DIR) # still does not use
|
157
|
+
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
4
|
+
|
5
|
+
describe Termtter::Client, 'when the plugin cool is loaded' do
|
6
|
+
it 'should add something about cool' do
|
7
|
+
Termtter::Client.should_receive(:register_macro)
|
8
|
+
plugin 'cool'
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
4
|
+
|
5
|
+
describe Termtter::Client, 'when the plugin fib is loaded' do
|
6
|
+
it 'should add command fib' do
|
7
|
+
Termtter::Client.should_receive(:add_command).with(/^fib\s+(\d+)/)
|
8
|
+
Termtter::Client.should_receive(:add_command).with(/^fibyou\s(\w+)\s(\d+)/)
|
9
|
+
plugin 'fib'
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should define fib method' do
|
13
|
+
plugin 'fib'
|
14
|
+
(0..10).map {|i| fib i }.should == [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
4
|
+
|
5
|
+
module Termtter
|
6
|
+
describe Client, 'when the filter plugin is loaded' do
|
7
|
+
it 'should add command filter, filters and unfilter' do
|
8
|
+
Termtter::Client.should_receive(:register_command).exactly(3)
|
9
|
+
plugin 'filter'
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should set public_storage[:filters]' do
|
13
|
+
plugin 'filter'
|
14
|
+
Client::public_storage.keys.should be_include(:filters)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/../../lib/termtter'
|
4
|
+
|
5
|
+
module Termtter
|
6
|
+
describe Client, 'when the plugin plugin is loaded' do
|
7
|
+
it 'should add command plugin and plugins' do
|
8
|
+
Termtter::Client.should_receive(:register_command).twice
|
9
|
+
plugin 'plugin'
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should set public_storage[:plugins]' do
|
13
|
+
plugin 'plugin'
|
14
|
+
Client::public_storage[:plugins].should_not be_empty
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'after the plugin plugin is loaded' do
|
18
|
+
before { plugin 'plugin' }
|
19
|
+
|
20
|
+
it 'should load the given plugin in the command plugin'
|
21
|
+
# hmm... How can I write it...?
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
4
|
+
|
5
|
+
describe Termtter::Client, 'when the plugin shell is loaded' do
|
6
|
+
it 'should add command shell' do
|
7
|
+
Termtter::Client.should_receive(:register_command)
|
8
|
+
plugin 'shell'
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
4
|
+
|
5
|
+
describe Termtter::Client, 'when the plugin spam is loaded' do
|
6
|
+
it 'should add command spam and post immediately' do
|
7
|
+
connection = mock('connection', :null_object => true)
|
8
|
+
t = Termtter::Twitter.new('a', 'b', connection)
|
9
|
+
Termtter::Twitter.should_receive(:new).and_return(t)
|
10
|
+
t.should_receive(:update_status).with('*super spam time*')
|
11
|
+
|
12
|
+
Termtter::Client.should_receive(:clear_commands)
|
13
|
+
Termtter::Client.should_receive(:add_command).with(/.+/)
|
14
|
+
plugin 'spam'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
4
|
+
plugin 'standard_plugins'
|
5
|
+
|
6
|
+
module Termtter
|
7
|
+
describe Client do
|
8
|
+
it 'shold return registerd commands' do
|
9
|
+
[
|
10
|
+
[:update, [:u]], [:direct, [:d]],
|
11
|
+
[:profile, [:p]], [:list, [:l]],
|
12
|
+
[:search, [:s]], [:replies, [:r]],
|
13
|
+
[:show, [ ]], [:shows, [ ]],
|
14
|
+
[:limit, [:lm]], [:pause, [ ]],
|
15
|
+
[:resume, [ ]], [:exit, [:e]],
|
16
|
+
].each do |name, aliases|
|
17
|
+
command = Client.get_command(name)
|
18
|
+
command.name.should == name
|
19
|
+
command.aliases.should == aliases
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should return candidates when call find_status_id_candidates' do
|
24
|
+
Client.public_storage[:status_ids] = %w[1 2 22 3 4 5]
|
25
|
+
Client.find_status_id_candidates("1", "%s").should == ["1"]
|
26
|
+
Client.find_status_id_candidates("2", "%s").should == ["2", "22"]
|
27
|
+
#TODO: more spec for like "jugyo:1113830"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
4
|
+
|
5
|
+
module Termtter
|
6
|
+
|
7
|
+
describe Client do
|
8
|
+
|
9
|
+
it 'should take new_command' do
|
10
|
+
command = Command.new(:name => :test)
|
11
|
+
Client.register_command(command)
|
12
|
+
Client.get_command(:test).should == command
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should take command as Hash' do
|
16
|
+
Client.register_command(:name => :test)
|
17
|
+
Client.get_command(:test).name.should == :test
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should call new_command' do
|
21
|
+
command_arg = nil
|
22
|
+
command = Command.new(:name => :test, :exec_proc => lambda {|arg| command_arg = arg})
|
23
|
+
Client.register_command(command)
|
24
|
+
command_arg.should == nil
|
25
|
+
|
26
|
+
[
|
27
|
+
['test', ''],
|
28
|
+
['test foo bar', 'foo bar'],
|
29
|
+
['test foo bar ', 'foo bar'],
|
30
|
+
['test foo bar ', 'foo bar'],
|
31
|
+
].each do |input, args|
|
32
|
+
Client.call_commands(input, nil)
|
33
|
+
command_arg.should == args
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should take new_hook' do
|
38
|
+
hook = Hook.new(:name => :test)
|
39
|
+
Client.register_hook(hook)
|
40
|
+
Client.get_hook(:test).should == hook
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should take hook as Hash' do
|
44
|
+
Client.register_hook(:name => :test)
|
45
|
+
Client.get_hook(:test).name.should == :test
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should call new_hook' do
|
49
|
+
hook_called = false
|
50
|
+
Client.register_hook(:name => :test1, :points => [:point1], :exec_proc => lambda {hook_called = true})
|
51
|
+
hook_called.should == false
|
52
|
+
Client.call_new_hooks(:point1)
|
53
|
+
hook_called.should == true
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should call new_hook with args' do
|
57
|
+
arg1 = nil
|
58
|
+
arg2 = nil
|
59
|
+
Client.register_hook(:name => :test1, :points => [:point1], :exec_proc => lambda {|a1, a2| arg1 = a1; arg2 = a2})
|
60
|
+
arg1.should == nil
|
61
|
+
arg2.should == nil
|
62
|
+
Client.call_new_hooks(:point1, 'foo', 'bar')
|
63
|
+
arg1.should == 'foo'
|
64
|
+
arg2.should == 'bar'
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should return hooks when call get_hooks' do
|
68
|
+
hook1 = Client.register_hook(:name => :test1, :points => [:point1])
|
69
|
+
hook2 = Client.register_hook(:name => :test2, :points => [:point1])
|
70
|
+
hook3 = Client.register_hook(:name => :test3, :points => [:point2])
|
71
|
+
|
72
|
+
hooks = Client.get_hooks(:point1)
|
73
|
+
hooks.size.should == 2
|
74
|
+
hooks.include?(hook1).should == true
|
75
|
+
hooks.include?(hook2).should == true
|
76
|
+
hooks.include?(hook3).should == false
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should call decide_arg hooks' do
|
80
|
+
input_command = nil
|
81
|
+
input_arg = nil
|
82
|
+
decided_arg = nil
|
83
|
+
Client.register_hook( :name => :test1,
|
84
|
+
:points => [:modify_arg_for_update],
|
85
|
+
:exec_proc => lambda {|cmd, arg| input_command = cmd; input_arg = arg; arg.upcase})
|
86
|
+
Client.register_hook( :name => :test2,
|
87
|
+
:points => [:pre_exec_update],
|
88
|
+
:exec_proc => lambda {|cmd, arg| decided_arg = arg})
|
89
|
+
Client.register_command(:name => :update, :aliases => [:u])
|
90
|
+
|
91
|
+
input_command.should == nil
|
92
|
+
input_arg.should == nil
|
93
|
+
decided_arg.should == nil
|
94
|
+
Client.call_commands('u foo')
|
95
|
+
input_command.should == 'u'
|
96
|
+
input_arg.should == 'foo'
|
97
|
+
decided_arg.should == 'FOO'
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'should call pre_exec hooks' do
|
101
|
+
hook_called = false
|
102
|
+
Client.register_hook( :name => :test,
|
103
|
+
:points => [:pre_exec_update],
|
104
|
+
:exec_proc => lambda {|cmd, arg| hook_called = true})
|
105
|
+
Client.register_command(:name => :update)
|
106
|
+
|
107
|
+
hook_called.should == false
|
108
|
+
Client.call_commands('update foo')
|
109
|
+
hook_called.should == true
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'should able to cancel exec command' do
|
113
|
+
command_called = false
|
114
|
+
Client.register_hook( :name => :test,
|
115
|
+
:points => [:pre_exec_update],
|
116
|
+
:exec_proc => lambda {|cmd, arg| false})
|
117
|
+
Client.register_command(:name => :update, :exec_proc => lambda {|cmd, arg| command_called = true})
|
118
|
+
|
119
|
+
command_called.should == false
|
120
|
+
Client.call_commands('update foo')
|
121
|
+
command_called.should == false
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'should call post_exec hooks' do
|
125
|
+
command_result = nil
|
126
|
+
Client.register_hook( :name => :test,
|
127
|
+
:points => [:post_exec_update],
|
128
|
+
:exec_proc => lambda {|cmd, arg, result| command_result = result })
|
129
|
+
Client.register_command(:name => :update, :exec_proc => lambda {|arg| 'foo'})
|
130
|
+
|
131
|
+
command_result.should == nil
|
132
|
+
Client.call_commands('update foo')
|
133
|
+
command_result.should == 'foo'
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'should call exit hooks' do
|
137
|
+
hook_called = false
|
138
|
+
Client.register_hook(
|
139
|
+
:name => :test,
|
140
|
+
:points => [:exit],
|
141
|
+
:exec_proc => lambda { hook_called = true }
|
142
|
+
)
|
143
|
+
|
144
|
+
hook_called.should == false
|
145
|
+
Client.exit
|
146
|
+
hook_called.should == true
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'should call plural hooks' do
|
150
|
+
hook1_called = false
|
151
|
+
hook2_called = false
|
152
|
+
Client.register_hook(:name => :hook1, :points => [:exit], :exec_proc => lambda {hook1_called = true})
|
153
|
+
Client.register_hook(:name => :hook2, :points => [:exit], :exec_proc => lambda {hook2_called = true})
|
154
|
+
|
155
|
+
hook1_called.should == false
|
156
|
+
hook2_called.should == false
|
157
|
+
Client.exit
|
158
|
+
hook1_called.should == true
|
159
|
+
hook2_called.should == true
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'should able to override hooks' do
|
163
|
+
hook1_called = false
|
164
|
+
hook2_called = false
|
165
|
+
Client.register_hook(:name => :hook, :points => [:exit], :exec_proc => lambda {hook1_called = true})
|
166
|
+
Client.register_hook(:name => :hook, :points => [:exit], :exec_proc => lambda {hook2_called = true})
|
167
|
+
|
168
|
+
hook1_called.should == false
|
169
|
+
hook2_called.should == false
|
170
|
+
Client.exit
|
171
|
+
hook1_called.should == false
|
172
|
+
hook2_called.should == true
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|