<commit_before># encoding: utf-8
require 'sinatra'
require 'instagram'
require 'active_support/core_ext/object/blank'
require 'active_support/notifications'
require 'active_support/cache'
require 'active_support/core_ext/numeric/time'
require 'active_support/core_ext/integer/time'
require 'active_support/core_ext/time/acts_like'
require 'addressable/uri'
require 'digest/md5'
require 'haml'
require 'sass'
require 'compass'
require 'models'
require 'choices'

Choices.load_settings(File.join(settings.root, 'config.yml'), settings.environment.to_s).each do |key, value|
  set key.to_sym, value
end

Compass.configuration do |config|
  config.project_path = settings.root
  config.sass_dir = 'views'
end

set :haml, format: :html5
set :scss do
  Compass.sass_engine_options.merge style: settings.production? ? :compressed : :nested,
    cache_location: File.join(ENV['TMPDIR'], 'sass-cache')
end

set(:search_index) {
  search_client = IndexTank::Client.new(settings.indextank.api_url)
  search_client.indexes('idx')
}

set(:cache_dir) { File.join(ENV['TMPDIR'], 'cache') }

Instagram.configure do |config|
  for key, value in settings.instagram
    config.send("#{key}=", value)
  end

  config.cache = ActiveSupport::Cache::FileStore.new settings.cache_dir,
    namespace: 'instagram',
    expires_in: settings.production? ? 3.minutes : 1.hour
end

configure :development, :production do
  Mingo.connect settings.mongodb.url
  User.collection.create_index(:username, :unique => true)

  ActiveSupport::Cache::Store.instrument = true

  ActiveSupport::Notifications.subscribe('search.indextank') do |name, start, ending, _, payload|
    $stderr.puts 'IndexTank search for "%s" (%.3f s)' % [payload[:query], ending - start]
  end

  strip_params = %w[access_token client_id]

  ActiveSupport::Notifications.subscribe('request.faraday') do |name, start, ending, _, payload|
    url = payload[:url]
    if (url.query_values.keys & strip_params).any?
      url = url.dup
      url.query_values = url.query_values.reject { |k,| strip_params.include? k }
    end
    $stderr.puts '[%s] %s %s (%.3f s)' % [url.host, payload[:method].to_s.upcase, url.request_uri, ending - start]
  end
  
  ActiveSupport::Notifications.subscribe(/^cache_(\w+).active_support$/) do |name, start, ending, _, payload|
    case name.split('.').first
    when 'cache_reuse_stale'
      $stderr.puts "Error rebuilding cache: %s (%s)" % [payload[:key], payload[:exception].message]
    when 'cache_generate'
      $stderr.puts "Cache rebuild: %s (%.3f s)" % [payload[:key], ending - start]
    when 'cache_read'
      $stderr.puts "Cache hit: %s" % payload[:key] if payload[:hit]
    end
  end
end

configure :development do
  set :logging, false
end

FILTERS = {
  1 => 'X-Pro II',
  2 => 'Lomo-fi',
  3 => 'Earlybird',
  4 => 'Apollo',
  5 => 'Poprocket',
  10 => 'Inkwell',
  13 => 'Gotham',
  14 => '1977',
  15 => 'Nashville',
  16 => '<NAME>',
  17 => 'Lily',
  18 => 'Sutro',
  19 => 'Toaster',
  20 => 'Walden',
  21 => 'Hefe'
}

helpers do
  def instalink(text)
    text.sub(/\b(on instagram)\b/i, '<span>\1</span>').
      sub(/\b(instagram)\b/i, '<a href="http://instagr.am">\1</a>')
  end
  
  def photo_url(photo)
    absolute_url "/users/#{photo.user.username}#p#{photo.id}"
  end
  
  def user_url(user_id)
    absolute_url "/users/#{user_id}"
  end
  
  def atom_path(user)
    "/users/#{user.user_id}.atom"
  end
  
  def absolute_url(path)
    abs_uri = "#{request.scheme}://#{request.host}"

    if request.scheme == 'https' && request.port != 443 ||
          request.scheme == 'http' && request.port != 80
      abs_uri << ":#{request.port}"
    end

    abs_uri << path
  end
  
  def root_path?
    request.path == '/'
  end
  
  def user_path?
    request.path.index('/users/') == 0
  end
  
  def search_path?
    request.path.index('/search') == 0
  end
  
  def search_page(page)
    Addressable::URI.parse(request.path).tap do |url|
      url.query_values = params.merge('page' => page.to_s)
    end
  end
  
  def last_modified_from_photos(photos)
    if photos.any?
      last_modified Time.at(photos.first.created_time.to_i)
    end
  end
end

get '/' do
  @photos = Instagram::media_popular
  @title = "Instagram popular photos"
  
  expires 15.minutes, :public
  haml :index
end

get '/popular.atom' do
  @photos = Instagram::media_popular
  @title = "Instagram popular photos"
  <commit_msg>enable using `expires 15.minutes` again<commit_after># encoding: utf-8
require 'sinatra'
require 'instagram'
require 'active_support/core_ext/object/blank'
require 'active_support/notifications'
require 'active_support/cache'
require 'active_support/core_ext/numeric/time'
require 'active_support/core_ext/integer/time'
require 'active_support/core_ext/time/acts_like'
require 'addressable/uri'
require 'digest/md5'
require 'haml'
require 'sass'
require 'compass'
require 'models'
require 'choices'

Choices.load_settings(File.join(settings.root, 'config.yml'), settings.environment.to_s).each do |key, value|
  set key.to_sym, value
end

Compass.configuration do |config|
  config.project_path = settings.root
  config.sass_dir = 'views'
end

set :haml, format: :html5
set :scss do
  Compass.sass_engine_options.merge style: settings.production? ? :compressed : :nested,
    cache_location: File.join(ENV['TMPDIR'], 'sass-cache')
end

set(:search_index) {
  search_client = IndexTank::Client.new(settings.indextank.api_url)
  search_client.indexes('idx')
}

set(:cache_dir) { File.join(ENV['TMPDIR'], 'cache') }

Instagram.configure do |config|
  for key, value in settings.instagram
    config.send("#{key}=", value)
  end

  config.cache = ActiveSupport::Cache::FileStore.new settings.cache_dir,
    namespace: 'instagram',
    expires_in: settings.production? ? 3.minutes : 1.hour
end

configure :development, :production do
  Mingo.connect settings.mongodb.url
  User.collection.create_index(:username, :unique => true)

  ActiveSupport::Cache::Store.instrument = true

  ActiveSupport::Notifications.subscribe('search.indextank') do |name, start, ending, _, payload|
    $stderr.puts 'IndexTank search for "%s" (%.3f s)' % [payload[:query], ending - start]
  end

  strip_params = %w[access_token client_id]

  ActiveSupport::Notifications.subscribe('request.faraday') do |name, start, ending, _, payload|
    url = payload[:url]
    if (url.query_values.keys & strip_params).any?
      url = url.dup
      url.query_values = url.query_values.reject { |k,| strip_params.include? k }
    end
    $stderr.puts '[%s] %s %s (%.3f s)' % [url.host, payload[:method].to_s.upcase, url.request_uri, ending - start]
  end
  
  ActiveSupport::Notifications.subscribe(/^cache_(\w+).active_support$/) do |name, start, ending, _, payload|
    case name.split('.').first
    when 'cache_reuse_stale'
      $stderr.puts "Error rebuilding cache: %s (%s)" % [payload[:key], payload[:exception].message]
    when 'cache_generate'
      $stderr.puts "Cache rebuild: %s (%.3f s)" % [payload[:key], ending - start]
    when 'cache_read'
      $stderr.puts "Cache hit: %s" % payload[:key] if payload[:hit]
    end
  end
end

configure :development do
  set :logging, false
end

FILTERS = {
  1 => 'X-Pro II',
  2 => 'Lomo-fi',
  3 => 'Earlybird',
  4 => 'Apollo',
  5 => 'Poprocket',
  10 => 'Inkwell',
  13 => 'Gotham',
  14 => '1977',
  15 => 'Nashville',
  16 => '<NAME>',
  17 => 'Lily',
  18 => 'Sutro',
  19 => 'Toaster',
  20 => 'Walden',
  21 => 'Hefe'
}

helpers do
  def instalink(text)
    text.sub(/\b(on instagram)\b/i, '<span>\1</span>').
      sub(/\b(instagram)\b/i, '<a href="http://instagr.am">\1</a>')
  end
  
  def photo_url(photo)
    absolute_url "/users/#{photo.user.username}#p#{photo.id}"
  end
  
  def user_url(user_id)
    absolute_url "/users/#{user_id}"
  end
  
  def atom_path(user)
    "/users/#{user.user_id}.atom"
  end
  
  def absolute_url(path)
    abs_uri = "#{request.scheme}://#{request.host}"

    if request.scheme == 'https' && request.port != 443 ||
          request.scheme == 'http' && request.port != 80
      abs_uri << ":#{request.port}"
    end

    abs_uri << path
  end
  
  def root_path?
    request.path == '/'
  end
  
  def user_path?
    request.path.index('/users/') == 0
  end
  
  def search_path?
    request.path.index('/search') == 0
  end
  
  def search_page(page)
    Addressable::URI.parse(request.path).tap do |url|
      url.query_values = params.merge('page' => page.to_s)
    end
  end
  
  def last_modified_from_photos(photos)
    if photos.any?
      last_modified Time.at(photos.first.created_time.to_i)
    end
  end
  
  # enables using `15.minutes`
  def expires(amount, *args)
    amount = amount.to_i if amount.class == Fixnum
    super(amount, *args)
  end
end

get '/' do
  @photos = Instagram::media_popular
  @title = "Instagram popular photos"
  
  expires 15.minutes, :public
  haml :index
end

get '/popular.atom' do
  @photos = Instagram::media_popular
  @title = "Instagram popular photos"
  
{'fraction_non_alphanumeric': 0.15485886421956935, 'fraction_numerical': 0.011156978690170702, 'mean_word_length': 3.775705913692062, 'pattern_counts': {'":': 2, '<': 21, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7157242', 'n_tokens_mistral': 3266, 'n_tokens_neox': 3169, 'n_words': 692}