find_friends_worker.rb 2.2 KB
Newer Older
Eugen Rochko's avatar
Eugen Rochko committed
1 2 3 4 5 6 7
# frozen_string_literal: true

class FindFriendsWorker
  include Sidekiq::Worker
  include Sidekiq::Status::Worker

  def perform(user_id)
8 9
    current_user   = User.find(user_id)
    client         = current_user.twitter_client
Eugen Rochko's avatar
Eugen Rochko committed
10 11
    all_friend_ids = []
    twitter_user   = client.user
12
    performed      = 0
Eugen Rochko's avatar
Eugen Rochko committed
13 14 15 16 17 18

    total twitter_user.friends_count

    begin
      client.friend_ids.each do |friend_id|
        all_friend_ids << friend_id
19 20
        performed += 1
        at performed
Eugen Rochko's avatar
Eugen Rochko committed
21 22 23 24 25 26
      end
    rescue Twitter::Error::TooManyRequests => error
      sleep error.rate_limit.reset_in + 1
      retry
    end

27 28 29 30 31
    users = User.where(id: Authorization.where(provider: :twitter, uid: all_friend_ids).map(&:user_id))
                .includes(:twitter, :mastodon)
                .reject { |user| user.mastodon.nil? }

    unless current_user.mastodon.nil?
Yamagishi Kazutoshi's avatar
Yamagishi Kazutoshi committed
32
      total all_friend_ids * 2 + 1
33

34
      users.each do |user|
35 36 37
        performed += 1
        at performed

38 39
        begin
          user.relative_account_id = Rails.cache.fetch("#{current_user.id}/#{current_user.mastodon.domain}/#{user.mastodon.uid}", expires_in: 1.week) do
Yamagishi Kazutoshi's avatar
Yamagishi Kazutoshi committed
40
            account, = current_user.mastodon_client.perform_request(:get, '/api/v1/accounts/search', q: user.mastodon.uid, resolve: 'true', limit: 1)
41 42 43 44 45 46 47 48 49
            next if account.nil?
            account['id']
          end
        rescue Mastodon::Error, HTTP::Error, OpenSSL::SSL::SSLError
          next
        end
      end

      set_relationships!(current_user, users)
50 51
      performed += 1
      at performed
52 53 54 55 56 57 58 59 60
    end

    Rails.cache.write("#{current_user.id}/friends", users.map { |u| [u.id, u.relative_account_id, u.following] })
  end

  private

  def set_relationships!(current_user, users)
    account_map = users.map { |user| [user.relative_account_id, user] }.to_h
Yamagishi Kazutoshi's avatar
Yamagishi Kazutoshi committed
61
    account_ids = users.map(&:relative_account_id).compact
62 63 64
    param_str   = account_ids.map { |id| "id[]=#{id}" }.join('&')

    current_user.mastodon_client.perform_request(:get, "/api/v1/accounts/relationships?#{param_str}").each do |relationship|
65
      account_map[relationship['id']].following = relationship['following'] || relationship['requested']
66 67 68
    end
  rescue Mastodon::Error, HTTP::Error, OpenSSL::SSL::SSLError
    nil
Eugen Rochko's avatar
Eugen Rochko committed
69 70
  end
end