# frozen_string_literal: true # lightweight Twitter api calls class TwitterApi class << self include ActionView::Helpers::NumberHelper BASE_URL = "https://api.twitter.com" def prettify_tweet(tweet) text = tweet["full_text"].dup if (entities = tweet["entities"]) && (urls = entities["urls"]) urls.each do |url| text.gsub!( url["url"], "#{url["display_url"]}", ) end end text = link_hashtags_in link_handles_in text result = Rinku.auto_link(text, :all, 'target="_blank"').to_s if tweet["extended_entities"] && media = tweet["extended_entities"]["media"] media.each do |m| if m["type"] == "photo" if large = m["sizes"]["large"] result << "
" end elsif m["type"] == "video" || m["type"] == "animated_gif" video_to_display = m["video_info"]["variants"] .select { |v| v["content_type"] == "video/mp4" } .sort { |v| v["bitrate"] } .last # choose highest bitrate if video_to_display && url = video_to_display["url"] width = m["sizes"]["large"]["w"] height = m["sizes"]["large"]["h"] attributes = if m["type"] == "animated_gif" %w[playsinline loop muted autoplay disableRemotePlayback disablePictureInPicture] else %w[controls playsinline] end.join(" ") result << <<~HTML
HTML end end end end result end def prettify_number(count) number_to_human( count, format: "%n%u", precision: 2, units: { thousand: "K", million: "M", billion: "B", }, ) end def tweet_for(id) JSON.parse(twitter_get(tweet_uri_for(id))) end alias_method :status, :tweet_for def twitter_credentials_missing? consumer_key.blank? || consumer_secret.blank? end protected def link_handles_in(text) text .gsub(/(?:^|\s)@\w+/) do |match| whitespace = match[0] == " " ? " " : "" handle = match.strip[1..] "#{whitespace}@#{handle}" end .strip end def link_hashtags_in(text) text .gsub(/(?:^|\s)#\w+/) do |match| whitespace = match[0] == " " ? " " : "" hashtag = match.strip[1..] "#{whitespace}##{hashtag}" end .strip end def tweet_uri_for(id) URI.parse "#{BASE_URL}/1.1/statuses/show.json?id=#{id}&tweet_mode=extended" end def twitter_get(uri) request = Net::HTTP::Get.new(uri) request.add_field "Authorization", "Bearer #{bearer_token}" response = http(uri).request(request) if response.kind_of?(Net::HTTPTooManyRequests) Rails.logger.warn("Twitter API rate limit has been reached") end response.body end def authorization request = Net::HTTP::Post.new(auth_uri) request.add_field "Authorization", "Basic #{bearer_token_credentials}" request.add_field "Content-Type", "application/x-www-form-urlencoded;charset=UTF-8" request.set_form_data "grant_type" => "client_credentials" http(auth_uri).request(request).body end def bearer_token @access_token ||= JSON.parse(authorization).fetch("access_token") end def bearer_token_credentials Base64.strict_encode64( "#{UrlHelper.encode_component(consumer_key)}:#{UrlHelper.encode_component(consumer_secret)}", ) end def auth_uri URI.parse "#{BASE_URL}/oauth2/token" end def http(uri) Net::HTTP.new(uri.host, uri.port).tap { |http| http.use_ssl = true } end def consumer_key SiteSetting.twitter_consumer_key end def consumer_secret SiteSetting.twitter_consumer_secret end end end