tilde.news/script/sync_twitter_users

87 lines
2.4 KiB
Ruby
Executable File

#!/usr/bin/env ruby
ENV["RAILS_ENV"] ||= "production"
APP_PATH = File.expand_path("../../config/application", __FILE__)
require File.expand_path("../../config/boot", __FILE__)
require APP_PATH
Rails.application.require_environment!
TWITTER_LIST = "users".freeze
# find the id of our list name
res = Twitter.oauth_request("/1.1/lists/list.json", :get)
our_list = res.find { |l| l["name"] == TWITTER_LIST }
if our_list.blank?
raise "can't find list #{TWITTER_LIST.inspect} in #{res.inspect}"
end
list_id = our_list["id_str"]
# fetch its member list
res = Twitter.oauth_request("/1.1/lists/members.json?list_id=#{list_id}" \
"&count=5000&skip_status=true", :get)
their_users = res["users"].map { |u| [u["screen_name"].downcase, true] }.to_h
if their_users.empty?
raise "Intemittent Twitter bug: they said the list is empty when it's not"
end
if their_users.count >= 5000
warn "need to implement paging for list members"
end
# fetch our active users that have a linked twitter account
our_users = User.active.where("settings LIKE '%twitter_username:%'")
.select { |u| u.twitter_username.present? }
.map { |u| [u.twitter_username.downcase, true] }.to_h
# ignore users that have previously been determined to have protected accounts,
# which cannot be added to a public list
Keystore.where("`key` LIKE 'user:%:twitter_private'").find_each do |ks|
our_users.reject! do |k, _v|
k.downcase == ks.key.scan(/:(.+):/).first.first.downcase
end
end
# diff
to_add = our_users.keys.reject { |u| their_users[u] }
to_del = their_users.keys.reject { |u| our_users[u] }
to_add.each_slice(100) do |g|
# lookup and remove any protected users
Twitter.oauth_request("/1.1/users/lookup.json?screen_name=#{g.join(",")}")
.select { |u| u["protected"] }.each do |u|
# puts "user #{u["screen_name"]} protected, ignoring"
Keystore.put("user:#{u["screen_name"]}:twitter_private", 1)
g.reject! { |tu| tu.downcase == u["screen_name"].downcase }
end
if !g.any?
next
end
# puts "adding: #{g.inspect}"
begin
Twitter.oauth_request(
"/1.1/lists/members/create_all.json",
:post,
"list_id" => list_id,
"screen_name" => g.join(",")
)
rescue Net::OpenTimeout # Twitter's having a nap
exit
end
end
to_del.each_slice(100) do |g|
# puts "deleting: #{g.inspect}"
Twitter.oauth_request(
"/1.1/lists/members/destroy_all.json",
:post,
"list_id" => list_id,
"screen_name" => g.join(",")
)
end