donfanning
8/15/2018 - 1:34 PM

SocialBot full gist

SocialBot full gist

!!!
%html(prefix="og: http://ogp.me/ns#")
  %head
    %meta(http-equiv='Content-Type' content='text/html')
    %meta(charset='utf-8')
    - if ENV['analytics_yandex_verification']
      %meta(name="yandex-verification" content="#{ENV['analytics_yandex_verification']}")
    %title= @meta['title']+@meta['title_sufix']
    %meta(name='description' content="#{@meta['description']}")
    %meta(name="author" content="#{@meta['author']}")
    %meta(property="og:title" content="#{@meta['og:title']}")
    %meta(property="og:description" content="#{@meta['og:description']}")
    %meta(property="og:image" content="#{@meta['og:image']}")
    %meta(property="og:url" content="#{@meta['og:url']}")
    %meta(property='og:locale:locale' content='ru_ru')

    %meta(name='twitter:card' content="#{@meta['twitter:card']}")
    %meta(name='twitter:domain' content="#{ENV['root_domain']}")
    %meta(name='twitter:site_name' content="#{@meta['og:title']}")
    %meta(name='twitter:site' content="#{@meta['twitter:site']}")
    %meta(name='twitter:creator' content="#{@meta['twitter:site']}")
    %meta(name='twitter:description' content="#{@meta['twitter:creator']}")
    %meta(name='twitter:image:src' content="#{@meta['og:image']}")

    %meta(property='vk:description' content="#{@meta['og:description']}")
    %meta(property='vk:title' content="#{@meta['og:title']}")

    %link(rel='image_src' href="#{@meta['og:image']}")
  %body
module BaseSiteTheme
  module Rack
    class SocialBot
      require 'net/http'
      require 'active_support'
      require 'haml'

      def initialize(app)
        Rails.logger.debug 'Init SocialBot'
        @crawler_user_agents = ['rambler', 'googlebot', 'aport', 'yahoo', 'msnbot', 'turtle', 'mail.ru', 'omsktele',
                                'yetibot', 'picsearch', 'sape.bot', 'sape_context', 'gigabot', 'snapbot', 'alexa.com',
                                'megadownload.net', 'askpeter.info', 'igde.ru', 'ask.com', 'qwartabot', 'yanga.co.uk',
                                'scoutjet', 'similarpages', 'oozbot', 'shrinktheweb.com', 'aboutusbot', 'followsite.com',
                                'dataparksearch', 'google-sitemaps', 'appEngine-google', 'feedfetcher-google',
                                'liveinternet.ru', 'xml-sitemaps.com', 'agama', 'metadatalabs.com', 'h1.hrn.ru',
                                'googlealert.com', 'seo-rus.com', 'yaDirectBot', 'yandeG', 'yandex', 'yandexSomething',
                                'Copyscape.com', 'AdsBot-Google', 'domaintools.com', 'Nigma.ru', 'bing.com', 'dotnetdotcom',
                                'baiduspider', 'facebookexternalhit', 'twitterbot', 'rogerbot', 'linkedinbot', 'embedly',
                                'bufferbot', 'quora link preview', 'showyoubot', 'outbrain', 'pinterest',
                                'developers.google.com/+/web/snippet', 'slackbot', 'vkShare', 'W3C_Validator', 'redditbot',
                                'Applebot', 'OdklBot', 'Bingbot', 'SkypeUriPreview']

        @extensions_to_ignore = %w(.js .css .xml .less .png .jpg .jpeg .gif .pdf .doc .txt .ico .rss .zip .mp3 .rar .json
        .exe .wmv .doc .avi .ppt .mpg .mpeg .tif .wav .mov .psd .ai .xls .mp4 .m4a .swf .dat .dmg .iso .flv .m4v .torrent /api/)
        @app = app
      end

      def call(env)
        if should_show_bot_page(env)
          static_render(env)
        else
          @app.call(env)
        end
      end

      def should_show_bot_page(env)
        user_agent = env['HTTP_USER_AGENT']
        buffer_agent = env['X-BUFFERBOT']
        is_requesting_prerendered_page = false

        return false unless user_agent
        return false if env['REQUEST_METHOD'] != 'GET'

        request = ::Rack::Request.new(env)

        is_requesting_prerendered_page = true if ::Rack::Utils.parse_query(request.query_string).has_key?('_escaped_fragment_')
        is_requesting_prerendered_page = true if @crawler_user_agents.any? { |crawler_user_agent| user_agent.downcase.include?(crawler_user_agent.downcase) }
        is_requesting_prerendered_page = true if buffer_agent

        return false if @extensions_to_ignore.any? { |extension| request.fullpath.include? extension }

        return is_requesting_prerendered_page
      end

      def static_render(env)
        @meta = default_meta(env).merge!(detected_meta(env))
        template = File.read(File.join(File.dirname(__FILE__), '../../..', 'app', 'views', 'layouts', 'static.html.haml'))
        haml_engine = Haml::Engine.new(template)
        output = haml_engine.render(binding)
        [200, {'Content-Type' => 'text/html'}, ["#{output}"]]
      end

      def default_meta(env)
        {
            'title_sufix' => " | #{I18n.t('site.title_suffix')}",
            'title' => I18n.t('site.title'),
            'description' => I18n.t('site.description'),
            'author' => I18n.t('site.author'),
            'og:title' => I18n.t('site.og_title'),
            'og:description' => I18n.t('site.og_description'),
            'og:image' => ActionController::Base.helpers.image_url(ENV['SEO_default_img']),
            'og:url' => "#{env['rack.url_scheme']}://#{env['HTTP_HOST']}#{env['REQUEST_PATH']}",
            'twitter:card' => 'summary_large_image',
            'twitter:site' => I18n.t('site.twitter_site'),
            'twitter:creator' => I18n.t('site.twitter_creator')
        }
      end

      def detected_meta(env)
        path = env['REQUEST_PATH']
        resource_klass, resource_id = case path
                                        when /posts\/(.+)$/
                                          [Blog::Post, $1]
                                        when /mneniya\/(.+)$/
                                          [Opinion::Post, $1]
                                        when /smi-o-nas\/(.+)$/
                                          [MassMedia::Post, $1]
                                        when /page\/(.+)$/
                                          [Site::Page, $1]
                                        when /videos\/(.+)$/
                                          [Video, $1]
                                        else
                                          []
                                      end
        if resource_klass && (resource = resource_klass.find(resource_id).try(:decorate)).present?
          resource.seo_meta
        else
          {}
        end
      end
    end
  end
end