Created
September 6, 2020 01:04
-
-
Save jasoncrawford/681f3fe367d67f1f725a73c9575fb988 to your computer and use it in GitHub Desktop.
Twitter utilities
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
These are some Twitter utilities, written directly against their API. | |
Credentials are required. Sign up for a Twitter developer account. | |
To run these scripts, ensure the BEARER_TOKEN is in the environment. E.g., put it in a .env file and run with foreman. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'net/http' | |
require 'json' | |
require 'csv' | |
TOKEN = ENV['BEARER_TOKEN'] | |
def twitter_uri(path) | |
URI.parse("https://api.twitter.com/#{path}") | |
end | |
def twitter_request(uri, request) | |
http = Net::HTTP.new(uri.host, uri.port) | |
http.use_ssl = true | |
request['Authorization'] = "Bearer #{TOKEN}" | |
response = http.request(request) | |
raise "HTTP error #{response.code}: #{response.message}" if response.code.to_i >= 400 | |
JSON.parse(response.body) | |
end | |
def twitter_get(path) | |
uri = twitter_uri(path) | |
request = Net::HTTP::Get.new(uri.request_uri) | |
twitter_request(uri, request) | |
end | |
def twitter_post(path, params) | |
uri = twitter_uri(path) | |
request = Net::HTTP::Post.new(uri.request_uri) | |
request.set_form_data(params) | |
twitter_request(uri, request) | |
end | |
username = ARGV[0] | |
cursor = -1 | |
ids = [] | |
while cursor != 0 | |
response = twitter_get("1.1/followers/ids.json?screen_name=#{username}&cursor=#{cursor}") | |
ids += response['ids'] | |
cursor = response['next_cursor'] | |
puts "got #{ids.count} follower IDs" | |
end | |
puts "done getting follower IDs" | |
puts | |
count = 100 | |
offset = 0 | |
users = [] | |
while offset < ids.length | |
ids_block = ids.slice(offset, count) | |
response = twitter_post("1.1/users/lookup.json", {user_id: ids_block.join(","), include_entities: false}) | |
users += response | |
offset += count | |
puts "got #{users.count} followers" | |
end | |
puts "done getting followers" | |
puts | |
top_users = users.select {|u| u['followers_count'] >= 10000}.sort_by {|u| -u['followers_count']} | |
keys = [ | |
"followers_count", | |
"screen_name", | |
"name", | |
"description", | |
"url", | |
"location", | |
"verified", | |
"friends_count", | |
"statuses_count", | |
"favourites_count", | |
"listed_count", | |
"created_at", | |
"id", | |
] | |
CSV.open("top-followers.csv", "wb") do |csv| | |
csv << (keys + ["profile_url"]) | |
top_users.each do |user| | |
values = keys.map {|k| user[k]} | |
profile_url = "https://twitter.com/#{user['screen_name']}" | |
csv << (values + [profile_url]) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'net/http' | |
require 'json' | |
require 'csv' | |
TOKEN = ENV['BEARER_TOKEN'] | |
def twitter_uri(path) | |
URI.parse("https://api.twitter.com/#{path}") | |
end | |
def twitter_request(uri, request) | |
http = Net::HTTP.new(uri.host, uri.port) | |
http.use_ssl = true | |
request['Authorization'] = "Bearer #{TOKEN}" | |
response = http.request(request) | |
raise "HTTP error #{response.code}: #{response.message}" if response.code.to_i >= 400 | |
JSON.parse(response.body) | |
end | |
def twitter_get(path) | |
uri = twitter_uri(path) | |
request = Net::HTTP::Get.new(uri.request_uri) | |
twitter_request(uri, request) | |
end | |
tweet_url = ARGV[0] | |
puts "fetching thread *ending* with #{tweet_url}" | |
match = tweet_url.match(/status\/(\d+)/) | |
tweet_id = match[1] | |
tweets = [] | |
while tweet_id | |
puts "fetching tweet #{tweet_id}" | |
response = twitter_get("2/tweets/#{tweet_id}?tweet.fields=referenced_tweets") | |
data = response['data'] | |
text = data['text'].sub(/\n+/, ' ') | |
tweets.unshift text | |
referenced_tweets = data['referenced_tweets'] | |
replied_to = referenced_tweets && referenced_tweets.find {|t| t['type'] == 'replied_to'} | |
tweet_id = replied_to && replied_to['id'] | |
end | |
puts | |
puts tweets.join("\n\n") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment