akane 0.0.1 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: da68e17edf6170994c230591963faaa2f127ce0a
4
- data.tar.gz: 112e4fd65c01fbd1bc45c5bf35fab09824482e42
3
+ metadata.gz: 0bd862e8bde263f78e295317635f8bb4eb0256cd
4
+ data.tar.gz: 4b64ada85e74c5018bc7f013c3f37d850cccb7e5
5
5
  SHA512:
6
- metadata.gz: 4029d0d629134c6b7e27bafdcfc72747ef7ae104b97a4c303b2175278384c298b6b993169442f2fabe76aa57c322f5438e0f88b1c2e657127da78fb273a86833
7
- data.tar.gz: 60e2d7f0b8387798df35547b334e1e8b9dc40300f3c6a05455cbaa0d4f86dff0d201654477e741b1fb346dcf137d6fa18e2fab08daa2b662e9551e4315b75766
6
+ metadata.gz: 2015deae33ec6b5598a17743dc308f01ce8cf452819f1f2ca2334b1a37365897fb79c7f7d8676bb1618ebe5bc9ac98d3e224d39cd34738bad89cecb038029343
7
+ data.tar.gz: fe3250c3bc69de4bafcad0f68ea3d488efdf0ee75d7718e04eabe27f3ce2a400a200fab02bb1fe124858dab17d430fa2555277278b38cf161ae38696e4f681da
data/akane.gemspec CHANGED
@@ -18,8 +18,9 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency "tweetstream", "~> 2.6.0"
22
21
  spec.add_dependency "elasticsearch", "~> 0.4.1"
22
+ spec.add_dependency "twitter", "~> 5.5.1"
23
+ spec.add_dependency "oauth", ">= 0.4.7"
23
24
 
24
25
  spec.add_development_dependency "bundler"
25
26
  spec.add_development_dependency "rake"
data/lib/akane/cli.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'akane/manager'
2
2
  require 'akane/config'
3
+ require 'optparse'
3
4
 
4
5
  module Akane
5
6
  class CLI
@@ -20,6 +21,35 @@ module Akane
20
21
  manager.run
21
22
  end
22
23
 
24
+ def auth
25
+ require 'twitter'
26
+
27
+ consumer = config.consumer
28
+
29
+ request_token = consumer.get_request_token
30
+ puts "Allow me using this URL: #{request_token.authorize_url}"
31
+ print "Then type shown PIN: "
32
+ pin = $stdin.gets.chomp
33
+ print "Authorizing... "
34
+
35
+ access_token = request_token.get_access_token(oauth_verifier: pin)
36
+ twitter = Twitter::REST::Client.new(
37
+ consumer_key: config[:consumer]['token'],
38
+ consumer_secret: config[:consumer]['secret'],
39
+ access_token: access_token.token,
40
+ access_token_secret: access_token.secret,
41
+ )
42
+ puts "done.\n\n"
43
+
44
+ puts <<-EOY
45
+ ---
46
+ accounts:
47
+ #{twitter.current_user.screen_name}:
48
+ token: #{access_token.token}
49
+ secret: #{access_token.secret}
50
+ EOY
51
+ end
52
+
23
53
  def help
24
54
  puts <<-EOH
25
55
  Usage:
data/lib/akane/config.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'yaml'
2
2
  require 'logger'
3
+ require 'oauth'
3
4
 
4
5
  module Akane
5
6
  class Config
@@ -18,6 +19,13 @@ module Akane
18
19
  @hash[k.to_s]
19
20
  end
20
21
 
22
+ def consumer
23
+ consumer = self[:consumer]
24
+ return nil unless consumer
25
+ OAuth::Consumer.new(consumer['token'], consumer['secret'],
26
+ site: 'https://api.twitter.com/')
27
+ end
28
+
21
29
  def logger
22
30
  Logger.new(@hash["log"] || $stdout)
23
31
  end
data/lib/akane/manager.rb CHANGED
@@ -1,4 +1,3 @@
1
- require 'eventmachine'
2
1
  require 'akane/config'
3
2
  require 'akane/recorder'
4
3
  require 'akane/receivers/stream'
@@ -53,27 +52,14 @@ module Akane
53
52
  @logger.info "Starting receivers..."
54
53
  @receivers.each(&:start)
55
54
  @logger.info "Starting recorder..."
56
- if EM.reactor_running?
57
- EM.defer { @recorder.run }
58
- else
59
- @recorder.run
60
- end
55
+ @recorder.run
61
56
  end
62
57
 
63
58
  def run
64
59
  @logger.info "Running..."
65
60
  self.prepare()
66
61
 
67
- if EM.reactor_running?
68
- start()
69
- else
70
- @logger.info "Diving into Eventmachine"
71
- EM.epoll
72
- EM.kqueue
73
- EM.run do
74
- start()
75
- end
76
- end
62
+ start()
77
63
  end
78
64
 
79
65
  private
@@ -1,61 +1,53 @@
1
1
  require 'akane/receivers/abstract_receiver'
2
- require 'tweetstream'
2
+ require 'twitter'
3
3
 
4
4
  module Akane
5
5
  module Receivers
6
6
  class Stream < AbstractReceiver
7
7
  def initialize(*)
8
8
  super
9
- @running = false
9
+ @thread = nil
10
10
  end
11
11
 
12
- def running?() @running end
12
+ def running?() !!(@thread && @thread.alive?) end
13
13
 
14
14
  def stream
15
- @stream ||= TweetStream::Client.new(
16
- auth_method: :oauth,
15
+ @stream ||= Twitter::Streaming::Client.new(
17
16
  consumer_key: @consumer[:token],
18
17
  consumer_secret: @consumer[:secret],
19
- oauth_token: @account[:token],
20
- oauth_token_secret: @account[:secret]
21
- ).tap { |stream|
22
- stream.on_anything do |hash|
23
- invoke(:event, hash) if hash["event"]
24
- end
25
-
26
- stream.on_timeline_status do |tweet|
27
- invoke(:tweet, tweet)
28
- end
29
-
30
- stream.on_delete do |tweet_id, user_id|
31
- invoke(:delete, user_id, tweet_id)
32
- end
18
+ access_token: @account[:token],
19
+ access_token_secret: @account[:secret]
20
+ )
21
+ end
33
22
 
34
- stream.on_direct_message do |message|
35
- invoke(:message, message)
36
- end
23
+ attr_reader :thread
37
24
 
38
- stream.on_inited do
39
- @logger.info "Stream: inited"
40
- end
25
+ def start
26
+ @logger.info "Stream : Starting"
41
27
 
42
- stream.on_reconnect do
43
- @logger.info "Stream: reconnected"
28
+ @thread = Thread.new do
29
+ stream.user do |obj|
30
+ case obj
31
+ when Twitter::Tweet
32
+ invoke(:tweet, obj)
33
+ when Twitter::DirectMessage
34
+ invoke(:message, obj)
35
+ when Twitter::Streaming::DeletedTweet
36
+ invoke(:delete, obj.user_id, obj.id)
37
+ when Twitter::Streaming::Event
38
+ invoke(:event,
39
+ 'event' => obj.name, 'source' => obj.source,
40
+ 'target' => obj.target, 'target_object' => obj.target_object)
41
+ end
44
42
  end
45
- }
46
- end
43
+ end
47
44
 
48
- def start
49
- @logger.info "Stream : Starting"
50
- stream.userstream
51
- @running = true
52
45
  self
53
46
  end
54
47
 
55
48
  def stop
56
- stream.stop_stream
57
- @stream = nil
58
- @running = false
49
+ @thread.tap(&:kill).join
50
+ @thread = nil
59
51
  self
60
52
  end
61
53
  end
@@ -39,11 +39,12 @@ module Akane
39
39
 
40
40
  def perform(action, account, *payload, raise_errors: false)
41
41
  if action == :record_tweet
42
- return if @recently_performed[payload.last["id"]]
43
- @recently_performed.flag!(payload.last["id"])
42
+ return if @recently_performed[payload.last[:id]]
43
+ @recently_performed.flag!(payload.last[:id])
44
44
 
45
- if payload.last["retweeted_status"]
46
- perform(:record_tweet, account, payload.last["retweeted_status"], raise_errors: raise_errors)
45
+ # WTF: Twitter::NullObject
46
+ unless payload.last[:retweeted_status].nil?
47
+ perform(:record_tweet, account, payload.last[:retweeted_status], raise_errors: raise_errors)
47
48
  end
48
49
  end
49
50
 
@@ -64,7 +65,7 @@ module Akane
64
65
  begin
65
66
  self.dequeue(raise_errors)
66
67
  rescue Exception => e
67
- raise e if e === Interrupt
68
+ raise e if Interrupt === e
68
69
  raise e if raise_errors
69
70
  @logger.error "Error while recorder dequing: #{e.inspect}"
70
71
  @logger.error e.backtrace
@@ -17,10 +17,10 @@ module Akane
17
17
  end
18
18
 
19
19
  def record_tweet(account, tweet)
20
- timeline_io.puts "[#{tweet["created_at"].xmlschema}][#{account}] #{tweet["user"]["screen_name"]}: " \
21
- "#{tweet["text"].gsub(/\r?\n/,' ')} (#{tweet["user"]["id"]},#{tweet["id"]})"
20
+ timeline_io.puts "[#{tweet[:created_at].xmlschema}][#{account}] #{tweet[:user][:screen_name]}: " \
21
+ "#{tweet[:text].gsub(/\r?\n/,' ')} (#{tweet[:user][:id]},#{tweet[:id]})"
22
22
 
23
- tweets_io_for_user(tweet["user"]["id"], tweet["user"]["screen_name"]) do |io|
23
+ tweets_io_for_user(tweet[:user][:id], tweet[:user][:screen_name]) do |io|
24
24
  io.puts tweet.attrs.to_json
25
25
  end
26
26
  end
@@ -33,16 +33,16 @@ module Akane
33
33
  end
34
34
 
35
35
  def record_event(account, event)
36
- event_io.puts event.merge("happened_on" => account).to_json
36
+ event_io.puts event.merge(:happened_on => account).to_json
37
37
  end
38
38
 
39
39
  def record_message(account, message)
40
- messages_raw_io_for_user(message["sender"]["id"], message["sender"]["screen_name"]) do |io|
40
+ messages_raw_io_for_user(message[:sender][:id], message[:sender][:screen_name]) do |io|
41
41
  io.puts message.attrs.to_json
42
42
  end
43
- messages_io_for_user(message["sender"]["id"], message["sender"]["screen_name"]) do |io|
44
- io.puts "[#{message["created_at"].xmlschema}] #{message["sender"]["screen_name"]} -> #{message["recipient"]["screen_name"]}:" \
45
- " #{message["text"]} (#{message["sender"]["id"]} -> #{message["recipient"]["id"]},#{message["id"]})"
43
+ messages_io_for_user(message[:sender][:id], message[:sender][:screen_name]) do |io|
44
+ io.puts "[#{message[:created_at].xmlschema}] #{message[:sender][:screen_name]} -> #{message[:recipient][:screen_name]}:" \
45
+ " #{message[:text]} (#{message[:sender][:id]} -> #{message[:recipient][:id]},#{message[:id]})"
46
46
  end
47
47
  end
48
48
 
data/lib/akane/util.rb ADDED
@@ -0,0 +1,18 @@
1
+ module Akane
2
+ module Util
3
+ class << self
4
+ def symbolish_hash(hash)
5
+ Hash[hash.map { |k, v|
6
+ [
7
+ k.is_a?(Symbol) ? k : k.to_s.to_sym,
8
+ case v
9
+ when Hash; symbolish_hash(v)
10
+ when Array; v.map{ |i| i.kind_of?(Hash) ? symbolish_hash(i) : i }
11
+ else; v
12
+ end
13
+ ]
14
+ }]
15
+ end
16
+ end
17
+ end
18
+ end
data/lib/akane/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Akane
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
data/spec/manager_spec.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require 'spec_helper'
2
- require 'eventmachine'
3
2
  require 'akane/manager'
4
3
  require 'akane/receivers/stream'
5
4
  require 'akane/storages/mock'
@@ -29,10 +28,6 @@ describe Akane::Manager do
29
28
 
30
29
  subject { Akane::Manager.new(config) }
31
30
 
32
- before do
33
- EM.stub(:run) { |&block| block.call }
34
- end
35
-
36
31
  # receivers -> manager -> recorder -> storage
37
32
 
38
33
  describe "#prepare" do
@@ -7,13 +7,13 @@ describe Akane::Receivers::Stream do
7
7
  subject { described_class.new(consumer: {token: 'consumer-token', secret: 'consumer-secret'}, account: {token: '42-access-token', secret: 'access-secret'}, config: config, logger: Logger.new(nil)) }
8
8
 
9
9
  after(:each) do
10
- TweetStream::MockClient.clients.clear
10
+ Twitter::Streaming::MockClient.clients.clear
11
11
  end
12
12
 
13
13
  describe "#start" do
14
14
  it "starts listening" do
15
- expect { subject.start } \
16
- .to change { TweetStream::MockClient.clients.size } \
15
+ expect { subject.start; 100.times { break if subject.thread.status == 'sleep'; sleep 0.1 } } \
16
+ .to change { Twitter::Streaming::MockClient.clients.size } \
17
17
  .by(1)
18
18
  end
19
19
 
@@ -27,11 +27,12 @@ describe Akane::Receivers::Stream do
27
27
  describe "#stop" do
28
28
  before do
29
29
  subject.start
30
+ 100.times { break if subject.thread.status == 'sleep'; sleep 0.1 }
30
31
  end
31
32
 
32
33
  it "stops listening" do
33
34
  expect { subject.stop } \
34
- .to change { TweetStream::MockClient.clients.size } \
35
+ .to change { Twitter::Streaming::MockClient.clients.size } \
35
36
  .by(-1)
36
37
  end
37
38
 
@@ -45,36 +46,51 @@ describe Akane::Receivers::Stream do
45
46
  describe "when received tweet" do
46
47
  before do
47
48
  subject.start
49
+ 100.times { break if subject.thread.status == 'sleep'; sleep 0.1 }
48
50
  end
49
51
 
50
52
  it "calls on_tweet hook" do
51
53
  called = nil
52
- subject.on_tweet do |tweet|
53
- called = tweet
54
+ subject.on_tweet do |t|
55
+ called = t
54
56
  end
55
- TweetStream::MockClient.invoke('timeline_status', foo: :bar)
56
- expect(called).to eq(foo: :bar)
57
+
58
+ tweet = Twitter::Tweet.new(id: 1)
59
+ Twitter::Streaming::MockClient.invoke(tweet)
60
+
61
+ Twitter::Streaming::MockClient.invoke(:disconnect)
62
+ subject.thread.join
63
+
64
+ expect(called).to eq(tweet)
57
65
  end
58
66
  end
59
67
 
60
68
  describe "when received message" do
61
69
  before do
62
70
  subject.start
71
+ 100.times { break if subject.thread.status == 'sleep'; sleep 0.1 }
63
72
  end
64
73
 
65
74
  it "calls on_message hook" do
66
75
  called = nil
67
- subject.on_message do |message|
68
- called = message
76
+ subject.on_message do |m|
77
+ called = m
69
78
  end
70
- TweetStream::MockClient.invoke('direct_message', foo: :bar)
71
- expect(called).to eq(foo: :bar)
79
+
80
+ message = Twitter::DirectMessage.new(id: 1)
81
+ Twitter::Streaming::MockClient.invoke(message)
82
+
83
+ Twitter::Streaming::MockClient.invoke(:disconnect)
84
+ subject.thread.join
85
+
86
+ expect(called).to eq(message)
72
87
  end
73
88
  end
74
89
 
75
90
  describe "when received deletion" do
76
91
  before do
77
92
  subject.start
93
+ 100.times { break if subject.thread.status == 'sleep'; sleep 0.1 }
78
94
  end
79
95
 
80
96
  it "calls on_delete hook" do
@@ -82,7 +98,13 @@ describe Akane::Receivers::Stream do
82
98
  subject.on_delete do |u,t|
83
99
  called = [u,t]
84
100
  end
85
- TweetStream::MockClient.invoke('delete', 424242, 42)
101
+
102
+ deletion = Twitter::Streaming::DeletedTweet.new(user_id: 42, id: 424242)
103
+ Twitter::Streaming::MockClient.invoke(deletion)
104
+
105
+ Twitter::Streaming::MockClient.invoke(:disconnect)
106
+ subject.thread.join
107
+
86
108
  expect(called).to eq([42,424242])
87
109
  end
88
110
  end
@@ -90,6 +112,7 @@ describe Akane::Receivers::Stream do
90
112
  describe "when received event" do
91
113
  before do
92
114
  subject.start
115
+ 100.times { break if subject.thread.status == 'sleep'; sleep 0.1 }
93
116
  end
94
117
 
95
118
  it "calls on_event hook" do
@@ -97,9 +120,14 @@ describe Akane::Receivers::Stream do
97
120
  subject.on_event do |h|
98
121
  called = h
99
122
  end
100
- TweetStream::MockClient.invoke('anything', "event" => "favorite")
101
- TweetStream::MockClient.invoke('anything', "something" => "else")
102
- expect(called).to eq("event" => "favorite")
123
+ event = Twitter::Streaming::Event.new(event: 'favorite', source: {id: 1}, target: {id: 2}, target_object: {id: 3})
124
+ Twitter::Streaming::MockClient.invoke(event)
125
+
126
+ Twitter::Streaming::MockClient.invoke(:disconnect)
127
+ subject.thread.join
128
+
129
+ expect(called).to eq('event' => event.name, 'source' => event.source,
130
+ 'target' => event.target, 'target_object' => event.target_object)
103
131
  end
104
132
  end
105
133
  end
@@ -11,26 +11,26 @@ describe Akane::Recorder do
11
11
 
12
12
  describe "recording tweets" do
13
13
  it "records tweet" do
14
- storages[0].should_receive(:record_tweet).with('a', {"id" => 42})
15
- subject.record_tweet('a', "id" => 42)
14
+ storages[0].should_receive(:record_tweet).with('a', {id: 42})
15
+ subject.record_tweet('a', id: 42)
16
16
  subject.dequeue(true)
17
17
  end
18
18
 
19
19
  it "doesn't record tweets which already recorded recently" do
20
- storages[0].should_receive(:record_tweet).with('a', {"id" => 40})
21
- storages[0].should_receive(:record_tweet).with('a', {"id" => 42})
20
+ storages[0].should_receive(:record_tweet).with('a', {id: 40})
21
+ storages[0].should_receive(:record_tweet).with('a', {id: 42})
22
22
 
23
- subject.record_tweet('a', "id" => 40)
24
- subject.record_tweet('a', "id" => 42)
23
+ subject.record_tweet('a', id: 40)
24
+ subject.record_tweet('a', id: 42)
25
25
  subject.dequeue(true)
26
26
  subject.dequeue(true)
27
- subject.record_tweet('a', "id" => 42)
27
+ subject.record_tweet('a', id: 42)
28
28
  subject.dequeue(true)
29
29
  end
30
30
 
31
31
  it "records retweeted tweet" do
32
- tweet = {"id" => 42, "text" => "foo", "user" => {"id" => 1, "screen_name" => "a"}}
33
- retweet = {"id" => 43, "text" => "RT @a: foo", "user" => {"id" => 2, "screen_name" => "b"}, "retweeted_status" => tweet}
32
+ tweet = {id: 42, text: "foo", user: {id: 1, screen_name: "a"}}
33
+ retweet = {id: 43, text: "RT @a: foo", user: {id: 2, screen_name: "b"}, retweeted_status: tweet}
34
34
  storages[0].should_receive(:record_tweet).with('a', retweet)
35
35
  storages[0].should_receive(:record_tweet).with('a', tweet)
36
36
  subject.record_tweet('a', retweet)
@@ -49,18 +49,18 @@ describe Akane::Recorder do
49
49
 
50
50
  describe "recording messages" do
51
51
  it "records message" do
52
- subject.record_message('foo', {"id" => 42})
52
+ subject.record_message('foo', {id: 42})
53
53
 
54
- storages[0].should_receive(:record_message).with('foo', "id" => 42)
54
+ storages[0].should_receive(:record_message).with('foo', id: 42)
55
55
  subject.dequeue(true)
56
56
  end
57
57
  end
58
58
 
59
59
  describe "recording event" do
60
60
  it "records event" do
61
- subject.record_event('foo', {"event" => "favorite"})
61
+ subject.record_event('foo', {event: "favorite"})
62
62
 
63
- storages[0].should_receive(:record_event).with('foo', "event" => "favorite")
63
+ storages[0].should_receive(:record_event).with('foo', event: "favorite")
64
64
  subject.dequeue(true)
65
65
  end
66
66
  end
@@ -72,10 +72,10 @@ describe Akane::Recorder do
72
72
  end
73
73
 
74
74
  it "continues dequeuing the queue" do
75
- storages[0].should_receive(:record_tweet).with('a', {"id" => 42})
76
- storages[0].should_receive(:record_tweet).with('b', {"id" => 43})
77
- subject.record_tweet('a', "id" => 42)
78
- subject.record_tweet('b', "id" => 43)
75
+ storages[0].should_receive(:record_tweet).with('a', {:id => 42})
76
+ storages[0].should_receive(:record_tweet).with('b', {:id => 43})
77
+ subject.record_tweet('a', :id => 42)
78
+ subject.record_tweet('b', :id => 43)
79
79
  10.times { break if subject.queue_length.zero?; sleep 0.1 }
80
80
  end
81
81
 
data/spec/spec_helper.rb CHANGED
@@ -13,4 +13,4 @@ RSpec.configure do |config|
13
13
  config.order = 'random'
14
14
  end
15
15
 
16
- require_relative './support/mock_tweetstream'
16
+ require_relative './support/mock_twitter_streaming'
@@ -0,0 +1,98 @@
1
+ require 'twitter'
2
+ require 'thread'
3
+
4
+ class Twitter::Streaming::MockClient
5
+ Original = Twitter::Streaming::Client
6
+
7
+ class << self
8
+ def clients
9
+ @clients ||= []
10
+ end
11
+
12
+ def clients_mutex
13
+ @clients_mutex ||= Mutex.new
14
+ end
15
+
16
+ def add_client(client)
17
+ clients_mutex.synchronize {
18
+ clients << client
19
+ }
20
+ end
21
+
22
+ def remove_client(client)
23
+ clients_mutex.synchronize {
24
+ clients.delete client
25
+ }
26
+ end
27
+
28
+ def invoke(*args)
29
+ clients.each do |client|
30
+ client.invoke(*args)
31
+ end
32
+
33
+ self
34
+ end
35
+
36
+ def enable!
37
+ klass = self
38
+ Twitter::Streaming.instance_eval {
39
+ remove_const :Client
40
+ const_set :Client, klass
41
+ }
42
+ end
43
+
44
+ def disable!
45
+ klass = Original
46
+ Twitter::Streaming.instance_eval {
47
+ remove_const :Client
48
+ const_set :Client, klass
49
+ }
50
+ end
51
+ end
52
+
53
+ def initialize(options={})
54
+ @options = options
55
+ @queues = []
56
+ @mutex = Mutex.new
57
+ end
58
+
59
+ attr_accessor :options, :hooks
60
+
61
+ def invoke(*args)
62
+ @queues.each do |queue|
63
+ queue << args
64
+ end
65
+ end
66
+
67
+ def user(options = {}, &block)
68
+ connect(&block)
69
+ end
70
+
71
+ private
72
+
73
+ def connect
74
+ queue = Queue.new
75
+ was_empty = nil
76
+ @mutex.synchronize {
77
+ was_empty = @queues.empty?
78
+ @queues << queue
79
+
80
+ if was_empty
81
+ self.class.add_client self
82
+ end
83
+ }
84
+ while _ = queue.pop
85
+ break if _ == [:disconnect]
86
+ yield *_
87
+ end
88
+ ensure
89
+ @mutex.synchronize {
90
+ @queues.delete queue
91
+ if @queues.empty?
92
+ self.class.remove_client self
93
+ end
94
+ }
95
+ end
96
+ end
97
+
98
+ Twitter::Streaming::MockClient.enable!
data/spec/util_spec.rb ADDED
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+ require 'akane/util'
3
+
4
+ describe Akane::Util do
5
+ describe ".symbolish_hash" do
6
+ let(:target) { {'a' => 1, 'b' => 2} }
7
+ subject { described_class.symbolish_hash(target) }
8
+
9
+ it { should eq(a: 1, b: 2) }
10
+
11
+ context "with Hash" do
12
+ let(:target) { {'a' => {'b' => 2}} }
13
+ it { should eq(a: {b: 2}) }
14
+
15
+ context "with nested Hash" do
16
+ let(:target) { {'a' => {'b' => {'c' => 4}}} }
17
+ it { should eq(a: {b: {c: 4}}) }
18
+ end
19
+
20
+ context "with nested Array" do
21
+ let(:target) { {'a' => {'b' => [{'c' => 4}]}} }
22
+ it { should eq(a: {b: [{c: 4}]}) }
23
+ end
24
+
25
+ context "with nested Array" do
26
+ let(:target) { {'a' => {'b' => [{'c' => {'d' => 5}}]}} }
27
+ it { should eq(a: {b: [{c: {d: 5}}]}) }
28
+ end
29
+ end
30
+
31
+ context "with Hash in Array" do
32
+ let(:target) { {'a' => [1,2,{'b' => 3}]} }
33
+ it { should eq(a: [1,2,{b: 3}]) }
34
+ end
35
+ end
36
+ end
metadata CHANGED
@@ -1,43 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: akane
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shota Fukumori (sora_h)
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-14 00:00:00.000000000 Z
11
+ date: 2014-01-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: tweetstream
14
+ name: elasticsearch
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 2.6.0
19
+ version: 0.4.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 2.6.0
26
+ version: 0.4.1
27
27
  - !ruby/object:Gem::Dependency
28
- name: elasticsearch
28
+ name: twitter
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.4.1
33
+ version: 5.5.1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.4.1
40
+ version: 5.5.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: oauth
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 0.4.7
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 0.4.7
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: bundler
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -122,6 +136,7 @@ files:
122
136
  - lib/akane/storages/file.rb
123
137
  - lib/akane/storages/mock.rb
124
138
  - lib/akane/storages/stdout.rb
139
+ - lib/akane/util.rb
125
140
  - lib/akane/version.rb
126
141
  - spec/config_spec.rb
127
142
  - spec/manager_spec.rb
@@ -132,6 +147,8 @@ files:
132
147
  - spec/storages/abstract_storage_spec.rb
133
148
  - spec/storages/mock_spec.rb
134
149
  - spec/support/mock_tweetstream.rb
150
+ - spec/support/mock_twitter_streaming.rb
151
+ - spec/util_spec.rb
135
152
  homepage: https://github.com/sorah/akane
136
153
  licenses:
137
154
  - MIT
@@ -166,4 +183,6 @@ test_files:
166
183
  - spec/storages/abstract_storage_spec.rb
167
184
  - spec/storages/mock_spec.rb
168
185
  - spec/support/mock_tweetstream.rb
186
+ - spec/support/mock_twitter_streaming.rb
187
+ - spec/util_spec.rb
169
188
  has_rdoc: