drip 0.0.1

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.
@@ -0,0 +1,5 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'drip_tw'
3
+
4
+ app = DripDemo.new
5
+ app.update("@m_seki なんで?", 76285215248617472)
@@ -0,0 +1,52 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'drip_tw'
3
+
4
+ def last_tweet_id
5
+ key = nil
6
+ while kv = MyDrip.older(key, 'DripDemo MyStatus')
7
+ key, value = kv
8
+ return value['id'] if value['id']
9
+ end
10
+ nil
11
+ end
12
+
13
+ def get_user_timeline(app, since_id, max_id)
14
+ count = 3
15
+ begin
16
+ ary = app.user_timeline(since_id, max_id)
17
+ rescue
18
+ p $!
19
+ count -= 1
20
+ return nil, [] if count <= 0
21
+ sleep 5
22
+ retry
23
+ end
24
+ max_id = nil
25
+ ary.reverse_each do |event|
26
+ next unless event['id']
27
+ max_id = event['id'] - 1
28
+ break
29
+ end
30
+ return max_id, ary
31
+ end
32
+
33
+ app = DripDemo.new
34
+
35
+ since_id = last_tweet_id
36
+
37
+ max_id = nil
38
+ timeline = []
39
+ while true
40
+ max_id, ary = get_user_timeline(app, since_id, max_id)
41
+ break if ary.empty?
42
+ pp [ary[0]['text'], ary[-1]['text']] rescue nil
43
+ sleep 5
44
+ timeline += ary
45
+ end
46
+
47
+ p [timeline.size, 'continue?']
48
+ gets
49
+
50
+ timeline.reverse_each do |event|
51
+ MyDrip.write(event, 'DripDemo MyStatus')
52
+ end
@@ -0,0 +1,140 @@
1
+ #
2
+ # import from https://github.com/shibason/rb-simple-oauth
3
+ # see: http://d.hatena.ne.jp/shibason/20090809/1249764381
4
+ require 'uri'
5
+ require 'net/http'
6
+ require 'openssl'
7
+
8
+ class SimpleOAuth
9
+ def initialize(consumer_key, consumer_secret, token, token_secret)
10
+ @consumer_key = consumer_key
11
+ @consumer_secret = consumer_secret
12
+ @token = token
13
+ @token_secret = token_secret
14
+ # This class supports only 'HMAC-SHA1' as signature method at present.
15
+ @signature_method = 'HMAC-SHA1'
16
+ end
17
+
18
+ def get(url, headers = {})
19
+ request(:GET, url, nil, headers)
20
+ end
21
+
22
+ def head(url, headers = {})
23
+ request(:HEAD, url, nil, headers)
24
+ end
25
+
26
+ def post(url, body = nil, headers = {})
27
+ request(:POST, url, body, headers)
28
+ end
29
+
30
+ def put(url, body = nil, headers = {})
31
+ request(:PUT, url, body, headers)
32
+ end
33
+
34
+ def delete(url, headers = {})
35
+ request(:DELETE, url, nil, headers)
36
+ end
37
+
38
+ private
39
+ def request(method, url, body = nil, headers = {})
40
+ method = method.to_s
41
+ url = URI.parse(url)
42
+ request = create_http_request(method, url.request_uri, body, headers)
43
+ request['Authorization'] = auth_header(method, url, request.body)
44
+ Net::HTTP.new(url.host, url.port).request(request)
45
+ end
46
+
47
+ RESERVED_CHARACTERS = /[^a-zA-Z0-9\-\.\_\~]/
48
+
49
+ def escape(value)
50
+ URI.escape(value.to_s, RESERVED_CHARACTERS)
51
+ end
52
+
53
+ def encode_parameters(params, delimiter = '&', quote = nil)
54
+ if params.is_a?(Hash)
55
+ params = params.map do |key, value|
56
+ "#{escape(key)}=#{quote}#{escape(value)}#{quote}"
57
+ end
58
+ else
59
+ params = params.map { |value| escape(value) }
60
+ end
61
+ delimiter ? params.join(delimiter) : params
62
+ end
63
+
64
+ VERSION = '0.1'
65
+ USER_AGENT = "SimpleOAuth/#{VERSION}"
66
+
67
+ def create_http_request(method, path, body, headers)
68
+ method = method.capitalize.to_sym
69
+ request = Net::HTTP.const_get(method).new(path, headers)
70
+ request['User-Agent'] = USER_AGENT
71
+ if method == :Post || method == :Put
72
+ request.body = body.is_a?(Hash) ? encode_parameters(body) : body.to_s
73
+ request.content_type = 'application/x-www-form-urlencoded'
74
+ request.content_length = (request.body || '').length
75
+ end
76
+ request
77
+ end
78
+
79
+ def auth_header(method, url, body)
80
+ parameters = oauth_parameters
81
+ parameters[:oauth_signature] = signature(method, url, body, parameters)
82
+ 'OAuth ' + encode_parameters(parameters, ', ', '"')
83
+ end
84
+
85
+ OAUTH_VERSION = '1.0'
86
+
87
+ def oauth_parameters
88
+ {
89
+ :oauth_consumer_key => @consumer_key,
90
+ :oauth_token => @token,
91
+ :oauth_signature_method => @signature_method,
92
+ :oauth_timestamp => timestamp,
93
+ :oauth_nonce => nonce,
94
+ :oauth_version => OAUTH_VERSION
95
+ }
96
+ end
97
+
98
+ def timestamp
99
+ Time.now.to_i.to_s
100
+ end
101
+
102
+ def nonce
103
+ OpenSSL::Digest::Digest.hexdigest('MD5', "#{Time.now.to_f}#{rand}")
104
+ end
105
+
106
+ def signature(*args)
107
+ base64(digest_hmac_sha1(signature_base_string(*args)))
108
+ end
109
+
110
+ def base64(value)
111
+ [ value ].pack('m').gsub(/\n/, '')
112
+ end
113
+
114
+ def digest_hmac_sha1(value)
115
+ OpenSSL::HMAC.digest(OpenSSL::Digest::SHA1.new, secret, value)
116
+ end
117
+
118
+ def secret
119
+ escape(@consumer_secret) + '&' + escape(@token_secret)
120
+ end
121
+
122
+ def signature_base_string(method, url, body, parameters)
123
+ method = method.upcase
124
+ base_url = signature_base_url(url)
125
+ parameters = normalize_parameters(parameters, body, url.query)
126
+ encode_parameters([ method, base_url, parameters ])
127
+ end
128
+
129
+ def signature_base_url(url)
130
+ URI::HTTP.new(url.scheme, url.userinfo, url.host, nil, nil, url.path,
131
+ nil, nil, nil)
132
+ end
133
+
134
+ def normalize_parameters(parameters, body, query)
135
+ parameters = encode_parameters(parameters, nil)
136
+ parameters += body.split('&') if body
137
+ parameters += query.split('&') if query
138
+ parameters.sort.join('&')
139
+ end
140
+ end
@@ -0,0 +1,154 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'my_drip'
3
+ require 'MeCab'
4
+ require 'pp'
5
+
6
+ class Bag
7
+ def initialize
8
+ @bag = Hash.new(0)
9
+ @size = 0
10
+ @cache = nil
11
+ end
12
+ attr_reader :size
13
+
14
+ def push(obj)
15
+ @cache = nil
16
+ @bag[obj] += 1
17
+ @size += 1
18
+ obj
19
+ end
20
+
21
+ def sample
22
+ @cache = @bag.sort_by {|k, v| v} unless @cache
23
+ prob = rand(@size)
24
+ @cache.each do |k, v|
25
+ prob -= v
26
+ return k if prob < 0
27
+ end
28
+ end
29
+ end
30
+
31
+ class BagInBag < Bag
32
+ def initialize(&blk)
33
+ super
34
+ @bag_in_bag = Hash.new {|h, k| h[k] = blk.call}
35
+ end
36
+
37
+ def push(obj, *rest)
38
+ super(obj)
39
+ @bag_in_bag[obj].push(*rest)
40
+ end
41
+
42
+ def [](key, *rest)
43
+ if rest.empty?
44
+ @bag_in_bag[key]
45
+ else
46
+ @bag_in_bag[key][*rest]
47
+ end
48
+ end
49
+ end
50
+
51
+ class EntityEnum
52
+ def initialize(str, entity)
53
+ @str = str || ''
54
+ @entity = []
55
+ (entity || []).each do |k, v|
56
+ @entity += v
57
+ end
58
+ end
59
+
60
+ def each
61
+ unless @entity
62
+ yield(@str, nil)
63
+ return
64
+ end
65
+ ary = @entity.sort_by {|e| e['indices'][0]}
66
+ cursor = 0
67
+ while head = ary.shift
68
+ left, right = head['indices']
69
+ if left > cursor
70
+ yield(@str[cursor ... left], nil)
71
+ end
72
+ yield(@str[left .. right], head)
73
+ cursor = right + 1
74
+ end
75
+ if @str.length > cursor
76
+ yield(@str[cursor ... @str.length], nil)
77
+ end
78
+ end
79
+ end
80
+
81
+ class Markov
82
+ def initialize
83
+ @bag = BagInBag.new { BagInBag.new { Bag.new } }
84
+ @start = Bag.new
85
+ @intern = Hash.new
86
+ end
87
+
88
+ def intern(str)
89
+ @intern[str] ||= str
90
+ @intern[str]
91
+ end
92
+
93
+ def add(ary)
94
+ return if ary.size <= 3
95
+ ary = ary.collect {|s| intern(s)}
96
+ @start.push(ary[0])
97
+ ary.each_cons(3) do |p0, p1, suffix|
98
+ @bag.push(p0, p1, suffix)
99
+ end
100
+ end
101
+
102
+ def generate(max_len=30)
103
+ s = @start.sample
104
+ ary = [s, @bag[s].sample]
105
+ max_len.times do
106
+ it = @bag[*ary[-2, 2]].sample
107
+ break if it == :eos
108
+ ary << it
109
+ end
110
+ ary
111
+ end
112
+ end
113
+
114
+ $screen_name = {}
115
+
116
+ def mention_user
117
+ " @#{$screen_name.keys.sample} "
118
+ end
119
+
120
+ def as_str(ary)
121
+ ary = ary.map {|x| x == :name ? mention_user : x}
122
+ ary.inject{|s,c|s+=(s+"\00"+c=~/\w\00\w/?" ":"")+c}
123
+ end
124
+
125
+ markov = Markov.new
126
+ m = MeCab::Tagger.new('-Owakati')
127
+
128
+ MyDrip.head(4000, 'DripDemo MyStatus').each do |k, v|
129
+ next if v['retweeted_status']
130
+ entity = v['entities']
131
+ str = v['text']
132
+ ary = []
133
+ EntityEnum.new(str, entity).each do |s, kind|
134
+ next if s == 'RT'
135
+ unless kind
136
+ ary += m.parse(s).split(' ')
137
+ else
138
+ ary <<:name if kind['screen_name']
139
+ if kind['screen_name']
140
+ $screen_name[kind['screen_name']] = true
141
+ end
142
+ end
143
+ end
144
+ markov.add(ary + [:eos])
145
+ end
146
+
147
+ while gets
148
+ 10.times do
149
+ ary = markov.generate
150
+ next if ary.size < 10
151
+ puts as_str(ary)
152
+ puts
153
+ end
154
+ end
@@ -0,0 +1,156 @@
1
+ require 'test/unit'
2
+ require '../lib/drip.rb'
3
+ require 'fileutils'
4
+
5
+ class TestDrip < Test::Unit::TestCase
6
+ def setup
7
+ @drip = Drip.new(nil)
8
+ end
9
+
10
+ def test_time_travel
11
+ @drip.write('age' => 1)
12
+ @drip.write('age' => 2)
13
+ @drip.write('age' => 3)
14
+ oid, value = @drip.older(nil)
15
+ assert_equal(value, 'age' => 3)
16
+ oid, value = @drip.older(oid)
17
+ assert_equal(value, 'age' => 2)
18
+ oid, value = @drip.older(oid)
19
+ assert_equal(value, 'age' => 1)
20
+ oid, value = @drip.older(oid)
21
+ assert_equal(oid, nil)
22
+ assert_equal(value, nil)
23
+
24
+ oid, value = @drip.newer(0)
25
+ assert_equal(value, 'age' => 1)
26
+ oid, value = @drip.newer(oid)
27
+ assert_equal(value, 'age' => 2)
28
+ oid, value = @drip.newer(oid)
29
+ assert_equal(value, 'age' => 3)
30
+ oid, value = @drip.newer(oid)
31
+ assert_equal(oid, nil)
32
+ assert_equal(value, nil)
33
+ end
34
+
35
+ def test_read
36
+ 11.times do |n|
37
+ @drip.write("n=#{n}" => 'x' * n, n => n, "n" => n, :symbol => n)
38
+ end
39
+ ary = @drip.read(0, 3)
40
+ assert_equal(ary.size, 3)
41
+ assert_equal(ary[0][1]['n'], 0)
42
+ assert_equal(ary[1][1]['n'], 1)
43
+ assert_equal(ary[2][1]['n'], 2)
44
+ ary = @drip.read(ary[2][0], 3)
45
+ assert_equal(ary.size, 3)
46
+ ary = @drip.read(ary[2][0], 3)
47
+ assert_equal(ary.size, 3)
48
+ ary = @drip.read(ary[2][0], 3)
49
+ assert_equal(ary.size, 2)
50
+
51
+ oid = @drip.write('latest', 'tag1', 'tag2')
52
+ oid, value, *tags = @drip.newer(oid - 1)
53
+ assert_equal(value, 'latest')
54
+ assert_equal(tags, ['tag1', 'tag2'])
55
+ end
56
+
57
+ def test_symbol_is_not_tag
58
+ @drip.write({:symbol => :symbol, 'string' => :string}, :symbol, 'string')
59
+ assert_raise(ArgumentError) {@drip.read_tag(0, :symbol, 1, 0)}
60
+ oid, value = @drip.older(@drip.time_to_key(Time.now))
61
+ assert_equal(value, {:symbol => :symbol, 'string' => :string})
62
+ end
63
+
64
+ def test_number_is_not_tag
65
+ @drip.write({5 => :five, 'string' => :string}, 5, 'string')
66
+ assert_equal(@drip.read_tag(0, 'string', 1, 0).size, 1)
67
+ assert_raise(ArgumentError) {@drip.read_tag(0, 5, 1, 0)}
68
+ end
69
+
70
+ def test_older_now_is_newest
71
+ @drip.write('age' => 1)
72
+ @drip.write('age' => 2)
73
+ @drip.write('age' => 3)
74
+ oid, value = @drip.older(nil)
75
+ assert_equal(value, 'age' => 3)
76
+ oid, value = @drip.older(@drip.time_to_key(Time.now))
77
+ assert_equal(value, 'age' => 3)
78
+
79
+ # newer(past)
80
+ assert_equal(@drip.newer(0)[1], 'age' => 1)
81
+ assert_equal(@drip.newer(0)[1], 'age' => 1)
82
+ end
83
+
84
+ def test_read_tag
85
+ 3.times do |n|
86
+ @drip.write({'n' => n}, 'n')
87
+ @drip.write({'n' => n, '2' => n * 2}, 'n', '2')
88
+ @drip.write({'n' => n, '2' => n * 2, '3' => n * 3}, 'n', '2', '3')
89
+ end
90
+
91
+ ary = @drip.read_tag(0, 'n', 10)
92
+ assert_equal(ary.size, 9)
93
+ assert_equal(ary[0][1]['n'], 0)
94
+ assert_equal(ary[0][2], 'n')
95
+ assert_equal(ary[2][4], '3')
96
+ end
97
+
98
+ def test_head
99
+ 10.times do |n|
100
+ @drip.write(n)
101
+ end
102
+
103
+ ary = @drip.head(3)
104
+ assert_equal(ary.size, 3)
105
+ assert_equal(ary[0][1], 7)
106
+ assert_equal(ary[2][1], 9)
107
+ end
108
+
109
+ def test_after
110
+ assert_equal(@drip.write_after(Time.at(1), 1), 1000000)
111
+ assert_equal(@drip.write_after(Time.at(2), 2), 2000000)
112
+ assert_equal(@drip.write_after(Time.at(3), 3), 3000000)
113
+ assert_equal(@drip.write_after(Time.at(4), 4), 4000000)
114
+ assert_equal(@drip.write_after(Time.at(4), 5), 4000001)
115
+ assert_equal(@drip.write_after(Time.at(2), 6), 4000002)
116
+ assert_equal(@drip.write_after(Time.at(5), 6), 5000000)
117
+ assert_equal(@drip.write_after(Time.at(5), 7), 5000001)
118
+ assert_equal(@drip.write_at(Time.at(6), 8), 6000000)
119
+ assert_raise(RuntimeError) {@drip.write_at(Time.at(6), 8)}
120
+ assert_equal(@drip.write_after(Time.at(5), 8), 6000001)
121
+ end
122
+ end
123
+
124
+ class TestDripUsingStorage < TestDrip
125
+ def remove_drip(dir='test_db')
126
+ FileUtils.rm_r(dir, :force => true)
127
+ end
128
+
129
+ def setup
130
+ remove_drip
131
+ @drip = Drip.new('test_db')
132
+ end
133
+
134
+ def teardown
135
+ remove_drip
136
+ end
137
+
138
+ def test_twice
139
+ 11.times do |n|
140
+ @drip.write("n=#{n}" => 'x' * n, n => n, "n" => n, :symbol => n)
141
+ end
142
+
143
+ drip = Drip.new('test_db')
144
+ ary = drip.read(0, 3)
145
+ assert_equal(ary.size, 3)
146
+ assert_equal(ary[0][1]['n'], 0)
147
+ assert_equal(ary[1][1]['n'], 1)
148
+ assert_equal(ary[2][1]['n'], 2)
149
+ ary = drip.read(ary[2][0], 3)
150
+ assert_equal(ary.size, 3)
151
+ ary = drip.read(ary[2][0], 3)
152
+ assert_equal(ary.size, 3)
153
+ ary = drip.read(ary[2][0], 3)
154
+ assert_equal(ary.size, 2)
155
+ end
156
+ end