fluent-plugin-twitter 0.1.1 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -2,7 +2,7 @@ fluent-plugin-twitter
2
2
  =====================
3
3
 
4
4
  ## Component
5
- Fluentd Input/Output plugin. You can create your own "Twitter Bot" with fluentd messaging system.
5
+ Fluentd Input/Output plugin to process tweets with Twitter Streaming API.
6
6
 
7
7
  ## Installation
8
8
 
@@ -29,8 +29,9 @@ gem install fluent-plugin-twitter
29
29
  oauth_token_secret YOUR_OAUTH_TOKEN_SECRET # Required
30
30
  tag input.twitter.sampling # Required
31
31
  timeline sampling # Required (sampling or userstream)
32
- keyword Ruby,Python # Optional (userstream not supported yet)
32
+ keyword Ruby,Python # Optional (only work with `timeline` is sampling)
33
33
  lang ja,en # Optional
34
+ output_format nest # Optional (nest or flat or simple[default])
34
35
  </source>
35
36
 
36
37
  <match input.twitter.sampling>
@@ -71,6 +72,9 @@ $ curl http://localhost:8888/notify.twitter -F 'json={"message":"foo"}'
71
72
  ### Twitter OAuth Guide
72
73
  http://pocketstudio.jp/log3/2012/02/12/how_to_get_twitter_apikey_and_token/
73
74
 
75
+ ### Quick Tour to count a tweet with fluent-plugin-twitter and fluent-plugin-datacounter
76
+ http://qiita.com/items/fe4258b394190f23fece
77
+
74
78
  ## TODO
75
79
  patches welcome!
76
80
 
@@ -3,11 +3,11 @@ $:.push File.expand_path("../lib", __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "fluent-plugin-twitter"
6
- s.version = "0.1.1"
6
+ s.version = "0.2.1"
7
7
  s.authors = ["Kentaro Yoshida"]
8
8
  s.email = ["y.ken.studio@gmail.com"]
9
9
  s.homepage = "https://github.com/y-ken/fluent-plugin-twitter"
10
- s.summary = %q{Fluentd Input/Output plugin. You can create your own "Twitter Bot" with fluentd messaging system.}
10
+ s.summary = %q{Fluentd Input/Output plugin to process tweets with Twitter Streaming API.}
11
11
 
12
12
  s.files = `git ls-files`.split("\n")
13
13
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -1,6 +1,7 @@
1
1
  module Fluent
2
2
  class TwitterInput < Fluent::Input
3
3
  TIMELINE_TYPE = %w(userstream sampling)
4
+ OUTPUT_FORMAT_TYPE = %w(nest flat simple)
4
5
  Plugin.register_input('twitter', self)
5
6
 
6
7
  config_param :consumer_key, :string
@@ -10,7 +11,9 @@ module Fluent
10
11
  config_param :tag, :string
11
12
  config_param :timeline, :string
12
13
  config_param :keyword, :string, :default => nil
13
- config_param :lang, :string, :default => ''
14
+ config_param :lang, :string, :default => nil
15
+ config_param :output_format, :string, :default => 'simple'
16
+ config_param :flatten_separator, :string, :default => '_'
14
17
 
15
18
  def initialize
16
19
  super
@@ -19,7 +22,14 @@ module Fluent
19
22
 
20
23
  def configure(conf)
21
24
  super
22
- raise Fluent::ConfigError, "timeline value undefined #{@timeline}" if !TIMELINE_TYPE.include?(@timeline)
25
+
26
+ if !TIMELINE_TYPE.include?(@timeline)
27
+ raise Fluent::ConfigError, "timeline value undefined #{@timeline}"
28
+ end
29
+ if !OUTPUT_FORMAT_TYPE.include?(@output_format)
30
+ raise Fluent::ConfigError, "output_format value undefined #{@output_format}"
31
+ end
32
+
23
33
  TweetStream.configure do |config|
24
34
  config.consumer_key = @consumer_key
25
35
  config.consumer_secret = @consumer_secret
@@ -31,6 +41,9 @@ module Fluent
31
41
 
32
42
  def start
33
43
  @thread = Thread.new(&method(:run))
44
+ @any = Proc.new do |hash|
45
+ get_message(hash) if is_message?(hash)
46
+ end
34
47
  end
35
48
 
36
49
  def shutdown
@@ -38,57 +51,69 @@ module Fluent
38
51
  end
39
52
 
40
53
  def run
54
+ client = get_twitter_connection
41
55
  if @timeline == 'sampling' && @keyword
42
- start_twitter_track
56
+ client.track(@keyword)
43
57
  elsif @timeline == 'sampling' && @keyword.nil?
44
- start_twitter_sample
58
+ client.sample
45
59
  elsif @timeline == 'userstream'
46
- start_twitter_userstream
60
+ client.userstream
61
+ #elsif @timeline == 'follow'
62
+ # client.follow(@follow_ids)
47
63
  end
48
64
  end
49
65
 
50
- def start_twitter_track
51
- $log.info "starting twitter keyword tracking. tag:#{@tag} lang:#{@lang} keyword:#{@keyword}"
66
+ def get_twitter_connection
67
+ notice = "twitter: starting Twitter Streaming API for #{@timeline}."
68
+ notice << " tag:#{@tag}"
69
+ notice << " lang:#{@lang}" unless @lang.nil?
70
+ notice << " keyword:#{@keyword}" unless @keyword.nil?
71
+ $log.info notice
52
72
  client = TweetStream::Client.new
53
- client.track(@keyword) do |status|
54
- next unless status.text
55
- next unless @lang.include?(status.user.lang)
56
- get_message(status)
73
+ client.on_anything(&@any)
74
+ client.on_error do |message|
75
+ $log.info "twitter: unexpected error has occured. #{message}"
57
76
  end
77
+ return client
58
78
  end
59
79
 
60
- def start_twitter_sample
61
- $log.info "starting twitter sampled streaming. tag:#{@tag} lang:#{@lang}"
62
- client = TweetStream::Client.new
63
- client.sample do |status|
64
- next unless status.text
65
- next unless @lang.include?(status.user.lang)
66
- get_message(status)
67
- end
80
+ def is_message?(status)
81
+ return false if !status.include?(:text)
82
+ return false if !status.include?(:user)
83
+ return false if (!@lang.nil? && @lang != '') && !@lang.include?(status[:user][:lang])
84
+ return true
68
85
  end
69
86
 
70
- def start_twitter_userstream
71
- $log.info "starting twitter userstream tracking. tag:#{@tag} lang:#{@lang}"
72
- client = TweetStream::Client.new
73
- client.userstream do |status|
74
- next unless status.text
75
- next unless @lang.include?(status.user.lang)
76
- get_message(status)
87
+ def get_message(status)
88
+ case @output_format
89
+ when 'nest'
90
+ record = status.inject({}){|f,(k,v)| f[k.to_s] = v; f}
91
+ when 'flat'
92
+ record = hash_flatten(status)
93
+ when 'simple'
94
+ record = Hash.new
95
+ record.store('message', status[:text])
96
+ record.store('geo', status[:geo])
97
+ record.store('place', status[:place])
98
+ record.store('created_at', status[:place])
99
+ record.store('user_name', status[:user][:name])
100
+ record.store('user_screen_name', status[:user][:screen_name])
101
+ record.store('user_profile_image_url', status[:user][:profile_image_url])
102
+ record.store('user_time_zone', status[:user][:time_zone])
103
+ record.store('user_lang', status[:user][:lang])
77
104
  end
105
+ Engine.emit(@tag, Engine.now, record)
78
106
  end
79
107
 
80
- def get_message(status)
81
- record = Hash.new
82
- record.store('message', status.text)
83
- record.store('geo', status.geo)
84
- record.store('place', status.place)
85
- record.store('created_at', status.created_at)
86
- record.store('user_name', status.user.name)
87
- record.store('user_screen_name', status.user.screen_name)
88
- record.store('user_profile_image_url', status.user.profile_image_url)
89
- record.store('user_time_zone', status.user.time_zone)
90
- record.store('user_lang', status.user.lang)
91
- Engine.emit(@tag, Engine.now, record)
108
+ def hash_flatten(record, prefix = nil)
109
+ record.inject({}) do |d, (k, v)|
110
+ k = prefix.to_s + k.to_s
111
+ if v.is_a?(Hash)
112
+ d.merge(hash_flatten(v, k + @flatten_separator))
113
+ else
114
+ d.merge(k => v)
115
+ end
116
+ end
92
117
  end
93
118
  end
94
119
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-twitter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-14 00:00:00.000000000 Z
12
+ date: 2013-03-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fluentd
16
- requirement: &11259400 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *11259400
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: fluentd
27
- requirement: &11258160 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,10 +37,15 @@ dependencies:
32
37
  version: '0'
33
38
  type: :runtime
34
39
  prerelease: false
35
- version_requirements: *11258160
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: twitter
38
- requirement: &11257360 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
51
  - - ! '>='
@@ -43,10 +53,15 @@ dependencies:
43
53
  version: '0'
44
54
  type: :runtime
45
55
  prerelease: false
46
- version_requirements: *11257360
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: tweetstream
49
- requirement: &11283100 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
67
  - - ! '>='
@@ -54,7 +69,12 @@ dependencies:
54
69
  version: '0'
55
70
  type: :runtime
56
71
  prerelease: false
57
- version_requirements: *11283100
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
58
78
  description:
59
79
  email:
60
80
  - y.ken.studio@gmail.com
@@ -93,11 +113,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
93
113
  version: '0'
94
114
  requirements: []
95
115
  rubyforge_project:
96
- rubygems_version: 1.8.11
116
+ rubygems_version: 1.8.23
97
117
  signing_key:
98
118
  specification_version: 3
99
- summary: Fluentd Input/Output plugin. You can create your own "Twitter Bot" with fluentd
100
- messaging system.
119
+ summary: Fluentd Input/Output plugin to process tweets with Twitter Streaming API.
101
120
  test_files:
102
121
  - test/helper.rb
103
122
  - test/plugin/test_in_twitter.rb