twexicon 0.1.6
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 +7 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/bin/twexicon +5 -0
- data/config/environment.rb +8 -0
- data/lib/twexicon.rb +1 -0
- data/lib/twexicon/analyzer.rb +184 -0
- data/lib/twexicon/cli.rb +25 -0
- data/lib/twexicon/scraper.rb +27 -0
- data/lib/twexicon/validator.rb +40 -0
- data/lib/twexicon/version.rb +3 -0
- metadata +117 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a1cd602f292631f449f3fe0f20536abbdf98ad4a
|
4
|
+
data.tar.gz: b0a6f7d8c6635cd17ec42754875761ee977b1388
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 392e64484aace879ae529f9f54c44e8e8de403ed5126bc2b182f224d556667dd2b2b4760d0c0a10be21c92fd3cd82c383f072e10613646aeea4c2add05226e26
|
7
|
+
data.tar.gz: fe9d1014c544a9712f97b0bcbf0b18a6758d9763ff628e45a02edef0371590424130d76d344728aeda0779361d8b07367bc63e1f2c0c26aef626448a4b6b4e65
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "twexicon"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/bin/twexicon
ADDED
data/lib/twexicon.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require_relative '../config/environment'
|
@@ -0,0 +1,184 @@
|
|
1
|
+
class Twexicon::Analyzer
|
2
|
+
attr_reader :tweets, :username, :input, :int
|
3
|
+
|
4
|
+
def initialize(username, tweets)
|
5
|
+
@username = username
|
6
|
+
@tweets = tweets
|
7
|
+
puts "\nIndexed the #{tweets.size} most recent tweet(s) for @#{username}."
|
8
|
+
run
|
9
|
+
end
|
10
|
+
|
11
|
+
def run
|
12
|
+
quit = false
|
13
|
+
until quit
|
14
|
+
@input = nil
|
15
|
+
@int = ""
|
16
|
+
puts "What would you like to do next? For options, type 'help'."
|
17
|
+
until is_valid?
|
18
|
+
@input = gets.strip.gsub(/\W/, "").downcase
|
19
|
+
end
|
20
|
+
case input
|
21
|
+
when "help", "h"
|
22
|
+
puts "\nTo retrieve one of @#{username}'s #{tweets.size} tweet(s), type 'GET'."
|
23
|
+
puts "To view @#{username}'s ten favorite words, type 'WORDS'."
|
24
|
+
puts "For @#{username}'s favorite things to scream about, type 'SHOUTS'."
|
25
|
+
puts "To see the #hashtags that consume @#{username}'s thoughts, type 'HASHTAGS'."
|
26
|
+
puts "For some Twitter handles that @#{username} has tweeted at, type 'USERNAMES'."
|
27
|
+
puts "To see links for embedded pictures and/or videos, type 'PIX'."
|
28
|
+
puts "To view any other links @#{username} deemed worthy of sharing, type 'LINKS'."
|
29
|
+
puts "For some numbers that @#{username} mentioned, type 'NUMBERS'."
|
30
|
+
puts "To see which short acronyms @#{username} is fond of, type 'ACRONYMS'."
|
31
|
+
puts "To look up a different Twitter handle or to exit the program, type 'EXIT'."
|
32
|
+
puts "Short commands, in order: 'g', 'w', 's', 'ht', 'u', 'p', 'l', 'n', 'a', 'e', and 'h' for 'help'."
|
33
|
+
when "get", "g" then get_tweet
|
34
|
+
when "words", "w" then get_words
|
35
|
+
when "shouts", "s" then get_shouts
|
36
|
+
when "pix", "p" then get_pix
|
37
|
+
when "links", "l" then get_links
|
38
|
+
when "numbers", "n" then get_numbers
|
39
|
+
when "acronyms", "a" then get_acronyms
|
40
|
+
when "hashtags", "ht" then get_hashtags
|
41
|
+
when "usernames", "handles", "u" then get_usernames
|
42
|
+
when "exit", "e" then quit = true
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def is_valid?
|
48
|
+
if input =~ /(^help$|^h$|^get$|^g$|^exit$|^e$|^words$|^w$|^shouts$|^s$|^pix$|^p$|^links$|^l$|^numbers$|^n$|^acronyms$|^a$|^hashtags$|^ht$|^usernames$|^handles$|^u$)/
|
49
|
+
true
|
50
|
+
elsif input == nil
|
51
|
+
false
|
52
|
+
else
|
53
|
+
puts "Hm, I didn't recognize that. Please make a valid selection."
|
54
|
+
puts "To display all options, type 'help'."
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def get_tweet
|
59
|
+
if tweets.size == 1
|
60
|
+
puts "\n@#{username}'s only tweet is: #{tweets[int].keys[1]}"
|
61
|
+
else
|
62
|
+
puts "\nWhich tweet would you like to view?"
|
63
|
+
int = ""
|
64
|
+
until int =~ /^\d+$/ && int.to_i >= 1 && int.to_i <= tweets.size
|
65
|
+
puts "Please specify a number between 1 and #{tweets.size}."
|
66
|
+
int = gets.strip.gsub(/\D/, "")
|
67
|
+
end
|
68
|
+
puts "\n@#{username} said: #{tweets[int.to_i].keys[0]}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# 38 words from https://en.wikipedia.org/wiki/Most_common_words_in_English –– Left out some common yet still interesting ones (People, Good, Think, Work, First, One, Two, Want, New, Give, Know)
|
73
|
+
COMMON_WORDS = ["A", "About", "An", "And", "Are", "As", "At", "Be", "Been", "But", "By", "For", "From", "Get", "Had", "Has", "Have", "In", "Into", "Is", "It", "It's", "Its", "Just", "Not", "Of", "On", "Or", "Say", "So", "Some", "That", "The", "There", "These", "This", "Those", "To", "Up", "With", "I", "My", "Your", "They", "He", "You", "Do", "His", "We", "Her", "She", "Will", "All", "Would", "Their", "What", "Out", "If", "Who", "Which", "Go", "Me", "When", "Make", "Can", "Like", "Time", "No", "Him", "Take", "Year", "Could", "Them", "See", "Other", "Than", "Then", "Now", "Look", "Only", "Come", "Over", "Also", "Back", "After", "Use", "How", "Our", "Well", "Way", "Even", "Because", "Any", "Day", "Most", "Us",
|
74
|
+
# other additions
|
75
|
+
"Wouldn't", "Couldn't", "Shouldn't", "Mustn't", "Would've", "Could've", "Should've", "Must've", "Hadn't", "Wasn't", "Weren't", "Ain't", "Aint", "Here", "Seem", "Seems", "That's", "Took", "Much", "More", "You're", "We're", "We've", "I've", "I'm",
|
76
|
+
# contraction endings until I fix the parsing error
|
77
|
+
"Re", "Ll", "Ve",
|
78
|
+
# Letters until I fix the contraction parsing error
|
79
|
+
"B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
|
80
|
+
|
81
|
+
def get_words
|
82
|
+
words = {}
|
83
|
+
word_array = []
|
84
|
+
tweets.each_value do |v| # Count up instances of each word
|
85
|
+
v.values[0][:words].each do |w|
|
86
|
+
word = w.gsub(/[^\'\w]/, "").capitalize
|
87
|
+
if words.has_key?(word) && !COMMON_WORDS.include?(word)
|
88
|
+
words[word] += 1
|
89
|
+
else
|
90
|
+
words[word] = 1
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
words.each do |w, n| # Create strings for the words that occur >1 times
|
95
|
+
case n
|
96
|
+
when 1..9 then word_array << "0#{n}x #{w}"
|
97
|
+
when 10..99 then word_array << "#{n}x #{w}"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
if word_array.empty?
|
101
|
+
puts "\nIt appears that @#{username} is not much of a talker."
|
102
|
+
else
|
103
|
+
puts "\n@#{username}'s current favorite word(s):"
|
104
|
+
puts word_array.sort.reverse.take(10)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def get_shouts
|
109
|
+
collection = []
|
110
|
+
tweets.each{|num, tweet| collection << tweet.values[0][:shouts]}
|
111
|
+
if collection.flatten.compact.empty?
|
112
|
+
puts "\nIt appears that @#{username} isn't excited by anything."
|
113
|
+
else
|
114
|
+
puts "\n@#{username} shouted about the following things:"
|
115
|
+
collection.flatten.compact.uniq.each{|s| puts s}
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def get_pix
|
120
|
+
collection = []
|
121
|
+
tweets.each{|num, tweet| collection << tweet.values[0][:pix]}
|
122
|
+
if collection.flatten.compact.empty?
|
123
|
+
puts "\nIt appears that @#{username} doesn't think a picture is worth 140 characters."
|
124
|
+
else
|
125
|
+
puts "\n@#{username} shared the following risky clicks:"
|
126
|
+
collection.flatten.compact.uniq.each{|p| puts p}
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def get_links
|
131
|
+
collection = []
|
132
|
+
tweets.each{|num, tweet| collection << tweet.values[0][:links]}
|
133
|
+
if collection.flatten.compact.empty?
|
134
|
+
puts "\nIt appears that @#{username} hasn't found anything worth sharing on the interwebs."
|
135
|
+
else
|
136
|
+
puts "\n@#{username} directed traffic to the following sites:"
|
137
|
+
collection.flatten.compact.uniq.each{|l| puts l}
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def get_numbers
|
142
|
+
collection = []
|
143
|
+
tweets.each{|num, tweet| collection << tweet.values[0][:numbers]}
|
144
|
+
if collection.flatten.compact.empty?
|
145
|
+
puts "\nIt appears that @#{username} isn't a numbers person."
|
146
|
+
else
|
147
|
+
puts "\n@#{username} loves them some digits:"
|
148
|
+
collection.flatten.compact.uniq.each{|n| puts n}
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def get_acronyms
|
153
|
+
collection = []
|
154
|
+
tweets.each{|num, tweet| collection << tweet.values[0][:acronyms]}
|
155
|
+
if collection.flatten.compact.empty?
|
156
|
+
puts "\nIt appears that @#{username} really likes to spell everything out."
|
157
|
+
else
|
158
|
+
puts "\n@#{username} was too lazy to type out the following acronyms:"
|
159
|
+
collection.flatten.compact.uniq.each{|a| puts a}
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def get_hashtags
|
164
|
+
collection = []
|
165
|
+
tweets.each{|num, tweet| collection << tweet.values[0][:hashtags]}
|
166
|
+
if collection.flatten.compact.empty?
|
167
|
+
puts "\nIt appears that @#{username} isn't maximizing their #impressions."
|
168
|
+
else
|
169
|
+
puts "\n@#{username} ameliorated the lack of Thought Leadership on these topics:"
|
170
|
+
collection.flatten.compact.uniq.each{|h| puts h}
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def get_usernames
|
175
|
+
collection = []
|
176
|
+
tweets.each{|num, tweet| collection << tweet.values[0][:usernames]}
|
177
|
+
if collection.flatten.compact.empty?
|
178
|
+
puts "\nIt appears that @#{username} is a bit of a solipsist."
|
179
|
+
else
|
180
|
+
puts "\n@#{username} thinkfluenced the following users:"
|
181
|
+
collection.flatten.compact.uniq{|u| u.downcase}.each{|u| puts u}
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
data/lib/twexicon/cli.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
class Twexicon::CLI
|
2
|
+
def call
|
3
|
+
puts "Welcome to Twexicon."
|
4
|
+
run = true
|
5
|
+
|
6
|
+
while run
|
7
|
+
username = Twexicon::Validator.new.run
|
8
|
+
tweets = Twexicon::Scraper.new(username).refine_tweets
|
9
|
+
if tweets.empty?
|
10
|
+
puts "Unfortunately, @#{username} has never tweeted or has their tweets protected. Sorry about that."
|
11
|
+
else
|
12
|
+
Twexicon::Analyzer.new(username, tweets)
|
13
|
+
end
|
14
|
+
|
15
|
+
input = ""
|
16
|
+
until input =~ /^[yn]$/
|
17
|
+
puts "Would you like to look up tweets from another Twitter handle? [Y/N]"
|
18
|
+
input = gets.strip.gsub(/\W/, "").downcase
|
19
|
+
end
|
20
|
+
input =~ /[n]/ ? run = false : run = true
|
21
|
+
end
|
22
|
+
|
23
|
+
puts "Thank you –– come again!"
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class Twexicon::Scraper
|
2
|
+
attr_reader :tweets
|
3
|
+
|
4
|
+
def initialize(username)
|
5
|
+
@tweets = {}
|
6
|
+
scrape_tweets(username)
|
7
|
+
end
|
8
|
+
|
9
|
+
def scrape_tweets(username)
|
10
|
+
Nokogiri::HTML(open("https://twitter.com/#{username}")).css(".tweet-text").each{|t| tweets[tweets.length+1] = {t.text => {:pix => [], :links => [], :hashtags => [], :usernames => [], :numbers => [], :acronyms => [], :shouts => [], :words => []}}}
|
11
|
+
end
|
12
|
+
|
13
|
+
def refine_tweets
|
14
|
+
tweets.each do |num, tweet|
|
15
|
+
t = tweet.keys[0].dup
|
16
|
+
t.scan(/pic.twitter.com\/\w{10}/){|p| tweet.values[0][:pix] << p.strip}.gsub!(/pic.twitter.com\/\w{10}/, " ")
|
17
|
+
t.scan(/https?:\/\/[\w\.\?\=\&\-\/\#]+/){|w| tweet.values[0][:links] << w.strip}.gsub!(/https?:\/\/[\w\.\?\=\&\-\/\#]+/, " ")
|
18
|
+
t.scan(/#\w+/){|h| tweet.values[0][:hashtags] << h.gsub(/\W/, "").prepend("#")}.gsub!(/#\w+/, " ")
|
19
|
+
t.scan(/@\w+/){|u| tweet.values[0][:usernames] << u.gsub(/\W/, "").prepend("@")}.gsub!(/@\w+/, " ")
|
20
|
+
t.scan(/(\d+[:\.\b]?\d*)+/){|n| tweet.values[0][:numbers] << n.first.gsub(/(^\W+|\W+$)/, "")}.gsub!(/(\d+[:\.\b]?\d*)+/, " ")
|
21
|
+
t.scan(/(\b[A-Z][\.\b][A-Z][\.\b][A-Z][\.\b]|\b[A-Z][\.\b][A-Z][\.\b])/){|a| tweet.values[0][:acronyms] << a.first.strip}.gsub!(/(\b[A-Z][\.\b][A-Z][\.\b][A-Z][\.\b]|\b[A-Z][\.\b][A-Z][\.\b])/, " ")
|
22
|
+
t.scan(/(([A-Z]+\W){2,}|[A-Z]{4,}\W)/){|s| tweet.values[0][:shouts] << s.first.gsub(/\W/, " ").strip}.gsub!(/(([A-Z]+\W){2,}|[A-Z]{4,}\W)/, " ")
|
23
|
+
t.scan(/\b[A-Z]{2,3}\b/){|a| tweet.values[0][:acronyms] << a.strip}.gsub!(/\b[A-Z]{2,3}\b/, " ")
|
24
|
+
t.scan(/\w+['\/]?\w*/){|w| tweet.values[0][:words] << w.strip}.gsub!(/\w+['\/]?\w*/, " ")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class Twexicon::Validator
|
2
|
+
attr_reader :username
|
3
|
+
|
4
|
+
TWITTER_RESERVED_WORDS = ["settings", "i", "search", "logout", "login", "download", "signup", "tos", "privacy", "account"]
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@username = ""
|
8
|
+
end
|
9
|
+
|
10
|
+
def run
|
11
|
+
until username.length > 0
|
12
|
+
puts "\nPlease enter a valid Twitter handle:"
|
13
|
+
@username = gets.gsub(/\W/, "")
|
14
|
+
until is_valid?
|
15
|
+
puts "Sorry, that doesn't seem to be a valid Twitter account. Please try again."
|
16
|
+
@username = gets.gsub(/\W/, "")
|
17
|
+
end
|
18
|
+
begin
|
19
|
+
@username = Nokogiri::HTML(open("https://twitter.com/#{username}")).css("span.u-linkComplex-target").first.text
|
20
|
+
rescue OpenURI::HTTPError, NoMethodError
|
21
|
+
puts "Hm, that doesn't seem to be an active Twitter account."
|
22
|
+
@username = ""
|
23
|
+
run
|
24
|
+
rescue SocketError
|
25
|
+
puts "Sorry, the network isn't responding. Please try again."
|
26
|
+
@username = ""
|
27
|
+
run
|
28
|
+
rescue
|
29
|
+
puts "Something went wrong. Please try again."
|
30
|
+
@username = ""
|
31
|
+
run
|
32
|
+
end
|
33
|
+
end
|
34
|
+
"#{username}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def is_valid?
|
38
|
+
username.match(/^\w{1,15}$/) && !TWITTER_RESERVED_WORDS.include?(username.downcase)
|
39
|
+
end
|
40
|
+
end
|
metadata
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: twexicon
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.6
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Gabe Jackson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-07-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.5'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pry
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.10'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.10'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: nokogiri
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.5'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.5'
|
69
|
+
description: 'When provided a valid Twitter handle, allows for command-line access
|
70
|
+
to the given user''s most recent tweets. Permits the retrieval of individual tweets
|
71
|
+
and can provide ordered lists outlining the following details from the user''s recent
|
72
|
+
tweets: their most frequently used words; any embedded pictures or videos; any embedded
|
73
|
+
hyperlinks; any #hashtags or @usernames mentioned; any numbers, such as years or
|
74
|
+
times of day; any acronyms mentioned; and, last but definitely not least, anything
|
75
|
+
the tweeter felt passionately enough about to SCREAM IN ALL CAPS.'
|
76
|
+
email: gj+code@mail.co.de
|
77
|
+
executables:
|
78
|
+
- twexicon
|
79
|
+
extensions: []
|
80
|
+
extra_rdoc_files: []
|
81
|
+
files:
|
82
|
+
- bin/console
|
83
|
+
- bin/setup
|
84
|
+
- bin/twexicon
|
85
|
+
- config/environment.rb
|
86
|
+
- lib/twexicon.rb
|
87
|
+
- lib/twexicon/analyzer.rb
|
88
|
+
- lib/twexicon/cli.rb
|
89
|
+
- lib/twexicon/scraper.rb
|
90
|
+
- lib/twexicon/validator.rb
|
91
|
+
- lib/twexicon/version.rb
|
92
|
+
homepage: https://github.com/gj/twexicon-cli-gem
|
93
|
+
licenses:
|
94
|
+
- MIT
|
95
|
+
metadata: {}
|
96
|
+
post_install_message:
|
97
|
+
rdoc_options: []
|
98
|
+
require_paths:
|
99
|
+
- lib
|
100
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
requirements: []
|
111
|
+
rubyforge_project:
|
112
|
+
rubygems_version: 2.6.6
|
113
|
+
signing_key:
|
114
|
+
specification_version: 4
|
115
|
+
summary: CLI gem that returns a given Twitter user's most recent tweets and does some
|
116
|
+
basic textual analysis.
|
117
|
+
test_files: []
|