tinatra 0.1.0
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/README.mkd +80 -0
- data/Rakefile +13 -0
- data/VERSION +1 -0
- data/examples/simple.rb +18 -0
- data/lib/tinatra.rb +269 -0
- data/spec/helper_dummytter.rb +101 -0
- data/spec/spec_tinatra.rb +131 -0
- data/tinatra.gemspec +58 -0
- metadata +111 -0
data/README.mkd
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
# Tinatra - Ruby powered DSL, which a designed for making twitter bots.
|
2
|
+
|
3
|
+
Tinatra is a DSL for making twitter bots. It's like Sinatra. トゥィナトラ.
|
4
|
+
|
5
|
+
## Feature
|
6
|
+
|
7
|
+
* Easy to make twitter bot
|
8
|
+
* Run in cron
|
9
|
+
* Many actions (always,mention,direct\_message,followed,timeline,...)
|
10
|
+
* Automatic follow return/remove return
|
11
|
+
|
12
|
+
## Install
|
13
|
+
|
14
|
+
gem install tinatra
|
15
|
+
|
16
|
+
## Usage
|
17
|
+
|
18
|
+
require 'tinatra'
|
19
|
+
|
20
|
+
timeline do |tweet|
|
21
|
+
p tweet #=> New tweet in timeline
|
22
|
+
end
|
23
|
+
|
24
|
+
mention do |m|
|
25
|
+
p m #=> New tweet in mention
|
26
|
+
end
|
27
|
+
|
28
|
+
direct_message do |dm|
|
29
|
+
p dm #=> New Direct message
|
30
|
+
end
|
31
|
+
|
32
|
+
followed do |user|
|
33
|
+
p user #=> New user who is followed
|
34
|
+
end
|
35
|
+
|
36
|
+
removed do |user|
|
37
|
+
p user #=> User removed
|
38
|
+
end
|
39
|
+
|
40
|
+
always do
|
41
|
+
# Always run
|
42
|
+
end
|
43
|
+
|
44
|
+
### Setup
|
45
|
+
|
46
|
+
$ ruby a.rb --db=/path/to/db --init
|
47
|
+
------------ AUTHORIZING ------------
|
48
|
+
Input your consumer key: CONSUMERKEY
|
49
|
+
Input your consumer secret: PSSSSST
|
50
|
+
|
51
|
+
Access This URL and press 'Allow' in account for tinatra => http://...
|
52
|
+
Input key shown by twitter: 0000000
|
53
|
+
|
54
|
+
Authorizing is done.
|
55
|
+
$ ruby a.rb --db=/path/to/db
|
56
|
+
|
57
|
+
## License
|
58
|
+
|
59
|
+
The MIT Licence
|
60
|
+
|
61
|
+
(c) Shota Fukumori (sora\_h) 2010-
|
62
|
+
|
63
|
+
>Permission is hereby granted, free of charge, to any person obtaining a copy
|
64
|
+
>of this software and associated documentation files (the "Software"), to deal
|
65
|
+
>in the Software without restriction, including without limitation the rights
|
66
|
+
>to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
67
|
+
>copies of the Software, and to permit persons to whom the Software is
|
68
|
+
>furnished to do so, subject to the following conditions:
|
69
|
+
>
|
70
|
+
>The above copyright notice and this permission notice shall be included in
|
71
|
+
>all copies or substantial portions of the Software.
|
72
|
+
>
|
73
|
+
>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
74
|
+
>IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
75
|
+
>FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
76
|
+
>AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
77
|
+
>LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
78
|
+
>OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
79
|
+
>THE SOFTWARE.
|
80
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'jeweler'
|
2
|
+
Jeweler::Tasks.new do |gemspec|
|
3
|
+
gemspec.name = "tinatra"
|
4
|
+
gemspec.summary = "DSL for twitter bot!"
|
5
|
+
gemspec.email = "sora134@gmail.com"
|
6
|
+
gemspec.homepage = "http://github.com/sorah/tinatra"
|
7
|
+
gemspec.description = "Ruby implemented DSL, designed for twitter bot."
|
8
|
+
gemspec.authors = ["Shota Fukumori (sora_h)"]
|
9
|
+
|
10
|
+
gemspec.add_dependency 'rubytter'
|
11
|
+
gemspec.add_dependency 'highline'
|
12
|
+
gemspec.add_dependency 'oauth'
|
13
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/examples/simple.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
$:.unshift "#{File.dirname(__FILE__)}/../lib"
|
2
|
+
require "tinatra"
|
3
|
+
|
4
|
+
mention do |m|
|
5
|
+
puts "mention #{m[:user][:screen_name]}: #{m[:text]}"
|
6
|
+
end
|
7
|
+
|
8
|
+
timeline do |m|
|
9
|
+
puts "timeline #{m[:user][:screen_name]}: #{m[:text]}"
|
10
|
+
end
|
11
|
+
|
12
|
+
direct_message do |m|
|
13
|
+
puts "dm #{m[:user][:screen_name]}: #{m[:text]}"
|
14
|
+
end
|
15
|
+
|
16
|
+
always do
|
17
|
+
puts "always"
|
18
|
+
end
|
data/lib/tinatra.rb
ADDED
@@ -0,0 +1,269 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'oauth'
|
3
|
+
require 'rubytter'
|
4
|
+
require 'pstore'
|
5
|
+
require 'singleton'
|
6
|
+
require 'highline'
|
7
|
+
|
8
|
+
class Hash
|
9
|
+
def transaction
|
10
|
+
yield self
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
#oauth-patch.rb http://d.hatena.ne.jp/shibason/20090802/1249204953
|
15
|
+
if RUBY_VERSION >= '1.9.0'
|
16
|
+
module OAuth
|
17
|
+
module Helper
|
18
|
+
def escape(value)
|
19
|
+
begin
|
20
|
+
URI::escape(value.to_s, OAuth::RESERVED_CHARACTERS)
|
21
|
+
rescue ArgumentError
|
22
|
+
URI::escape(
|
23
|
+
value.to_s.force_encoding(Encoding::UTF_8),
|
24
|
+
OAuth::RESERVED_CHARACTERS
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
module HMAC
|
32
|
+
class Base
|
33
|
+
def set_key(key)
|
34
|
+
key = @algorithm.digest(key) if key.size > @block_size
|
35
|
+
key_xor_ipad = Array.new(@block_size, 0x36)
|
36
|
+
key_xor_opad = Array.new(@block_size, 0x5c)
|
37
|
+
key.bytes.each_with_index do |value, index|
|
38
|
+
key_xor_ipad[index] ^= value
|
39
|
+
key_xor_opad[index] ^= value
|
40
|
+
end
|
41
|
+
@key_xor_ipad = key_xor_ipad.pack('c*')
|
42
|
+
@key_xor_opad = key_xor_opad.pack('c*')
|
43
|
+
@md = @algorithm.new
|
44
|
+
@initialized = true
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
class Tinatra
|
53
|
+
API_BASE = 'http://api.twitter.com/'
|
54
|
+
include Singleton
|
55
|
+
|
56
|
+
def initialize
|
57
|
+
@config = {:rubytter => OAuthRubytter}
|
58
|
+
@actions = {}
|
59
|
+
@db = nil
|
60
|
+
@t = nil
|
61
|
+
end
|
62
|
+
|
63
|
+
def parse_option
|
64
|
+
init = false
|
65
|
+
help = false
|
66
|
+
ARGV.each do |a|
|
67
|
+
case a
|
68
|
+
when "--init"
|
69
|
+
init = true
|
70
|
+
help = false
|
71
|
+
when /--db=(.+)/
|
72
|
+
set :db, $1
|
73
|
+
when "--help"
|
74
|
+
help = true
|
75
|
+
init = false
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
if init
|
80
|
+
authorize
|
81
|
+
exit
|
82
|
+
end
|
83
|
+
if help
|
84
|
+
puts <<-EOH
|
85
|
+
Usage: #{File.basename($0)} [--db=DATABASE] [--init|--help]
|
86
|
+
|
87
|
+
--db -- set a path to database file.
|
88
|
+
--init -- authorize an account
|
89
|
+
--help -- show this message
|
90
|
+
EOH
|
91
|
+
exit
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def authorize
|
96
|
+
puts "------------ AUTHORIZING ------------"
|
97
|
+
init_db
|
98
|
+
@db.transaction do |d|
|
99
|
+
if d[:consumer]
|
100
|
+
puts "You're already setted consumer key/secret."
|
101
|
+
cons_again = HighLine.new.agree("Input consumer key/secret again? ")
|
102
|
+
else
|
103
|
+
cons_again = true
|
104
|
+
end
|
105
|
+
|
106
|
+
if cons_again
|
107
|
+
cons = []
|
108
|
+
cons << HighLine.new.ask("Input your consumer key: ")
|
109
|
+
cons << HighLine.new.ask("Input your consumer secret: ")
|
110
|
+
d[:consumer] = OAuth::Consumer.new(cons[0],cons[1], :site => API_BASE)
|
111
|
+
end
|
112
|
+
|
113
|
+
puts
|
114
|
+
|
115
|
+
request_token = d[:consumer].get_request_token
|
116
|
+
puts "Access This URL and press 'Allow' in account for tinatra => #{request_token.authorize_url}"
|
117
|
+
pin = HighLine.new.ask('Input key shown by twitter: ')
|
118
|
+
access_token = request_token.get_access_token(
|
119
|
+
:oauth_verifier => pin
|
120
|
+
)
|
121
|
+
d[:token] = access_token#[access_token.token.dup,access_token.secret.dup]
|
122
|
+
|
123
|
+
@t = @config[:rubytter].new(access_token)
|
124
|
+
d[:self] = eval(@t.verify_credentials.inspect)
|
125
|
+
|
126
|
+
puts
|
127
|
+
puts "Authorizing is done."
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def reset
|
132
|
+
initialize
|
133
|
+
end
|
134
|
+
|
135
|
+
def set(a,b)
|
136
|
+
@config[a]=b
|
137
|
+
end
|
138
|
+
|
139
|
+
def add_action(event, block)
|
140
|
+
@actions[event] ||= []
|
141
|
+
@actions[event] << block
|
142
|
+
end
|
143
|
+
|
144
|
+
def call_action(event, *args)
|
145
|
+
@actions[event] ||= []
|
146
|
+
@actions[event].each do |a|
|
147
|
+
a.yield(*args)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def run
|
152
|
+
init_db
|
153
|
+
init_twit
|
154
|
+
|
155
|
+
call_action(:always)
|
156
|
+
|
157
|
+
[[:mention, :replies], [:timeline, :home_timeline],
|
158
|
+
[:direct_message, :direct_messages]].each do |act|
|
159
|
+
if @actions[act[0]]
|
160
|
+
r = @t.__send__(act[1])
|
161
|
+
@db.transaction do |d|
|
162
|
+
(r - d[act[0]]).each do |new|
|
163
|
+
call_action(act[0],new)
|
164
|
+
end
|
165
|
+
d[act[0]] = eval(r.inspect)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
@db.transaction do |d|
|
171
|
+
if @actions[:followed]||@actions[:removed]
|
172
|
+
f = @t.followers_ids(d[:self][:id])
|
173
|
+
[[:followed,(f-d[:follower])],
|
174
|
+
[:removed,(d[:follower]-f)]].each do |x|
|
175
|
+
if @actions[x[0]]
|
176
|
+
x[1].each do |n|
|
177
|
+
call_action(x[0],@t.user(n))
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
d[:follower] = eval(f.inspect)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def api
|
187
|
+
init_twit unless @t
|
188
|
+
@t
|
189
|
+
end
|
190
|
+
|
191
|
+
[:mention,:timeline,:direct_message,:always,:followed,:removed].each do |act|
|
192
|
+
eval "def #{act}(&block); add_action(:#{act},block); end"
|
193
|
+
end
|
194
|
+
|
195
|
+
def self.method_missing(name, *args)
|
196
|
+
Tinatra.instance.__send__(name, *args)
|
197
|
+
end
|
198
|
+
|
199
|
+
attr_reader :config
|
200
|
+
|
201
|
+
module Helpers
|
202
|
+
end
|
203
|
+
include Helpers
|
204
|
+
|
205
|
+
private
|
206
|
+
|
207
|
+
def init_twit
|
208
|
+
return @t if @t
|
209
|
+
init_db
|
210
|
+
@db.transaction do |d|
|
211
|
+
if d[:consumer].nil? || d[:token].nil?
|
212
|
+
abort "Run #{File.basename($0)} --init first." unless @config[:spec]
|
213
|
+
end
|
214
|
+
access_token = nil
|
215
|
+
if @config[:spec]
|
216
|
+
d[:self] = @config[:rubytter].new.verify_credentials
|
217
|
+
end
|
218
|
+
@t = @config[:rubytter].new(d[:token])
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def init_db
|
223
|
+
return @db if @db
|
224
|
+
if @config[:db] == :memory
|
225
|
+
@db = {}
|
226
|
+
else
|
227
|
+
unless @config[:db]
|
228
|
+
abort "You must set a path to db file using --db= or db method."
|
229
|
+
end
|
230
|
+
@db = PStore.new(@config[:db])
|
231
|
+
end
|
232
|
+
make_db
|
233
|
+
end
|
234
|
+
|
235
|
+
def make_db
|
236
|
+
@db.transaction do |d|
|
237
|
+
unless d[:initialized]
|
238
|
+
d[:initialized] = true
|
239
|
+
[:mention,:direct_message,
|
240
|
+
:timeline,:follower,:following].each{|k|d[k]=[]}
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
|
246
|
+
end
|
247
|
+
|
248
|
+
module Kernel
|
249
|
+
def set(*args)
|
250
|
+
Tinatra.instance.set(*args)
|
251
|
+
end
|
252
|
+
def db(path)
|
253
|
+
Tinatra.instance.set(:db,path)
|
254
|
+
end
|
255
|
+
[:mention,:timeline,:direct_message,:always,:followed,:removed].each do |act|
|
256
|
+
eval "def #{act}(&block); Tinatra.instance.#{act}(&block); end"
|
257
|
+
end
|
258
|
+
|
259
|
+
def api
|
260
|
+
Tinatra.instance.api
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
at_exit do
|
265
|
+
if $!.nil? && !Tinatra.config[:spec]
|
266
|
+
Tinatra.parse_option
|
267
|
+
Tinatra.run
|
268
|
+
end
|
269
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
class Dummytter
|
2
|
+
@@dummy = {:replies => [], :home_timeline => [], :direct_messages => [],
|
3
|
+
:followers_ids => [], :friends_ids => []}
|
4
|
+
def method_missing(name,*args)
|
5
|
+
@@dummy[name] ||= []
|
6
|
+
@@dummy[name].dup
|
7
|
+
end
|
8
|
+
|
9
|
+
def user(id)
|
10
|
+
{:id=>id}
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.dummy
|
14
|
+
@@dummy
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
$tinatra_spec_tweet_id = 0
|
19
|
+
|
20
|
+
def dummy_user(name)
|
21
|
+
$tinatra_spec_tweet_id += 1
|
22
|
+
{:profile_background_tile=>true,
|
23
|
+
:favourites_count=>0, :description=>"hi",
|
24
|
+
:profile_text_color=>"FFFFFF", :url=>"http://example.com/sorah",
|
25
|
+
:geo_enabled=>false, :follow_request_sent=>false, :lang=>"ja",
|
26
|
+
:created_at=>"Sat Sep 01 15:00:00 +0000 2009", :profile_link_color=>"FFFFFF",
|
27
|
+
:location=>"Tochigi", :verified=>false, :time_zone=>"Tokyo",
|
28
|
+
:profile_sidebar_fill_color=>"FFFFFF",
|
29
|
+
:profile_image_url=>"http://example.com/a.png",
|
30
|
+
:following=>true, :listed_count=>0, :profile_use_background_image=>true,
|
31
|
+
:profile_sidebar_border_color=>"FFFFFF",
|
32
|
+
:followers_count=>1, :protected=>false,
|
33
|
+
:screen_name=>name, :statuses_count=>1, :name=>name,
|
34
|
+
:show_all_inline_media=>false,
|
35
|
+
:profile_background_image_url=>"http://example.com/b.jpg",
|
36
|
+
:friends_count=>1, :id=>$tinatra_spec_tweet_id, :contributors_enabled=>false, :notifications=>false,
|
37
|
+
:utc_offset=>32400, :profile_background_color=>"FFFFFF"}
|
38
|
+
end
|
39
|
+
|
40
|
+
def dummy_tweet(t)
|
41
|
+
$tinatra_spec_tweet_id += 1
|
42
|
+
{:contributors=>nil, :in_reply_to_screen_name=>nil, :retweeted=>false,
|
43
|
+
:truncated=>false, :created_at=>"Mon Sep 13 12:00:00 +0000 2010",
|
44
|
+
:source=>"web",
|
45
|
+
:retweet_count=>nil,:in_reply_to_user_id=>nil, :favorited=>false,
|
46
|
+
:in_reply_to_status_id=>nil,
|
47
|
+
:place=>nil, :coordinates=>nil,
|
48
|
+
:user=>{:profile_background_tile=>true,
|
49
|
+
:favourites_count=>0, :description=>"hi",
|
50
|
+
:profile_text_color=>"FFFFFF", :url=>"http://example.com/sorah",
|
51
|
+
:geo_enabled=>false, :follow_request_sent=>false, :lang=>"ja",
|
52
|
+
:created_at=>"Sat Sep 01 15:00:00 +0000 2009", :profile_link_color=>"FFFFFF",
|
53
|
+
:location=>"Tochigi", :verified=>false, :time_zone=>"Tokyo",
|
54
|
+
:profile_sidebar_fill_color=>"FFFFFF",
|
55
|
+
:profile_image_url=>"http://example.com/a.png",
|
56
|
+
:following=>true, :listed_count=>0, :profile_use_background_image=>true,
|
57
|
+
:profile_sidebar_border_color=>"FFFFFF",
|
58
|
+
:followers_count=>1, :protected=>false,
|
59
|
+
:screen_name=>"foo", :statuses_count=>1, :name=>"foobar",
|
60
|
+
:show_all_inline_media=>false,
|
61
|
+
:profile_background_image_url=>"http://example.com/b.jpg",
|
62
|
+
:friends_count=>1, :id=>1, :contributors_enabled=>false, :notifications=>false,
|
63
|
+
:utc_offset=>32400, :profile_background_color=>"FFFFFF"},
|
64
|
+
:geo=>nil, :id=>$tinatra_spec_tweet_id, :text=>t}
|
65
|
+
end
|
66
|
+
|
67
|
+
def dummy_reply(i,t)
|
68
|
+
$tinatra_spec_tweet_id += 1
|
69
|
+
{:contributors=>nil, :in_reply_to_screen_name=>"tinatra", :retweeted=>false,
|
70
|
+
:truncated=>false, :created_at=>"Mon Sep 13 12:00:00 +0000 2010",
|
71
|
+
:source=>"web",
|
72
|
+
:retweet_count=>nil,:in_reply_to_user_id=>2, :favorited=>false,
|
73
|
+
:in_reply_to_status_id=>i,
|
74
|
+
:place=>nil, :coordinates=>nil,
|
75
|
+
:user=>{:profile_background_tile=>true,
|
76
|
+
:favourites_count=>0, :description=>"hi",
|
77
|
+
:profile_text_color=>"FFFFFF", :url=>"http://example.com/sorah",
|
78
|
+
:geo_enabled=>false, :follow_request_sent=>false, :lang=>"ja",
|
79
|
+
:created_at=>"Sat Sep 01 15:00:00 +0000 2009", :profile_link_color=>"FFFFFF",
|
80
|
+
:location=>"Tochigi", :verified=>false, :time_zone=>"Tokyo",
|
81
|
+
:profile_sidebar_fill_color=>"FFFFFF",
|
82
|
+
:profile_image_url=>"http://example.com/a.png",
|
83
|
+
:following=>true, :listed_count=>0, :profile_use_background_image=>true,
|
84
|
+
:profile_sidebar_border_color=>"FFFFFF",
|
85
|
+
:followers_count=>1, :protected=>false,
|
86
|
+
:screen_name=>"foo", :statuses_count=>1, :name=>"foobar",
|
87
|
+
:show_all_inline_media=>false,
|
88
|
+
:profile_background_image_url=>"http://example.com/b.jpg",
|
89
|
+
:friends_count=>1, :id=>1, :contributors_enabled=>false, :notifications=>false,
|
90
|
+
:utc_offset=>32400, :profile_background_color=>"FFFFFF"},
|
91
|
+
:geo=>nil, :id=>$tinatra_spec_tweet_id, :text=>t}
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
def dummy_direct(text)
|
96
|
+
{:recipient_screen_name=>"tinatra", :recipient=>{},
|
97
|
+
:created_at=>"Mon Sep 13 07:11:39 +0000 2010", :recipient_id=>2, :sender=>{},
|
98
|
+
:sender_id=>1, :id=>$tinatra_spec_tweet_id, :sender_screen_name=>"foo", :text=>text}
|
99
|
+
end
|
100
|
+
|
101
|
+
|
@@ -0,0 +1,131 @@
|
|
1
|
+
$:.unshift "#{File.dirname(__FILE__)}/../lib"
|
2
|
+
$:.unshift "#{File.dirname(__FILE__)}"
|
3
|
+
require "tinatra"
|
4
|
+
require "helper_dummytter"
|
5
|
+
|
6
|
+
#Dummytter.dummy[:followers_ids] = 100.times.map{|i|i}
|
7
|
+
|
8
|
+
describe "Tinatra" do
|
9
|
+
before do
|
10
|
+
Dummytter.dummy[:verify_credentials] = {:user => {:id => 2, :screen_name => "tinatra"}}
|
11
|
+
Tinatra.set :spec, true
|
12
|
+
Tinatra.set :db, :memory
|
13
|
+
Tinatra.set :rubytter, Dummytter
|
14
|
+
end
|
15
|
+
it "sets config by Kernel#set" do
|
16
|
+
Kernel.set :foo, :bar
|
17
|
+
Tinatra.config[:foo].should == :bar
|
18
|
+
end
|
19
|
+
|
20
|
+
it "adds and calls an action" do
|
21
|
+
Tinatra.reset
|
22
|
+
a = nil
|
23
|
+
l = lambda{ a = :twitra}
|
24
|
+
Tinatra.add_action(:foo, l)
|
25
|
+
Tinatra.call_action(:foo)
|
26
|
+
a.should == :twitra
|
27
|
+
end
|
28
|
+
|
29
|
+
it "adds and calls an action with args" do
|
30
|
+
Tinatra.reset
|
31
|
+
a = nil
|
32
|
+
l = lambda{|*x| a = x}
|
33
|
+
Tinatra.add_action(:foo, l)
|
34
|
+
Tinatra.call_action(:foo, :bar)
|
35
|
+
a.should == [:bar]
|
36
|
+
Tinatra.call_action(:foo, :bar, :hoge)
|
37
|
+
a.should == [:bar, :hoge]
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "action" do
|
41
|
+
it "timeline calls when detect new tweet in timeline" do
|
42
|
+
r = nil
|
43
|
+
tweet = dummy_tweet("hi")
|
44
|
+
a = lambda{|t|r = t[:id]}
|
45
|
+
Tinatra.add_action(:timeline, a)
|
46
|
+
Tinatra.run
|
47
|
+
Dummytter.dummy[:home_timeline] << tweet
|
48
|
+
Tinatra.run
|
49
|
+
r.should == tweet[:id]
|
50
|
+
end
|
51
|
+
|
52
|
+
it "mention calls when detect new tweet in mention" do
|
53
|
+
r = nil
|
54
|
+
target = dummy_tweet("hi")
|
55
|
+
mention = dummy_reply(target[:id],"hi!!")
|
56
|
+
Dummytter.dummy[:home_timeline] << target
|
57
|
+
a = lambda{|t|r=t[:id]}
|
58
|
+
Tinatra.add_action(:mention, a)
|
59
|
+
Tinatra.run
|
60
|
+
Dummytter.dummy[:replies] << mention
|
61
|
+
Tinatra.run
|
62
|
+
r.should == mention[:id]
|
63
|
+
end
|
64
|
+
|
65
|
+
it "direct_message calls when received new direct message" do
|
66
|
+
dm = dummy_direct("hello")
|
67
|
+
r = nil
|
68
|
+
a = lambda{|d|r = d[:id]}
|
69
|
+
Tinatra.add_action(:direct_message, a)
|
70
|
+
Tinatra.run
|
71
|
+
Dummytter.dummy[:direct_messages] << dm
|
72
|
+
Tinatra.run
|
73
|
+
r.should == dm[:id]
|
74
|
+
end
|
75
|
+
|
76
|
+
it "always calls always" do
|
77
|
+
r = false
|
78
|
+
a = lambda{r = true}
|
79
|
+
Tinatra.add_action(:always, a)
|
80
|
+
Tinatra.run
|
81
|
+
r.should be_true
|
82
|
+
end
|
83
|
+
|
84
|
+
it "followed calls when followed by user" do
|
85
|
+
r = nil
|
86
|
+
a = lambda{|u|r = u[:id]}
|
87
|
+
Tinatra.run
|
88
|
+
Tinatra.add_action(:followed,a)
|
89
|
+
Dummytter.dummy[:followers_ids] << 10000
|
90
|
+
Tinatra.run
|
91
|
+
r.should == 10000
|
92
|
+
end
|
93
|
+
|
94
|
+
it "removed calls when removed by user" do
|
95
|
+
r = nil
|
96
|
+
a = lambda{|u|r = u[:id]}
|
97
|
+
Tinatra.run
|
98
|
+
Tinatra.add_action(:removed,a)
|
99
|
+
Dummytter.dummy[:followers_ids].delete 10000
|
100
|
+
Tinatra.run
|
101
|
+
r.should == 10000
|
102
|
+
end
|
103
|
+
|
104
|
+
it "looks rubytter by api method" do
|
105
|
+
r = nil
|
106
|
+
a = lambda{r = api.class}
|
107
|
+
Tinatra.add_action(:always, a)
|
108
|
+
Tinatra.run
|
109
|
+
r.should == Dummytter
|
110
|
+
end
|
111
|
+
|
112
|
+
it "add by method" do
|
113
|
+
r = false
|
114
|
+
always do
|
115
|
+
r = true
|
116
|
+
end
|
117
|
+
Tinatra.run
|
118
|
+
r.should be_true
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe "config" do
|
123
|
+
it "autofollow returns follow automatically" do
|
124
|
+
pending
|
125
|
+
end
|
126
|
+
|
127
|
+
it "autoremove returns follow automatically" do
|
128
|
+
pending
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
data/tinatra.gemspec
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{tinatra}
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Shota Fukumori (sora_h)"]
|
12
|
+
s.date = %q{2010-09-14}
|
13
|
+
s.description = %q{Ruby implemented DSL, designed for twitter bot.}
|
14
|
+
s.email = %q{sora134@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.mkd"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
"README.mkd",
|
20
|
+
"Rakefile",
|
21
|
+
"VERSION",
|
22
|
+
"examples/simple.rb",
|
23
|
+
"lib/tinatra.rb",
|
24
|
+
"spec/helper_dummytter.rb",
|
25
|
+
"spec/spec_tinatra.rb",
|
26
|
+
"tinatra.gemspec"
|
27
|
+
]
|
28
|
+
s.homepage = %q{http://github.com/sorah/tinatra}
|
29
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
30
|
+
s.require_paths = ["lib"]
|
31
|
+
s.rubygems_version = %q{1.3.7}
|
32
|
+
s.summary = %q{DSL for twitter bot!}
|
33
|
+
s.test_files = [
|
34
|
+
"spec/helper_dummytter.rb",
|
35
|
+
"spec/spec_tinatra.rb",
|
36
|
+
"examples/simple.rb"
|
37
|
+
]
|
38
|
+
|
39
|
+
if s.respond_to? :specification_version then
|
40
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
41
|
+
s.specification_version = 3
|
42
|
+
|
43
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
44
|
+
s.add_runtime_dependency(%q<rubytter>, [">= 0"])
|
45
|
+
s.add_runtime_dependency(%q<highline>, [">= 0"])
|
46
|
+
s.add_runtime_dependency(%q<oauth>, [">= 0"])
|
47
|
+
else
|
48
|
+
s.add_dependency(%q<rubytter>, [">= 0"])
|
49
|
+
s.add_dependency(%q<highline>, [">= 0"])
|
50
|
+
s.add_dependency(%q<oauth>, [">= 0"])
|
51
|
+
end
|
52
|
+
else
|
53
|
+
s.add_dependency(%q<rubytter>, [">= 0"])
|
54
|
+
s.add_dependency(%q<highline>, [">= 0"])
|
55
|
+
s.add_dependency(%q<oauth>, [">= 0"])
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
metadata
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tinatra
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Shota Fukumori (sora_h)
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-09-14 00:00:00 +09:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rubytter
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
version: "0"
|
31
|
+
type: :runtime
|
32
|
+
version_requirements: *id001
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: highline
|
35
|
+
prerelease: false
|
36
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
37
|
+
none: false
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
version: "0"
|
44
|
+
type: :runtime
|
45
|
+
version_requirements: *id002
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: oauth
|
48
|
+
prerelease: false
|
49
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
segments:
|
55
|
+
- 0
|
56
|
+
version: "0"
|
57
|
+
type: :runtime
|
58
|
+
version_requirements: *id003
|
59
|
+
description: Ruby implemented DSL, designed for twitter bot.
|
60
|
+
email: sora134@gmail.com
|
61
|
+
executables: []
|
62
|
+
|
63
|
+
extensions: []
|
64
|
+
|
65
|
+
extra_rdoc_files:
|
66
|
+
- README.mkd
|
67
|
+
files:
|
68
|
+
- README.mkd
|
69
|
+
- Rakefile
|
70
|
+
- VERSION
|
71
|
+
- examples/simple.rb
|
72
|
+
- lib/tinatra.rb
|
73
|
+
- spec/helper_dummytter.rb
|
74
|
+
- spec/spec_tinatra.rb
|
75
|
+
- tinatra.gemspec
|
76
|
+
has_rdoc: true
|
77
|
+
homepage: http://github.com/sorah/tinatra
|
78
|
+
licenses: []
|
79
|
+
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options:
|
82
|
+
- --charset=UTF-8
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
segments:
|
91
|
+
- 0
|
92
|
+
version: "0"
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
segments:
|
99
|
+
- 0
|
100
|
+
version: "0"
|
101
|
+
requirements: []
|
102
|
+
|
103
|
+
rubyforge_project:
|
104
|
+
rubygems_version: 1.3.7
|
105
|
+
signing_key:
|
106
|
+
specification_version: 3
|
107
|
+
summary: DSL for twitter bot!
|
108
|
+
test_files:
|
109
|
+
- spec/helper_dummytter.rb
|
110
|
+
- spec/spec_tinatra.rb
|
111
|
+
- examples/simple.rb
|