rhaiker 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.ja.txt +3 -0
- data/History.txt +4 -0
- data/License.txt +20 -0
- data/Manifest.txt +34 -0
- data/README.ja.txt +34 -0
- data/README.txt +51 -0
- data/Rakefile +5 -0
- data/config/hoe.rb +74 -0
- data/config/requirements.rb +15 -0
- data/example/get_followers.rb +32 -0
- data/example/get_following_all_words.rb +29 -0
- data/example/get_hot_keywords.rb +17 -0
- data/example/haiku_update.rb +21 -0
- data/lib/rhaiker.rb +767 -0
- data/lib/rhaiker/utils.rb +113 -0
- data/lib/rhaiker/version.rb +9 -0
- data/lib/rhaiker/xml_parser.rb +211 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +82 -0
- data/setup.rb +1585 -0
- data/spec/rhaiker_spec.rb +318 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +10 -0
- data/tasks/deployment.rake +34 -0
- data/tasks/environment.rake +7 -0
- data/tasks/rspec.rake +21 -0
- data/tasks/website.rake +17 -0
- data/website/index.html +71 -0
- data/website/index.txt +45 -0
- data/website/javascripts/rounded_corners_lite.inc.js +285 -0
- data/website/stylesheets/screen.css +138 -0
- data/website/template.html.erb +47 -0
- metadata +103 -0
@@ -0,0 +1,318 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
describe Rhaiker, ' when first created' do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@accessor = Rhaiker.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should be have a user_agent "rhaiker"' do
|
10
|
+
@accessor.user_agent.should be_eql("rhaiker")
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should be have a source "rhaiker"' do
|
14
|
+
@accessor.source.should be_eql("rhaiker")
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'shoud not have a user_id' do
|
18
|
+
@accessor.user_id.should be_nil
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should not have a api_key' do
|
22
|
+
@accessor.api_key.should be_nil
|
23
|
+
end
|
24
|
+
|
25
|
+
after do
|
26
|
+
@accessor = nil
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
describe Rhaiker::Utils, " when use" do
|
32
|
+
before do
|
33
|
+
@accessor = Rhaiker.new
|
34
|
+
@accessor.user_id = 'saronpasu'
|
35
|
+
@accessor.api_key = 'ar3hge2f'
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'create_uri should be URI instance' do
|
39
|
+
@accessor.create_uri(
|
40
|
+
Rhaiker::BaseAddress +
|
41
|
+
'statuses/public_timeline.xml'
|
42
|
+
).should be_a_kind_of(URI)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'create_request with type in :get should be Net::HTTP::Get instance' do
|
46
|
+
uri = mock(:uri)
|
47
|
+
uri.should_receive(:request_uri).and_return('text')
|
48
|
+
@accessor.create_request(:get, uri).should be_a_kind_of(Net::HTTP::Get)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'create_request with type in :post should be Net::HTTP::Post instance' do
|
52
|
+
uri = mock(:uri)
|
53
|
+
uri.should_receive(:request_uri).and_return('text')
|
54
|
+
@accessor.create_request(:post, uri).should be_a_kind_of(Net::HTTP::Post)
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'create_request instance should have basic_auth' do
|
58
|
+
uri = mock(:uri)
|
59
|
+
uri.should_receive(:request_uri).and_return('text')
|
60
|
+
@accessor.create_request(
|
61
|
+
:get, uri, true
|
62
|
+
)['Authorization'].should be_eql(
|
63
|
+
"Basic c2Fyb25wYXN1OmFyM2hnZTJm"
|
64
|
+
)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'http_access and return should be REXML::Document' do
|
68
|
+
uri = mock('uri')
|
69
|
+
request = mock('request')
|
70
|
+
@accessor.should_receive(:http_access).and_return(REXML::Document.new('<a/>'))
|
71
|
+
@accessor.http_access(uri, request).should be_a_kind_of(REXML::Document)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'parse_options and return parsed options' do
|
75
|
+
@accessor.parse_options({:status=>'hello',:page=>2}).should be_eql('?status=hello&page=2')
|
76
|
+
end
|
77
|
+
|
78
|
+
after do
|
79
|
+
@accessor = nil
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe Rhaiker::XML_Parser, 'when use' do
|
84
|
+
before do
|
85
|
+
@accessor = Rhaiker.new
|
86
|
+
@timeline = REXML::Document.new(
|
87
|
+
'<statuses>
|
88
|
+
<status>
|
89
|
+
<id>1234567890</id>
|
90
|
+
<created_at>2008-09-04T04:26:06Z</created_at>
|
91
|
+
<text>ほげ</text>
|
92
|
+
<keyword>ふが</keyword>
|
93
|
+
<in_reply_to_status_id>1234567890</in_reply_to_status_id>
|
94
|
+
<in_reply_to_user_id>saronpasu</in_reply_to_user_id>
|
95
|
+
<favorited>0</favorited>
|
96
|
+
<link>http://h.hatena.ne.jp/saronpasu/1234567890</link>
|
97
|
+
<source>web</source>
|
98
|
+
<replies>
|
99
|
+
<id>1234567890</id>
|
100
|
+
<created_at>2008-09-04T04:26:06Z</created_at>
|
101
|
+
<text>ほげ</text>
|
102
|
+
<keyword>ふが</keyword>
|
103
|
+
<favorited>0</favorited>
|
104
|
+
<link>http://h.hatena.ne.jp/saronpasu/1234567890</link>
|
105
|
+
<source>web</source>
|
106
|
+
<user>
|
107
|
+
<id>saronpasu</id>
|
108
|
+
<name>saronpasu</name>
|
109
|
+
<screen_name>saronpasu</screen_name>
|
110
|
+
<url>http://h.hatena.ne.jp/saronpasu/</url>
|
111
|
+
<profile_image_url>http://www.hatena.ne.jp/sa/saronpasu/profile.gif</profile_image_url>
|
112
|
+
<followers_count>0</followers_count>
|
113
|
+
</user>
|
114
|
+
</replies>
|
115
|
+
<user>
|
116
|
+
<id>saronpasu</id>
|
117
|
+
<name>saronpasu</name>
|
118
|
+
<screen_name>saronpasu</screen_name>
|
119
|
+
<url>http://h.hatena.ne.jp/saronpasu/</url>
|
120
|
+
<profile_image_url>http://www.hatena.ne.jp/sa/saronpasu/profile.gif</profile_image_url>
|
121
|
+
<followers_count>0</followers_count>
|
122
|
+
</user>
|
123
|
+
</status>
|
124
|
+
</statuses>'
|
125
|
+
)
|
126
|
+
@status = REXML::Document.new('
|
127
|
+
<status>
|
128
|
+
<id>1234567890</id>
|
129
|
+
<created_at>2008-09-04T04:26:06Z</created_at>
|
130
|
+
<text>ほげ</text>
|
131
|
+
<keyword>ふが</keyword>
|
132
|
+
<in_reply_to_status_id/>
|
133
|
+
<in_reply_to_user_id/>
|
134
|
+
<favorited>0</favorited>
|
135
|
+
<link>http://h.hatena.ne.jp/saronpasu/1234567890</link>
|
136
|
+
<source>web</source>
|
137
|
+
<user>
|
138
|
+
<id>saronpasu</id>
|
139
|
+
<name>saronpasu</name>
|
140
|
+
<screen_name>saronpasu</screen_name>
|
141
|
+
<url>http://h.hatena.ne.jp/saronpasu/</url>
|
142
|
+
<profile_image_url>http://www.hatena.ne.jp/sa/saronpasu/profile.gif</profile_image_url>
|
143
|
+
<followers_count>0</followers_count>
|
144
|
+
</user>
|
145
|
+
</status>'
|
146
|
+
).root
|
147
|
+
@users = REXML::Document.new(
|
148
|
+
'<users>
|
149
|
+
<user>
|
150
|
+
<id>saronpasu</id>
|
151
|
+
<name>saronpasu</name>
|
152
|
+
<screen_name>saronpasu</screen_name>
|
153
|
+
<url>http://h.hatena.ne.jp/saronpasu/</url>
|
154
|
+
<followers_count>0</followers_count>
|
155
|
+
<profile_image_url>http://www.hatena.ne.jp/sa/saronpasu/profile.gif</profile_image_url>
|
156
|
+
</user>
|
157
|
+
</users>'
|
158
|
+
)
|
159
|
+
@user = REXML::Document.new(
|
160
|
+
'<user>
|
161
|
+
<id>saronpasu</id>
|
162
|
+
<name>saronpasu</name>
|
163
|
+
<screen_name>saronpasu</screen_name>
|
164
|
+
<url>http://h.hatena.ne.jp/saronpasu/</url>
|
165
|
+
<followers_count>0</followers_count>
|
166
|
+
<profile_image_url>http://www.hatena.ne.jp/sa/saronpasu/profile.gif</profile_image_url>
|
167
|
+
</user>'
|
168
|
+
).root
|
169
|
+
@keywords = REXML::Document.new(
|
170
|
+
'<keywords>
|
171
|
+
<keyword>
|
172
|
+
<title>ほげほげ</title>
|
173
|
+
<link>http://h.hatena.ne.jp/keyword/hogehoge</link>
|
174
|
+
<entry_count>0</entry_count>
|
175
|
+
<followers_count>0</followers_count>
|
176
|
+
<related_words>ふがふが</related_words>
|
177
|
+
</keyword>
|
178
|
+
</keywords>'
|
179
|
+
)
|
180
|
+
@keyword = REXML::Document.new(
|
181
|
+
'<keyword>
|
182
|
+
<title>ほげほげ</title>
|
183
|
+
<link>http://h.hatena.ne.jp/keyword/hogehoge</link>
|
184
|
+
<entry_count>0</entry_count>
|
185
|
+
<followers_count>0</followers_count>
|
186
|
+
<related_words>ふがふが</related_words>
|
187
|
+
</keyword>'
|
188
|
+
).root
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'parse_timeline and return Hash in Array Data' do
|
192
|
+
@accessor.parse_timeline(@timeline).should be_a_kind_of(Array)
|
193
|
+
@accessor.parse_timeline(@timeline).first.should be_a_kind_of(Hash)
|
194
|
+
end
|
195
|
+
|
196
|
+
describe 'parse_timeline result' do
|
197
|
+
before do
|
198
|
+
@result = @accessor.parse_timeline(@timeline)
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'have status id' do
|
202
|
+
@result.first.should have_key(:id)
|
203
|
+
end
|
204
|
+
it 'have status text' do
|
205
|
+
@result.first.should have_key(:text)
|
206
|
+
end
|
207
|
+
it 'have status source' do
|
208
|
+
@result.first.should have_key(:source)
|
209
|
+
end
|
210
|
+
it 'have status favorited' do
|
211
|
+
@result.first.should have_key(:favorited)
|
212
|
+
end
|
213
|
+
it 'have status link' do
|
214
|
+
@result.first.should have_key(:link)
|
215
|
+
end
|
216
|
+
it 'have user' do
|
217
|
+
@result.first.should have_key(:user)
|
218
|
+
end
|
219
|
+
it 'have replies' do
|
220
|
+
@result.first.should have_key(:replies)
|
221
|
+
end
|
222
|
+
it 'have in_reply_to' do
|
223
|
+
@result.first.should have_key(:in_reply_to)
|
224
|
+
end
|
225
|
+
|
226
|
+
after do
|
227
|
+
@result = nil
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
it 'parse_status and return Hash Data' do
|
232
|
+
@accessor.parse_status(@status).should be_a_kind_of(Hash)
|
233
|
+
end
|
234
|
+
|
235
|
+
it 'parse_users and return Hash in Array Data' do
|
236
|
+
@accessor.parse_users(@users).should be_a_kind_of(Array)
|
237
|
+
@accessor.parse_users(@users).first.should be_a_kind_of(Hash)
|
238
|
+
end
|
239
|
+
|
240
|
+
describe 'parse_users result' do
|
241
|
+
before do
|
242
|
+
@result = @accessor.parse_users(@users)
|
243
|
+
end
|
244
|
+
|
245
|
+
it 'have user id' do
|
246
|
+
@result.first.should have_key(:id)
|
247
|
+
end
|
248
|
+
it 'have user name' do
|
249
|
+
@result.first.should have_key(:name)
|
250
|
+
end
|
251
|
+
it 'have user screen_name' do
|
252
|
+
@result.first.should have_key(:screen_name)
|
253
|
+
end
|
254
|
+
it 'have user url' do
|
255
|
+
@result.first.should have_key(:url)
|
256
|
+
end
|
257
|
+
it 'have user followers_count' do
|
258
|
+
@result.first.should have_key(:followers_count)
|
259
|
+
end
|
260
|
+
it 'have user profile_image_url' do
|
261
|
+
@result.first.should have_key(:profile_image_url)
|
262
|
+
end
|
263
|
+
|
264
|
+
after do
|
265
|
+
@result = nil
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
it 'parse_user and return Hash Data' do
|
270
|
+
@accessor.parse_user(@user).should be_a_kind_of(Hash)
|
271
|
+
end
|
272
|
+
|
273
|
+
it 'parse_keywords and return Hash in Array Data' do
|
274
|
+
@accessor.parse_keywords(@keywords).should be_a_kind_of(Array)
|
275
|
+
@accessor.parse_keywords(@keywords).first.should be_a_kind_of(Hash)
|
276
|
+
end
|
277
|
+
|
278
|
+
describe 'parse_keywords result' do
|
279
|
+
before do
|
280
|
+
@result = @accessor.parse_keywords(@keywords)
|
281
|
+
end
|
282
|
+
|
283
|
+
it 'have keyword title' do
|
284
|
+
@result.first.should have_key(:title)
|
285
|
+
end
|
286
|
+
it 'have keyword link' do
|
287
|
+
@result.first.should have_key(:link)
|
288
|
+
end
|
289
|
+
it 'have keyword entry_count' do
|
290
|
+
@result.first.should have_key(:entry_count)
|
291
|
+
end
|
292
|
+
it 'have keyword followers_count' do
|
293
|
+
@result.first.should have_key(:followers_count)
|
294
|
+
end
|
295
|
+
it 'have keyword related_keywords' do
|
296
|
+
@result.first.should have_key(:related_keywords)
|
297
|
+
end
|
298
|
+
|
299
|
+
after do
|
300
|
+
@result = nil
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
it 'parse_keyword and return Hash Data' do
|
305
|
+
@accessor.parse_keyword(@keyword).should be_a_kind_of(Hash)
|
306
|
+
end
|
307
|
+
|
308
|
+
after do
|
309
|
+
@accessor = nil
|
310
|
+
@timeline = nil
|
311
|
+
@status = nil
|
312
|
+
@users = nil
|
313
|
+
@user = nil
|
314
|
+
@keywords = nil
|
315
|
+
@keyword = nil
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
desc 'Release the website and new gem version'
|
2
|
+
task :deploy => [:check_version, :website, :release] do
|
3
|
+
puts "Remember to create SVN tag:"
|
4
|
+
puts "svn copy svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/trunk " +
|
5
|
+
"svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/tags/REL-#{VERS} "
|
6
|
+
puts "Suggested comment:"
|
7
|
+
puts "Tagging release #{CHANGES}"
|
8
|
+
end
|
9
|
+
|
10
|
+
desc 'Runs tasks website_generate and install_gem as a local deployment of the gem'
|
11
|
+
task :local_deploy => [:website_generate, :install_gem]
|
12
|
+
|
13
|
+
task :check_version do
|
14
|
+
unless ENV['VERSION']
|
15
|
+
puts 'Must pass a VERSION=x.y.z release version'
|
16
|
+
exit
|
17
|
+
end
|
18
|
+
unless ENV['VERSION'] == VERS
|
19
|
+
puts "Please update your version.rb to match the release version, currently #{VERS}"
|
20
|
+
exit
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
desc 'Install the package as a gem, without generating documentation(ri/rdoc)'
|
25
|
+
task :install_gem_no_doc => [:clean, :package] do
|
26
|
+
sh "#{'sudo ' unless Hoe::WINDOZE }gem install pkg/*.gem --no-rdoc --no-ri"
|
27
|
+
end
|
28
|
+
|
29
|
+
namespace :manifest do
|
30
|
+
desc 'Recreate Manifest.txt to include ALL files'
|
31
|
+
task :refresh do
|
32
|
+
`rake check_manifest | patch -p0 > Manifest.txt`
|
33
|
+
end
|
34
|
+
end
|
data/tasks/rspec.rake
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
begin
|
2
|
+
require 'spec'
|
3
|
+
rescue LoadError
|
4
|
+
require 'rubygems'
|
5
|
+
require 'spec'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'spec/rake/spectask'
|
9
|
+
rescue LoadError
|
10
|
+
puts <<-EOS
|
11
|
+
To use rspec for testing you must install rspec gem:
|
12
|
+
gem install rspec
|
13
|
+
EOS
|
14
|
+
exit(0)
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "Run the specs under spec/models"
|
18
|
+
Spec::Rake::SpecTask.new do |t|
|
19
|
+
t.spec_opts = ['--options', "spec/spec.opts"]
|
20
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
21
|
+
end
|
data/tasks/website.rake
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
desc 'Generate website files'
|
2
|
+
task :website_generate => :ruby_env do
|
3
|
+
(Dir['website/**/*.txt'] - Dir['website/version*.txt']).each do |txt|
|
4
|
+
sh %{ #{RUBY_APP} script/txt2html #{txt} > #{txt.gsub(/txt$/,'html')} }
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
desc 'Upload website files to rubyforge'
|
9
|
+
task :website_upload do
|
10
|
+
host = "#{rubyforge_username}@rubyforge.org"
|
11
|
+
remote_dir = "/var/www/gforge-projects/#{PATH}/"
|
12
|
+
local_dir = 'website'
|
13
|
+
sh %{rsync -aCv #{local_dir}/ #{host}:#{remote_dir}}
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'Generate and upload website files'
|
17
|
+
task :website => [:website_generate, :website_upload, :publish_docs]
|
data/website/index.html
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
4
|
+
<head>
|
5
|
+
<link rel="stylesheet" href="stylesheets/screen.css" type="text/css" media="screen" />
|
6
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
7
|
+
<title>
|
8
|
+
rhaiker
|
9
|
+
</title>
|
10
|
+
<script src="javascripts/rounded_corners_lite.inc.js" type="text/javascript"></script>
|
11
|
+
<style>
|
12
|
+
|
13
|
+
</style>
|
14
|
+
<script type="text/javascript">
|
15
|
+
window.onload = function() {
|
16
|
+
settings = {
|
17
|
+
tl: { radius: 10 },
|
18
|
+
tr: { radius: 10 },
|
19
|
+
bl: { radius: 10 },
|
20
|
+
br: { radius: 10 },
|
21
|
+
antiAlias: true,
|
22
|
+
autoPad: true,
|
23
|
+
validTags: ["div"]
|
24
|
+
}
|
25
|
+
var versionBox = new curvyCorners(settings, document.getElementById("version"));
|
26
|
+
versionBox.applyCornersToAll();
|
27
|
+
}
|
28
|
+
</script>
|
29
|
+
</head>
|
30
|
+
<body>
|
31
|
+
<div id="main">
|
32
|
+
|
33
|
+
<h1>rhaiker</h1>
|
34
|
+
<div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/rhaiker"; return false'>
|
35
|
+
<p>Get Version</p>
|
36
|
+
<a href="http://rubyforge.org/projects/rhaiker" class="numbers">0.0.1</a>
|
37
|
+
</div>
|
38
|
+
<h2>What</h2>
|
39
|
+
<p>Rhaiker is Hatena::Haiku::<span class="caps">API</span> ruby binding.<br />
|
40
|
+
Hatena::Haiku is Japanese micro-blog service.</p>
|
41
|
+
<p>Hatena::Haiku<br />
|
42
|
+
http://h.hatena.ne.jp/</p>
|
43
|
+
<p>Hatena::Haiku::<span class="caps">API</span><br />
|
44
|
+
http://h.hatena.ne.jp/api</p>
|
45
|
+
<h2>Installing</h2>
|
46
|
+
<p><pre class='syntax'><span class="ident">sudo</span> <span class="ident">gem</span> <span class="ident">install</span> <span class="ident">rhaiker</span></pre></p>
|
47
|
+
<h2>The basics</h2>
|
48
|
+
<h2>Demonstration of usage</h2>
|
49
|
+
<p>require ‘rhaiker’</p>
|
50
|
+
<p>rhaiker = Rhaiker.new<br />
|
51
|
+
rhaiker.user_id = ‘your_user_id’<br />
|
52
|
+
rhaiker.api_key = ‘your_api_key’<br />
|
53
|
+
rhaiker.status_update({:status => ’HogeHoge’}</p>
|
54
|
+
<h3>Build and test instructions</h3>
|
55
|
+
<pre>cd rhaiker
|
56
|
+
rake spec
|
57
|
+
rake install_gem</pre>
|
58
|
+
<h2>License</h2>
|
59
|
+
<p>This code is free to use under the terms of the <span class="caps">MIT</span> license.</p>
|
60
|
+
<h2>Contact</h2>
|
61
|
+
<p>Comments are welcome.<br />
|
62
|
+
Send an email to jamneco at gmail dot com.</p>
|
63
|
+
<p class="coda">
|
64
|
+
Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
|
65
|
+
</p>
|
66
|
+
</div>
|
67
|
+
|
68
|
+
<!-- insert site tracking codes here, like Google Urchin -->
|
69
|
+
|
70
|
+
</body>
|
71
|
+
</html>
|