akane 0.2.0 → 0.3.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 +4 -4
- data/README.md +8 -2
- data/akane.example.yml +11 -0
- data/lib/akane/manager.rb +63 -37
- data/lib/akane/receivers.rb +17 -0
- data/lib/akane/receivers/abstract_receiver.rb +9 -0
- data/lib/akane/receivers/stream.rb +21 -1
- data/lib/akane/storages.rb +17 -0
- data/lib/akane/version.rb +1 -1
- data/spec/manager_spec.rb +56 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8bc71995c8cc299ddc5b873403f69f427ab87f6d
|
4
|
+
data.tar.gz: cdffc166e5a090a3159c60e3e2507b51d4eac98c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 74c163daa0604773c155a7828f9417605ba200e9f041a91d879855cb3c5784a0bff53c25cbca4f10b7a39fa3c5334f39fdf8f463dc46f9c21484ca1d5dab763e
|
7
|
+
data.tar.gz: c75dde351210dfbec90073c72aa1c7c75320538e398d0c4232729b811936c2b9e89e074d594e8522fdcd278f6c39f2ae90419fa0303aaaaa7fd70a01119c5840
|
data/README.md
CHANGED
data/akane.example.yml
CHANGED
@@ -2,13 +2,24 @@
|
|
2
2
|
consumer:
|
3
3
|
token: CONSUMER_TOKEN
|
4
4
|
secret: CONSUMER_SECRET
|
5
|
+
|
6
|
+
# You can issue access tokens for accounts by using `akane auth` command.
|
5
7
|
accounts:
|
6
8
|
your_account_name1:
|
7
9
|
token: ACCESS_TOKEN1
|
8
10
|
secret: SECRET_TOKEN1
|
11
|
+
# You can specify custom receivers for each account.
|
12
|
+
# by default, `receivers: ["stream"]` will be used.
|
13
|
+
# receivers:
|
14
|
+
# - stream
|
15
|
+
# - stream:
|
16
|
+
# method: filter
|
17
|
+
# options:
|
18
|
+
# track: foo,bar,baz
|
9
19
|
your_account_name2:
|
10
20
|
token: ACCESS_TOKEN2
|
11
21
|
secret: SECRET_TOKEN2
|
22
|
+
|
12
23
|
storages:
|
13
24
|
- stdout
|
14
25
|
- file:
|
data/lib/akane/manager.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'akane/config'
|
2
2
|
require 'akane/recorder'
|
3
|
-
require 'akane/receivers
|
3
|
+
require 'akane/receivers'
|
4
|
+
require 'akane/storages'
|
4
5
|
|
5
6
|
module Akane
|
6
7
|
class Manager
|
@@ -11,43 +12,10 @@ module Akane
|
|
11
12
|
|
12
13
|
def prepare
|
13
14
|
@logger.info 'Preparing'
|
14
|
-
@receivers = @config["accounts"].map do |name, credential|
|
15
|
-
Akane::Receivers::Stream.new(
|
16
|
-
consumer: {token: @config["consumer"]["token"], secret: @config["consumer"]["secret"]},
|
17
|
-
account: {token: credential["token"], secret: credential["secret"]},
|
18
|
-
logger: @config.logger
|
19
|
-
).tap do |receiver|
|
20
|
-
@logger.info "Preparing... receiver - #{receiver.class}"
|
21
|
-
receiver.on_tweet( &(method(:on_tweet).to_proc.curry[name]))
|
22
|
-
receiver.on_message(&(method(:on_message).to_proc.curry[name]))
|
23
|
-
receiver.on_event( &(method(:on_event).to_proc.curry[name]))
|
24
|
-
receiver.on_delete( &(method(:on_delete).to_proc.curry[name]))
|
25
|
-
end
|
26
|
-
end
|
27
15
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
definition.map do |kind, config|
|
32
|
-
[kind, config]
|
33
|
-
end
|
34
|
-
when String
|
35
|
-
[[definition, {}]]
|
36
|
-
end
|
37
|
-
end.map do |kind, config|
|
38
|
-
@logger.info "Preparing... storage - #{kind}"
|
39
|
-
require "akane/storages/#{kind}"
|
40
|
-
Akane::Storages.const_get(kind.gsub(/(?:\A|_)(.)/) { $1.upcase }).new(
|
41
|
-
config: config,
|
42
|
-
logger: @config.logger
|
43
|
-
)
|
44
|
-
end
|
45
|
-
|
46
|
-
@recorder = Akane::Recorder.new(
|
47
|
-
@storages,
|
48
|
-
timeout: @config["timeout"] || 20,
|
49
|
-
logger: @config.logger
|
50
|
-
)
|
16
|
+
prepare_receivers
|
17
|
+
prepare_storages
|
18
|
+
prepare_recorder
|
51
19
|
|
52
20
|
@logger.info "Prepared with #{@storages.size} storage(s) and #{@receivers.size} receiver(s)"
|
53
21
|
end
|
@@ -129,5 +97,63 @@ module Akane
|
|
129
97
|
def on_delete(account, user_id, tweet_id)
|
130
98
|
@recorder.mark_as_deleted(account, user_id, tweet_id)
|
131
99
|
end
|
100
|
+
|
101
|
+
def prepare_receivers
|
102
|
+
@receivers = @config["accounts"].flat_map do |name, credential|
|
103
|
+
receiver_definitions = credential["receivers"] || ['stream']
|
104
|
+
|
105
|
+
receiver_definitions.map do |definition|
|
106
|
+
if definition.kind_of?(Hash)
|
107
|
+
if 1 < definition.size
|
108
|
+
@logger.warn "Only 1 receiver definition is used in one Hash instance."
|
109
|
+
end
|
110
|
+
|
111
|
+
kind, config = definition.each.first
|
112
|
+
else
|
113
|
+
kind, config = definition, {}
|
114
|
+
end
|
115
|
+
|
116
|
+
Akane::Receivers.find(kind).new(
|
117
|
+
consumer: {token: @config["consumer"]["token"], secret: @config["consumer"]["secret"]},
|
118
|
+
account: {token: credential["token"], secret: credential["secret"], name: name},
|
119
|
+
config: config,
|
120
|
+
logger: @config.logger
|
121
|
+
).tap do |receiver|
|
122
|
+
@logger.info "Preparing... receiver - #{receiver.class}"
|
123
|
+
receiver.on_tweet(&( method(:on_tweet).to_proc.curry[receiver.name]))
|
124
|
+
receiver.on_message(&(method(:on_message).to_proc.curry[receiver.name]))
|
125
|
+
receiver.on_event(&( method(:on_event).to_proc.curry[receiver.name]))
|
126
|
+
receiver.on_delete(&( method(:on_delete).to_proc.curry[receiver.name]))
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def prepare_storages
|
133
|
+
@storages = @config["storages"].flat_map do |definition|
|
134
|
+
case definition
|
135
|
+
when Hash
|
136
|
+
definition.map do |kind, config|
|
137
|
+
[kind, config]
|
138
|
+
end
|
139
|
+
when String
|
140
|
+
[[definition, {}]]
|
141
|
+
end
|
142
|
+
end.map do |kind, config|
|
143
|
+
@logger.info "Preparing... storage - #{kind}"
|
144
|
+
Akane::Storages.find(kind).new(
|
145
|
+
config: config,
|
146
|
+
logger: @config.logger
|
147
|
+
)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def prepare_recorder
|
152
|
+
@recorder = Akane::Recorder.new(
|
153
|
+
@storages,
|
154
|
+
timeout: @config["timeout"] || 20,
|
155
|
+
logger: @config.logger
|
156
|
+
)
|
157
|
+
end
|
132
158
|
end
|
133
159
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Akane
|
2
|
+
module Receivers
|
3
|
+
def self.find(name)
|
4
|
+
class_name = name.gsub(/(?:\A|_)(.)/) { $1.upcase }
|
5
|
+
|
6
|
+
retried = false
|
7
|
+
begin
|
8
|
+
return Akane::Receivers.const_get(class_name, false)
|
9
|
+
rescue NameError => e
|
10
|
+
raise e if retried
|
11
|
+
retried = true
|
12
|
+
require "akane/receivers/#{name}"
|
13
|
+
retry
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -4,6 +4,7 @@ module Akane
|
|
4
4
|
def initialize(consumer: raise(ArgumentError, 'missing consumer'),
|
5
5
|
account: raise(ArgumentError, 'missing account'),
|
6
6
|
logger: Logger.new($stdout),
|
7
|
+
name: nil,
|
7
8
|
config: {})
|
8
9
|
@consumer = consumer
|
9
10
|
@account = account
|
@@ -13,6 +14,10 @@ module Akane
|
|
13
14
|
@hooks = {}
|
14
15
|
end
|
15
16
|
|
17
|
+
def name
|
18
|
+
@name ||= @config['name'] || "#{cname}:#{@account[:name]}"
|
19
|
+
end
|
20
|
+
|
16
21
|
def start
|
17
22
|
raise NotImplementedError
|
18
23
|
end
|
@@ -37,6 +42,10 @@ module Akane
|
|
37
42
|
|
38
43
|
private
|
39
44
|
|
45
|
+
def cname
|
46
|
+
@cname = self.class.name.split(/::/).last
|
47
|
+
end
|
48
|
+
|
40
49
|
def invoke(kind, *args)
|
41
50
|
return unless @hooks[kind]
|
42
51
|
@hooks[kind].each { |hook| hook.call(*args) }
|
@@ -7,6 +7,26 @@ module Akane
|
|
7
7
|
def initialize(*)
|
8
8
|
super
|
9
9
|
@thread = nil
|
10
|
+
|
11
|
+
if @config["method"]
|
12
|
+
@stream_method = @config["method"].to_sym
|
13
|
+
else
|
14
|
+
@stream_method = :user
|
15
|
+
end
|
16
|
+
|
17
|
+
if @config["options"]
|
18
|
+
@stream_options = Hash[@config["options"].map do |k,v|
|
19
|
+
[k.to_sym, v]
|
20
|
+
end]
|
21
|
+
else
|
22
|
+
@stream_options = {}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def name
|
27
|
+
# For backward compatibility, user stream returns only account name if
|
28
|
+
# config.name not specified.
|
29
|
+
@name ||= @config['name'] || @account[:name]
|
10
30
|
end
|
11
31
|
|
12
32
|
def running?() !!(@thread && @thread.alive?) end
|
@@ -27,7 +47,7 @@ module Akane
|
|
27
47
|
|
28
48
|
@thread = Thread.new do
|
29
49
|
begin
|
30
|
-
stream.
|
50
|
+
stream.send(@stream_method, @stream_options) do |obj|
|
31
51
|
case obj
|
32
52
|
when Twitter::Tweet
|
33
53
|
invoke(:tweet, obj)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Akane
|
2
|
+
module Storages
|
3
|
+
def self.find(name)
|
4
|
+
class_name = name.gsub(/(?:\A|_)(.)/) { $1.upcase }
|
5
|
+
|
6
|
+
retried = false
|
7
|
+
begin
|
8
|
+
return Akane::Storages.const_get(class_name, false)
|
9
|
+
rescue NameError => e
|
10
|
+
raise e if retried
|
11
|
+
retried = true
|
12
|
+
require "akane/storages/#{name}"
|
13
|
+
retry
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/akane/version.rb
CHANGED
data/spec/manager_spec.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'akane/manager'
|
3
3
|
require 'akane/receivers/stream'
|
4
|
+
require 'akane/receivers/abstract_receiver'
|
4
5
|
require 'akane/storages/mock'
|
5
6
|
require 'akane/config'
|
6
7
|
|
@@ -35,7 +36,8 @@ describe Akane::Manager do
|
|
35
36
|
it "creates receivers" do
|
36
37
|
Akane::Receivers::Stream.should_receive(:new) \
|
37
38
|
.with(consumer: {token: 'consumer-token', secret: 'consumer-secret'},
|
38
|
-
account: {token: 'a-access-token', secret: 'a-access-secret'},
|
39
|
+
account: {token: 'a-access-token', secret: 'a-access-secret', name: 'a'},
|
40
|
+
config: {},
|
39
41
|
logger: config.logger) \
|
40
42
|
.and_return(double("a").as_null_object)
|
41
43
|
|
@@ -54,6 +56,58 @@ describe Akane::Manager do
|
|
54
56
|
|
55
57
|
subject.prepare
|
56
58
|
end
|
59
|
+
|
60
|
+
context "with config.accounts[].receivers" do
|
61
|
+
let(:conf_accounts) do
|
62
|
+
{
|
63
|
+
"a" => {
|
64
|
+
"token" => "a-access-token",
|
65
|
+
"secret" => "a-access-secret",
|
66
|
+
"receivers" => [
|
67
|
+
'foo',
|
68
|
+
{"bar" => {'hello' => 'hola',}},
|
69
|
+
],
|
70
|
+
},
|
71
|
+
"b" => {
|
72
|
+
"token" => "b-access-token",
|
73
|
+
"secret" => "b-access-secret",
|
74
|
+
},
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
let(:foo_receiver) { Class.new(Akane::Receivers::AbstractReceiver) {} }
|
79
|
+
let(:bar_receiver) { Class.new(Akane::Receivers::AbstractReceiver) {} }
|
80
|
+
|
81
|
+
before do
|
82
|
+
stub_const 'Akane::Receivers::Foo', foo_receiver
|
83
|
+
stub_const 'Akane::Receivers::Bar', bar_receiver
|
84
|
+
end
|
85
|
+
|
86
|
+
it "creates receivers" do
|
87
|
+
expect(foo_receiver).to receive(:new) \
|
88
|
+
.with(consumer: {token: 'consumer-token', secret: 'consumer-secret'},
|
89
|
+
account: {token: 'a-access-token', secret: 'a-access-secret', name: 'a'},
|
90
|
+
config: {},
|
91
|
+
logger: config.logger) \
|
92
|
+
.and_return(double("foo").as_null_object)
|
93
|
+
|
94
|
+
expect(bar_receiver).to receive(:new) \
|
95
|
+
.with(consumer: {token: 'consumer-token', secret: 'consumer-secret'},
|
96
|
+
account: {token: 'a-access-token', secret: 'a-access-secret', name: 'a'},
|
97
|
+
config: {'hello' => 'hola',},
|
98
|
+
logger: config.logger) \
|
99
|
+
.and_return(double("bar").as_null_object)
|
100
|
+
|
101
|
+
Akane::Receivers::Stream.should_receive(:new) \
|
102
|
+
.with(consumer: {token: 'consumer-token', secret: 'consumer-secret'},
|
103
|
+
account: {token: 'b-access-token', secret: 'b-access-secret', name: 'b'},
|
104
|
+
config: {},
|
105
|
+
logger: config.logger) \
|
106
|
+
.and_return(double("bstream").as_null_object)
|
107
|
+
|
108
|
+
subject.prepare
|
109
|
+
end
|
110
|
+
end
|
57
111
|
end
|
58
112
|
|
59
113
|
describe "#start" do
|
@@ -64,6 +118,7 @@ describe Akane::Manager do
|
|
64
118
|
Akane::Recorder.stub(new: recorder)
|
65
119
|
|
66
120
|
@on_event, @on_tweet, @on_delete, @on_message = nil
|
121
|
+
receiver.stub(name: 'a')
|
67
122
|
receiver.stub(:on_event) { |&block| @on_event = block }
|
68
123
|
receiver.stub(:on_tweet) { |&block| @on_tweet = block }
|
69
124
|
receiver.stub(:on_delete) { |&block| @on_delete = block }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: akane
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.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-
|
11
|
+
date: 2014-08-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: elasticsearch
|
@@ -143,9 +143,11 @@ files:
|
|
143
143
|
- lib/akane/cli.rb
|
144
144
|
- lib/akane/config.rb
|
145
145
|
- lib/akane/manager.rb
|
146
|
+
- lib/akane/receivers.rb
|
146
147
|
- lib/akane/receivers/abstract_receiver.rb
|
147
148
|
- lib/akane/receivers/stream.rb
|
148
149
|
- lib/akane/recorder.rb
|
150
|
+
- lib/akane/storages.rb
|
149
151
|
- lib/akane/storages/abstract_storage.rb
|
150
152
|
- lib/akane/storages/elasticsearch.rb
|
151
153
|
- lib/akane/storages/file.rb
|