|
#!/usr/bin/env ruby |
|
# |
|
# Quick & dirty script to generate some Twitter statistics for events. |
|
# |
|
# Usage: |
|
# 1. gem install twitter |
|
# 2. Register your “app” on https://apps.twitter.com/apps and set OAuth |
|
# credentials here. |
|
# 3. Profit! |
|
# |
|
# License: |
|
# Creative Commons CC-Zero This file is made available under the Creative |
|
# Commons CC0 1.0 Universal Public Domain Dedication. |
|
# https://creativecommons.org/publicdomain/zero/1.0/deed.en |
|
|
|
require 'ostruct' |
|
require 'twitter' |
|
|
|
|
|
######## Configuration ######## |
|
|
|
HASHTAG = '#WebExpo' |
|
DATE_FROM = '2015-09-18' |
|
DATE_TO = '2015-09-21' |
|
|
|
USERS_LIST_LIMIT = 10 |
|
FAVORITES_LIST_LIMIT = 10 |
|
RETWEETS_LIST_LIMIT = 8 |
|
|
|
client = Twitter::REST::Client.new do |config| |
|
config.consumer_key = 'YOUR_CONSUMER_KEY' |
|
config.consumer_secret = 'YOUR_CONSUMER_SECRET' |
|
config.access_token = 'YOUR_ACCESS_TOKEN' |
|
config.access_token_secret = 'YOUR_ACCESS_SECRET' |
|
end |
|
|
|
year = DATE_FROM.split('-').first |
|
|
|
|
|
######## Functions ######## |
|
|
|
def top_tweets_by(field, tweets) |
|
tweets.lazy |
|
.group_by { |tw| tw.public_send(field) } |
|
.sort.reverse |
|
.map { |count, tweets| [count, tweets.sort_by(&:created_at)] } |
|
end |
|
|
|
def top_users_by_tweets_count(tweets) |
|
tweets.lazy |
|
.group_by(&:user) |
|
.map { |user, tweets| [user, tweets.count] } |
|
.group_by(&:last) # group by number of tweets |
|
.sort.reverse |
|
.map { |count, tuples| [count, tuples.map(&:first)] } # extract users as value of the entry |
|
.map { |count, users| [count, users.sort_by(&:screen_name)] } |
|
end |
|
|
|
def title(level, text) |
|
puts "\n\n#{'=' * level} #{text}\n\n" |
|
end |
|
|
|
def table(headers, data, &block) |
|
lines = ['|===', '| ' + headers.join(' | '), ''] |
|
data.each_with_index do |item, idx| |
|
(yield item, idx + 1).each do |col| |
|
lines << "| #{col}" |
|
end |
|
lines << '' |
|
end |
|
lines << '|===' << '' |
|
puts lines.join("\n") |
|
end |
|
|
|
format_user = ->(user) { "#{user.uri}[@#{user.screen_name}] (#{user.followers_count})" } |
|
format_tweet = ->(tweet) { "@#{tweet.user.screen_name}: #{tweet.uri}[#{tweet.text}]" } |
|
|
|
|
|
######## Main ######## |
|
|
|
tweets = client.search("#{HASHTAG} since:#{DATE_FROM} until:#{DATE_TO}", result_type: :all) |
|
.reject { |tweet| tweet.retweet? } |
|
|
|
users = tweets.map(&:user).uniq |
|
favourites_count = tweets.map(&:favorite_count).reduce(:+) |
|
retweets_count = tweets.map(&:retweet_count).reduce(:+) |
|
top_users = top_users_by_tweets_count(tweets).take(USERS_LIST_LIMIT) |
|
top_favorites = top_tweets_by(:favorite_count, tweets).take(FAVORITES_LIST_LIMIT) |
|
top_retweets = top_tweets_by(:retweet_count, tweets).take(RETWEETS_LIST_LIMIT) |
|
|
|
|
|
# Print report in AsciiDoc |
|
|
|
title 1, "Twitter statistics for #{HASHTAG} #{year}" |
|
|
|
puts "* Number of tweets (excluding RTs): #{tweets.count}" |
|
puts "* Number of favourites: #{favourites_count}" |
|
puts "* Number of retweets: #{retweets_count}" |
|
puts "* Number of tweeting users: #{users.count}" |
|
|
|
|
|
title 2, 'TOP tweeting users' |
|
|
|
puts "List of most active users sorted by number of their tweets with hashtag #{HASHTAG}.\n\n" |
|
|
|
table ['Rank', 'User(s)', 'Tweets'], top_users do |(count, users), idx| |
|
["#{idx}.", users.map(&format_user).join(', '), count] |
|
end |
|
|
|
|
|
title 2, 'TOP favourited tweets' |
|
|
|
table ['Rank', 'Tweet(s)', 'Favourites'], top_favorites do |(count, tweets), idx| |
|
["#{idx}.", tweets.map(&format_tweet).join("\n\n"), count] |
|
end |
|
|
|
|
|
title 2, 'TOP retweeted tweets' |
|
|
|
table ['Rank', 'Tweet(s)', 'Retweets'], top_retweets do |(count, tweets), idx| |
|
["#{idx}.", tweets.map(&format_tweet).join("\n\n"), count] |
|
end |
|
|
|
puts "\n\n''''" |
|
puts "_Generated on #{Time.now}._" |