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 +4 -4
- data/.gitignore +2 -0
- data/config.yml +20 -9
- data/exe/tweet_watch +5 -1
- data/lib/tweet_watch/account.rb +20 -0
- data/lib/tweet_watch/cli.rb +60 -30
- data/lib/tweet_watch/client.rb +13 -48
- data/lib/tweet_watch/config.rb +26 -21
- data/lib/tweet_watch/utils.rb +42 -0
- data/lib/tweet_watch/version.rb +1 -1
- data/lib/tweet_watch.rb +2 -1
- data/tweet_watch.gemspec +1 -0
- metadata +20 -5
- data/lib/tweet_watch/user.rb +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d74bc0d2d02588fbfac1ef6b5531997844e8e350
|
4
|
+
data.tar.gz: bddd89e90b54464df74c7d07b3c3a186f56affa6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ab9c6739f914f3d8b0d319953e7fb481c159da299bdd30616b8c359cc7489b8abbc97e02a2c3f67c3dd425b80630fdcfd18c39643f54375d82bd15ed769d5e7
|
7
|
+
data.tar.gz: facc27d954fc5773c5531777a4b5b74bdf1a761fada7a270401244a7f282a6b312662ea36c4c79a48a864b6faedd2dff17cb88e966c1c7119d298abcf71d4fb5
|
data/.gitignore
CHANGED
data/config.yml
CHANGED
@@ -1,15 +1,26 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
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:
|
8
|
-
access_token_secret:
|
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:
|
11
|
-
access_token_secret:
|
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
@@ -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
|
data/lib/tweet_watch/cli.rb
CHANGED
@@ -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
|
-
|
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
|
28
|
-
option :
|
29
|
-
|
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
|
-
|
32
|
-
|
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
|
-
|
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
|
39
|
-
|
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
|
46
|
-
option :
|
47
|
-
|
48
|
-
|
49
|
-
|
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
|
-
|
75
|
+
|
76
|
+
puts "Starting stream...".colorize(:light_cyan)
|
77
|
+
sc.user do |obj|
|
57
78
|
time = Time.now
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
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
|
|
data/lib/tweet_watch/client.rb
CHANGED
@@ -1,63 +1,28 @@
|
|
1
1
|
module TweetWatch
|
2
2
|
module Client
|
3
3
|
|
4
|
-
def
|
5
|
-
|
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 =
|
27
|
-
config.consumer_secret =
|
28
|
-
config.access_token =
|
29
|
-
config.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(
|
34
|
-
|
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 =
|
39
|
-
config.consumer_secret =
|
40
|
-
config.access_token =
|
41
|
-
config.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
|
data/lib/tweet_watch/config.rb
CHANGED
@@ -1,30 +1,29 @@
|
|
1
1
|
module TweetWatch
|
2
2
|
class Config
|
3
|
-
attr_accessor :
|
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
|
-
@
|
8
|
+
@accounts = []
|
10
9
|
@tweeters = []
|
11
10
|
@count = 50
|
12
11
|
@error_message = ""
|
13
12
|
end
|
14
13
|
|
15
|
-
def load_from_path(
|
16
|
-
|
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["
|
26
|
-
c["
|
27
|
-
self.
|
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
|
-
|
36
|
+
self
|
38
37
|
end
|
39
38
|
|
40
39
|
def valid?
|
41
40
|
@error_message = ""
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
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
|
-
|
49
|
-
|
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
|
data/lib/tweet_watch/version.rb
CHANGED
data/lib/tweet_watch.rb
CHANGED
data/tweet_watch.gemspec
CHANGED
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.
|
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-
|
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/
|
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:
|
141
|
+
version: 1.3.1
|
127
142
|
requirements: []
|
128
143
|
rubyforge_project:
|
129
144
|
rubygems_version: 2.5.1
|
data/lib/tweet_watch/user.rb
DELETED
@@ -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
|