<commit_before>require 'builder'
require 'erubis'
require 'htmlentities'
require 'sinatra/base'

require 'yuitweets'
require 'yuitweets/web/helpers'

module YUITweets; class Web < Sinatra::Base
  set :logging, true
  set :root, ROOT_DIR

  get '/' do
    content_type('text/html', :charset => 'utf-8')
    erubis(:index)
  end

  get '/recent.json' do
    content_type('application/json', :charset => 'utf-8')

    results = recent_tweets

    if results.empty?
      json_success({
        :limit    => @limit,
        :since_id => @since_id
      })
    else
      json_success({
        :add      => results.map {|t| t.to_hash(:html => render_tweet(t)) },
        :limit    => @limit,
        :max_id   => results.first && results.first.id || 0,
        :since_id => @since_id
      })
    end
  end

  get '/recent.rss' do
    content_type('application/rss+xml', :charset => 'utf-8')

    results  = recent_tweets
    entities = HTMLEntities.new

    x = Builder::XmlMarkup.new(:indent => 2)
    x.instruct!

    x.rss(:version     => '2.0',
          'xmlns:atom' => 'http://www.w3.org/2005/Atom',
          'xmlns:dc'   => 'http://purl.org/dc/elements/1.1/') do

      x.channel do
        x.title 'YUI Tweets'
        x.link  'http://yuitweets.pieisgood.org/'
        x.ttl   5

        results.each do |tweet|
          tweet_url = url_tweet(tweet)

          x.item do
            x.title   entities.decode(tweet.text)
            x.link    tweet_url
            x.dc      :creator, tweet.from_user
            x.guid    tweet_url, :isPermaLink => 'true'
            x.pubDate tweet.created_at.rfc2822
          end
        end
      end
    end

    x.target!
  end

  post '/vote.json' do
    content_type('application/json', :charset => 'utf-8')

    id    = params[:id] or json_error(400, "Missing required parameter: id")
    type  = params[:type] or json_error(400, "Missing required parameter: type")
    type.downcase!

    tweet = Tweet[id.to_i] or json_error(400, "Tweet id not found: #{id.to_i}")

    tweet.update(
      :type  => type,
      :votes => tweet.votes + 1
    )

    # Don't retrain if the tweet has already been trained as this type.
    if tweet.type != type
      unless tweet.type.nil?
        # Tweet was previously trained as a different type, so untrain it before
        # retraining.
        YUITweets.bayes.untrain(tweet.type, tweet.specimen)
      end

      YUITweets.bayes.train(type, tweet.specimen)
    end

    json_success({
      :update => [tweet.to_hash(:html => render_tweet(tweet))]
    })
  end
end; end<commit_msg>Oops. Need to train the classifier before updating the vote count, or the training won't actually happen.<commit_after>require 'builder'
require 'erubis'
require 'htmlentities'
require 'sinatra/base'

require 'yuitweets'
require 'yuitweets/web/helpers'

module YUITweets; class Web < Sinatra::Base
  set :logging, true
  set :root, ROOT_DIR

  get '/' do
    content_type('text/html', :charset => 'utf-8')
    erubis(:index)
  end

  get '/recent.json' do
    content_type('application/json', :charset => 'utf-8')

    results = recent_tweets

    if results.empty?
      json_success({
        :limit    => @limit,
        :since_id => @since_id
      })
    else
      json_success({
        :add      => results.map {|t| t.to_hash(:html => render_tweet(t)) },
        :limit    => @limit,
        :max_id   => results.first && results.first.id || 0,
        :since_id => @since_id
      })
    end
  end

  get '/recent.rss' do
    content_type('application/rss+xml', :charset => 'utf-8')

    results  = recent_tweets
    entities = HTMLEntities.new

    x = Builder::XmlMarkup.new(:indent => 2)
    x.instruct!

    x.rss(:version     => '2.0',
          'xmlns:atom' => 'http://www.w3.org/2005/Atom',
          'xmlns:dc'   => 'http://purl.org/dc/elements/1.1/') do

      x.channel do
        x.title 'YUI Tweets'
        x.link  'http://yuitweets.pieisgood.org/'
        x.ttl   5

        results.each do |tweet|
          tweet_url = url_tweet(tweet)

          x.item do
            x.title   entities.decode(tweet.text)
            x.link    tweet_url
            x.dc      :creator, tweet.from_user
            x.guid    tweet_url, :isPermaLink => 'true'
            x.pubDate tweet.created_at.rfc2822
          end
        end
      end
    end

    x.target!
  end

  post '/vote.json' do
    content_type('application/json', :charset => 'utf-8')

    id    = params[:id] or json_error(400, "Missing required parameter: id")
    type  = params[:type] or json_error(400, "Missing required parameter: type")
    type.downcase!

    tweet = Tweet[id.to_i] or json_error(400, "Tweet id not found: #{id.to_i}")

    # Don't retrain if the tweet has already been trained as this type.
    if tweet.type != type
      unless tweet.type.nil?
        # Tweet was previously trained as a different type, so untrain it before
        # retraining.
        YUITweets.bayes.untrain(tweet.type, tweet.specimen)
      end

      YUITweets.bayes.train(type, tweet.specimen)
    end

    tweet.update(
      :type  => type,
      :votes => tweet.votes + 1
    )

    json_success({
      :update => [tweet.to_hash(:html => render_tweet(tweet))]
    })
  end
end; end
{'fraction_non_alphanumeric': 0.1306340718105424, 'fraction_numerical': 0.01145912910618793, 'mean_word_length': 2.2069810165339865, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 6}, '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': '2056526', 'n_tokens_mistral': 1897, 'n_tokens_neox': 1800, 'n_words': 413}