view app/models/tweet.rb @ 145:c791b6bfeeda

More refactors
author nanaya <me@nanaya.pro>
date Wed, 13 Dec 2017 06:31:07 +0900
parents 1925b08153dc
children 7ca8aeba1a63
line wrap: on
line source

class Tweet
  TIMELINE_OPTIONS = {
    :count => 100,
    :exclude_replies => false,
    :include_rts => true,
    :tweet_mode => :extended,
  }

  def initialize(twitter_id)
    @clients = {}
    @twitter_id = twitter_id
  end

  def cache_expires_time
    (15 + rand(15)).minutes
  end

  def timeline
    if @timeline.nil?
      raw = Rails.cache.fetch("timeline:v2:#{@twitter_id}", :expires_in => cache_expires_time) do
        client_try(:user_timeline, @twitter_id, TIMELINE_OPTIONS).tap do |data|
          if data[:result] == :ok
            data[:data] = data[:data].select do |tweet|
              tweet.retweeted_status.nil? || tweet.user.id != tweet.retweeted_status.user.id
            end.map { |tweet| tweet.to_h }
          end
        end
      end

      raise Twitter::Error::NotFound if raw[:result] == :not_found

      @timeline = raw[:data].map { |tweet_hash| Twitter::Tweet.new(tweet_hash) }
    end

    @timeline
  end

  def user
    if @user.nil?
      return timeline.first.user if timeline.any?

      raw = Rails.cache.fetch("user:v1:#{@twitter_id}", :expires_in => cache_expires_time) do
        client_try :user, @twitter_id
      end

      raise Twitter::Error::NotFound if raw[:result] == :not_found

      @user = raw[:data]
    end

    @user
  end

  def client
    @clients[client_config_id] ||=
      Twitter::REST::Client.new do |config|
        $cfg[:twitter][client_config_id].each do |cfg_key, cfg_value|
          config.public_send(:"#{cfg_key}=", cfg_value)
        end
      end
  end

  def client_try(method, *args)
    initial_config_id = client_config_id

    begin
      data = client.public_send method, *args
    rescue Twitter::Error::TooManyRequests
      @client_config_id += 1

      if initial_config_id == client_config_id
        raise
      else
        retry
      end
    rescue Twitter::Error::NotFound
      return { :result => :not_found }
    end

    { :result => :ok, :data => data }
  end

  def client_config_id
    @client_config_id ||= 0

    @client_config_id %= $cfg[:twitter].size
  end
end