tweet_watch 0.1.0 → 0.2.1.pre

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: 1cf0ec161d2977390ad7ea92acc576b99c868a76
4
- data.tar.gz: 92ab838aecde143611dc953925ff4ba0ce1d4183
3
+ metadata.gz: d74bc0d2d02588fbfac1ef6b5531997844e8e350
4
+ data.tar.gz: bddd89e90b54464df74c7d07b3c3a186f56affa6
5
5
  SHA512:
6
- metadata.gz: 1677ab58dbb77b18a7479cbdbef2c6ce6e4b2ff9fe25147f04385421fe6642bea09aaac5e5128bdeb7b47cdedb81645de052468a09230327e12ab64e0f05e5c7
7
- data.tar.gz: 50c0d295f4980e36ad4199c96522dfd040bcef9acba2d03fe52fd55d66a94c0fa04cb5f9ac2b95475ab65739a4df254ed96fe41d769ccfb622ec7dc30b1ca069
6
+ metadata.gz: 4ab9c6739f914f3d8b0d319953e7fb481c159da299bdd30616b8c359cc7489b8abbc97e02a2c3f67c3dd425b80630fdcfd18c39643f54375d82bd15ed769d5e7
7
+ data.tar.gz: facc27d954fc5773c5531777a4b5b74bdf1a761fada7a270401244a7f282a6b312662ea36c4c79a48a864b6faedd2dff17cb88e966c1c7119d298abcf71d4fb5
data/.gitignore CHANGED
@@ -7,3 +7,5 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ *.csv
11
+ config-real.yml
data/config.yml CHANGED
@@ -1,15 +1,26 @@
1
- credentials:
2
- consumer_key: jKgFRB9dossgVmyRB1P4Wm5J7CN
3
- consumer_secret: oMswt4MMBJxrta3fQ27JkmbuLfHMvkZKrlSpIcT8AdmubJcSjlpT
4
-
5
- users:
1
+ # Configure all the accounts you want to track.
2
+ # You can go to dev https://apps.twitter.com/ to
3
+ # create an app. This will get you credentials.
4
+ # You then have to go into the app to generate access
5
+ # tokens.
6
+ #
7
+ # Add multiple accounts here and pass -u command to
8
+ # select the tracking user
9
+ accounts:
6
10
  - screen_name: ajoabraham
7
- access_token: 17609705-Fd9WcmbEEFFftfasEwxxFvF1FOgtZ1S4E1YNnj0XcPyc
8
- access_token_secret: VIge9jyWlz9k9qe0jVaaK3gHoSwqMlgsi0cRZwZEYpWXu6G
11
+ access_token: YOUR_ACCESS_TOKEN
12
+ access_token_secret: YOUR_ACCESS_TOKEN_SECRET
13
+ consumer_key: YOUR_CONSUMER_KEY
14
+ consumer_secret: YOUR_CONSUMER_SECRET
9
15
  - screen_name: lodr_io
10
- access_token: 797120884146311169asdf-OggIoXEHI1SqnTDuKmp87HSd3O22bw4
11
- access_token_secret: Zsl1Pbl7snrmjwfdsv7q2cZpVTAeYCjzDlu3C4k2eEtWMxh1
16
+ access_token: YOUR_ACCESS_TOKEN
17
+ access_token_secret: YOUR_ACCESS_TOKEN_SECRET
18
+ consumer_key: YOUR_CONSUMER_KEY
19
+ consumer_secret: YOUR_CONSUMER_SECRET
12
20
 
21
+ # When using the watch command you can choose
22
+ # tweets from cerntail users to be recorded as CSV
23
+ # The following tweeters will be recorded
13
24
  tweeters:
14
25
  - scottadamsays
15
26
  - jaketapper
data/exe/tweet_watch CHANGED
@@ -2,4 +2,8 @@
2
2
 
3
3
  require 'tweet_watch'
4
4
 
5
- TweetWatch::CLI.start(ARGV)
5
+ begin
6
+ TweetWatch::CLI.start(ARGV)
7
+ rescue Interrupt
8
+ puts "\nExiting..."
9
+ end
@@ -0,0 +1,20 @@
1
+ module TweetWatch
2
+
3
+ class Account
4
+ attr_accessor :screen_name, :access_token, :access_token_secret,
5
+ :consumer_key, :consumer_secret
6
+
7
+ def initialize(screen_name, consumer_key,
8
+ consumer_secret, access_token,
9
+ access_token_secret)
10
+
11
+ @screen_name = screen_name
12
+ @consumer_key = consumer_key
13
+ @consumer_secret = consumer_secret
14
+ @access_token = access_token
15
+ @access_token_secret = access_token_secret
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -1,19 +1,22 @@
1
+ require 'colorize'
2
+
1
3
  module TweetWatch
2
-
3
- def self.print_tweet(tw)
4
- puts "\n---"
5
- puts "from: @#{tw.user.screen_name}"
6
- puts tw.text
7
- puts "created #{Time.now - tw.created_at} seconds ago \n"
8
- end
9
-
4
+
10
5
  class CLI < Thor
11
6
  include Client
7
+ include Utils
8
+
9
+ class_option :screen_name, aliases: "-u",
10
+ desc: "The screename of the account. If not included, will select the first account from the config file."
11
+ class_option :config_file, aliases: "-c", required: true,
12
+ desc: "Yaml config file path"
13
+
12
14
 
13
15
  desc "limits", "Print out the current rate limits"
14
16
  def limits
17
+ load_config(options)
15
18
  resp = Twitter::REST::Request.new(client, 'get', "/1.1/application/rate_limit_status.json" ).perform
16
- puts resp.inspect
19
+
17
20
  current_time = Time.now.to_i
18
21
  template = " %-40s %5d remaining, resets in %3d seconds\n"
19
22
  resp.body[:resources].each do |category,resources|
@@ -24,46 +27,73 @@ module TweetWatch
24
27
  end
25
28
  end
26
29
 
27
- desc "timeline", "Prints out the first users timeline. 20 tweets."
28
- option :s, desc: "will stream the first users timeline"
29
- option :u, desc: "the screename of the user to authenticate access for"
30
+ desc "timeline", "Prints out an accounts timeline"
31
+ option :stream, aliases: "-s",
32
+ desc: "Will stream a tweets as they come in instead of printing the latest timeline."
33
+ option :count, aliases: "-c", default: 50, type: :numeric,
34
+ desc: "Number of past tweets to print out. Max history is 200"
30
35
  def timeline
31
- if options[:s]
32
- streaming_client(options[:u]).user do |obj|
36
+ load_config(options)
37
+
38
+ if options[:stream]
39
+ sc = streaming_client(options)
40
+ puts "Starting stream...".colorize(:light_cyan)
41
+ sc.user do |obj|
33
42
  if obj.class == Twitter::Tweet
34
- TweetWatch.print_tweet obj
43
+ print_tweet obj
44
+ elsif obj.class == Twitter::DirectMessage
45
+ print_dm obj
35
46
  end
36
47
  end
37
48
  else
38
- client(options[:u]).home_timeline.each do |tw|
39
- TweetWatch.print_tweet(tw)
49
+ client(options).home_timeline.each do |tw|
50
+ print_tweet(tw)
40
51
  end
41
52
  end
42
53
 
43
54
  end
44
55
 
45
- desc "watch", "Watches a stream to track tweets from specific tweeters"
46
- option :o, desc: "output file - will append if files exists", default: "tweet_watch.csv"
47
- option :u, desc: "the screename of the user to authenticate access for"
48
- def watch
49
- file = File.open(options[:o], "a+")
56
+ desc "watch", "Watches a stream and records tweets. Filter which tweets are recorded by providing a tweeters list."
57
+ option :output, aliases: "-o",
58
+ desc: "output file - will append if files exists", default: "tweet_watch.csv"
59
+ option :tweeters, aliases: "-t", type: :array,
60
+ desc: "list of tweeters to filter recorded tweets by"
61
+ option :tweeters_only, aliases: "-f",
62
+ desc: "only prints to screen provided list of tweeters"
63
+ def watch
64
+ load_config(options)
65
+
66
+ sc = streaming_client(options)
67
+ file = File.open(options[:output], "a+")
50
68
  tw_config = TweetWatch.config
51
69
 
70
+ tweeters = options[:tweeters] ? options[:tweeters] : tw_config.tweeters
71
+
52
72
  unless file.size > 0
53
73
  file.puts "timelined_at, tweet_id, screen_name, text, tweet_created_at, is_reply, is_quote"
54
74
  end
55
-
56
- streaming_client(options[:u]).user do |obj|
75
+
76
+ puts "Starting stream...".colorize(:light_cyan)
77
+ sc.user do |obj|
57
78
  time = Time.now
58
- if obj.class == Twitter::Tweet
59
- TweetWatch.print_tweet obj
60
-
61
- if tw_config.tweeters.include?(obj.user.screen_name)
62
- puts "recording tweet data"
63
- file.puts "\"#{time.utc}\", \"#{obj.id}\", \"#{obj.user.screen_name}\", \"#{obj.text}\", \"#{obj.created_at.getutc}\",\"#{obj.user.screen_name}\", \"#{obj.reply?}\", \"#{obj.quote?}\""
79
+
80
+ if obj.class == Twitter::Tweet
81
+ if options[:tweeters_only].nil? || (options[:tweeters_only] && tweeters.include?(obj.account.screen_name))
82
+ print_tweet obj
64
83
  end
65
84
 
85
+ if tw_config.tweeters.empty? || tweeters.include?(obj.user.screen_name)
86
+ puts "recording tweet data".colorize(:red)
87
+ file.puts "#{time.utc}, #{obj.id}, \"#{escape_str(obj.user.screen_name)}\", \"#{escape_str(obj.text)}\", #{obj.created_at.getutc},\"#{escape_str(obj.user.screen_name)}\", #{obj.reply?}, #{obj.quote?}"
88
+ end
89
+ elsif obj.class == Twitter::DirectMessage
90
+ print_dm obj
91
+ elsif obj.class == Twitter::Streaming::StallWarning
92
+ warn "Falling behind!"
93
+ else
94
+ puts "untracked tweet obj #{obj.class}".colorize(color: :black, background: :light_white)
66
95
  end
96
+
67
97
  end
68
98
  end
69
99
 
@@ -1,63 +1,28 @@
1
1
  module TweetWatch
2
2
  module Client
3
3
 
4
- def config
5
- tw_config = TweetWatch::config
6
-
7
- unless tw_config.valid?
8
- # try to load a local config.yml
9
- puts "trying to load config from current directory..."
10
- path = 'config.yml'
11
- if File.exists?(path)
12
- tw_config.load_from_path(path)
13
- else
14
- raise ArgumentError.new("Invalid configuration: " + tw_config.error_message)
15
- end
16
- end
17
-
18
- tw_config
19
- end
20
-
21
- def client(screen_name = nil)
22
- tw_config = config
23
- user = get_user(screen_name)
4
+ def client(options)
5
+ account = TweetWatch.config.get_account(options[:screen_name])
24
6
 
25
7
  @client ||= Twitter::REST::Client.new do |config|
26
- config.consumer_key = tw_config.consumer_key
27
- config.consumer_secret = tw_config.consumer_secret
28
- config.access_token = user.access_token
29
- config.access_token_secret = user.access_token_secret
8
+ config.consumer_key = account.consumer_key
9
+ config.consumer_secret = account.consumer_secret
10
+ config.access_token = account.access_token
11
+ config.access_token_secret = account.access_token_secret
30
12
  end
31
13
  end
32
14
 
33
- def streaming_client(screen_name = nil)
34
- tw_config = config
35
- user = get_user(screen_name)
15
+ def streaming_client(options)
16
+ account = TweetWatch.config.get_account(options[:screen_name])
36
17
 
37
18
  @client ||= Twitter::Streaming::Client.new do |config|
38
- config.consumer_key = tw_config.consumer_key
39
- config.consumer_secret = tw_config.consumer_secret
40
- config.access_token = user.access_token
41
- config.access_token_secret = user.access_token_secret
19
+ config.consumer_key = account.consumer_key
20
+ config.consumer_secret = account.consumer_secret
21
+ config.access_token = account.access_token
22
+ config.access_token_secret = account.access_token_secret
42
23
  end
43
24
  end
44
-
45
- def load_config(path)
46
- TweetWatch::config.load_from_path(path)
47
- end
48
-
49
- def get_user(screen_name)
50
- user = config.users.first
51
-
52
- unless screen_name.nil?
53
- res = config.users.select { |u| u.screen_name.strip() == screen_name.strip() }
54
- user = res.first if res.size > 0
55
- end
56
-
57
- return user
58
-
59
- end
60
-
25
+
61
26
  end
62
27
 
63
28
  end
@@ -1,30 +1,29 @@
1
1
  module TweetWatch
2
2
  class Config
3
- attr_accessor :consumer_key, :consumer_secret, :count,
4
- :users, :tweeters
3
+ attr_accessor :count, :accounts, :tweeters, :path
5
4
 
6
5
  attr_reader :error_message
7
6
 
8
7
  def initialize
9
- @users = []
8
+ @accounts = []
10
9
  @tweeters = []
11
10
  @count = 50
12
11
  @error_message = ""
13
12
  end
14
13
 
15
- def load_from_path(config_path)
16
- c = YAML.load_file(config_path)
17
-
18
- unless c["credentials"].nil?
19
- cc = c["credentials"]
20
- self.consumer_key = cc["consumer_key"] unless cc["consumer_key"].nil?
21
- self.consumer_secret = cc["consumer_secret"] unless cc["consumer_secret"].nil?
22
- self.count = cc["count"] unless cc["count"].nil?
14
+ def load_from_path(path)
15
+ unless File.exists?(path)
16
+ raise ArgumentError.new("The provided config file could not be located: #{path}")
23
17
  end
18
+
19
+ @path = path
20
+ c = YAML.load_file(@path)
24
21
 
25
- unless c["users"].nil?
26
- c["users"].each do |f|
27
- self.users << User.new(f["screen_name"], f["access_token"], f["access_token_secret"])
22
+ unless c["accounts"].nil?
23
+ c["accounts"].each do |f|
24
+ self.accounts << Account.new(f["screen_name"],
25
+ f["consumer_key"], f["consumer_secret"],
26
+ f["access_token"], f["access_token_secret"])
28
27
  end
29
28
  end
30
29
 
@@ -34,19 +33,25 @@ module TweetWatch
34
33
  end
35
34
  end
36
35
 
37
- return c
36
+ self
38
37
  end
39
38
 
40
39
  def valid?
41
40
  @error_message = ""
42
- [:consumer_key, :consumer_secret].each do |m|
43
- if self.send(m).nil?
44
- @error_message += "#{m.to_s.capitalize} is missing \n"
45
- end
41
+ @error_message += "There should be at least one account" if accounts.size ==0
42
+ @error_message.strip().length == 0
43
+ end
44
+
45
+ def get_account(screen_name = nil)
46
+ account = @accounts.first
47
+
48
+ unless screen_name.nil?
49
+ res = @accounts.select { |u| u.screen_name.strip() == screen_name.strip() }
50
+ account = res.first if res.size > 0
46
51
  end
47
52
 
48
- @error_message += "There should be at least one user" if users.size ==0
49
- @error_message.strip().length == 0
53
+ return account
54
+
50
55
  end
51
56
 
52
57
  end
@@ -0,0 +1,42 @@
1
+ module TweetWatch
2
+
3
+ module Utils
4
+ def load_config(options)
5
+ if options[:config_file]
6
+ TweetWatch.config.load_from_path(options[:config_file])
7
+ else
8
+ TweetWatch.config.load_from_path("config.yml")
9
+ end
10
+ end
11
+
12
+ def escape_str(str)
13
+ str2 = str.gsub('"', '\"')
14
+ str2.gsub(/\\(.)/) do |s|
15
+ case $1
16
+ when "n"
17
+ "\n"
18
+ when "t"
19
+ "\t"
20
+ else
21
+ $1
22
+ end
23
+ end
24
+ end
25
+
26
+ def print_tweet(tw)
27
+ puts "\n---".colorize(:light_red)
28
+ puts "#{tw.user.name} (@#{tw.user.screen_name})".colorize(:light_yellow) + " FW: #{tw.user.followers_count}".colorize(:green)
29
+ puts tw.text.colorize(:light_cyan)
30
+ puts "#{(Time.now - tw.created_at).round(2)} secs ago".colorize(:light_red) +" RT: #{tw.retweet_count} LK: #{tw.favorite_count}\n".colorize(:green)
31
+ end
32
+
33
+ def print_dm(tw)
34
+ puts "\nDM --- DM".colorize(color: :light_white, background: :red)
35
+ puts "#{tw.sender.name} (@#{tw.sender.screen_name})".colorize(color: :light_yellow, background: :red) + " FW: #{tw.sender.followers_count}".colorize(color: :green, background: :red)
36
+ puts tw.text.colorize(color: :white, background: :red)
37
+ puts "#{(Time.now - tw.created_at).round(2)} secs ago".colorize(color: :yellow, background: :red)
38
+ end
39
+
40
+ end
41
+
42
+ end
@@ -1,3 +1,3 @@
1
1
  module TweetWatch
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.1.pre"
3
3
  end
data/lib/tweet_watch.rb CHANGED
@@ -4,8 +4,9 @@ require 'thor'
4
4
 
5
5
  require "tweet_watch/version"
6
6
  require "tweet_watch/config"
7
- require "tweet_watch/user"
7
+ require "tweet_watch/account"
8
8
  require "tweet_watch/client"
9
+ require "tweet_watch/utils"
9
10
  require "tweet_watch/cli"
10
11
 
11
12
 
data/tweet_watch.gemspec CHANGED
@@ -35,4 +35,5 @@ Gem::Specification.new do |spec|
35
35
  spec.add_development_dependency "minitest", "~> 5.0"
36
36
  spec.add_dependency "twitter", "~> 6.1"
37
37
  spec.add_dependency 'thor'
38
+ spec.add_dependency 'colorize'
38
39
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tweet_watch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.1.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ajo Abraham
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-03-17 00:00:00.000000000 Z
11
+ date: 2017-03-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: colorize
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  description: The generated files can be loaded into a database to study twitter behaviour.
84
98
  email:
85
99
  - abraham.ajo@gmail.com
@@ -100,10 +114,11 @@ files:
100
114
  - config.yml
101
115
  - exe/tweet_watch
102
116
  - lib/tweet_watch.rb
117
+ - lib/tweet_watch/account.rb
103
118
  - lib/tweet_watch/cli.rb
104
119
  - lib/tweet_watch/client.rb
105
120
  - lib/tweet_watch/config.rb
106
- - lib/tweet_watch/user.rb
121
+ - lib/tweet_watch/utils.rb
107
122
  - lib/tweet_watch/version.rb
108
123
  - tweet_watch.gemspec
109
124
  homepage: http://rubygems.org/gems/tweet_watch
@@ -121,9 +136,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
121
136
  version: '0'
122
137
  required_rubygems_version: !ruby/object:Gem::Requirement
123
138
  requirements:
124
- - - ">="
139
+ - - ">"
125
140
  - !ruby/object:Gem::Version
126
- version: '0'
141
+ version: 1.3.1
127
142
  requirements: []
128
143
  rubyforge_project:
129
144
  rubygems_version: 2.5.1
@@ -1,14 +0,0 @@
1
- module TweetWatch
2
-
3
- class User
4
- attr_accessor :screen_name, :access_token, :access_token_secret
5
-
6
- def initialize(screen_name, token, secret)
7
- @screen_name = screen_name
8
- @access_token = token
9
- @access_token_secret = secret
10
- end
11
-
12
- end
13
-
14
- end