midwire
1/27/2015 - 8:02 PM

pastie.rb

#!/usr/bin/env ruby
# kate: remove-trailing-space on; replace-trailing-space-save on; indent-width 2; indent-mode ruby; syntax ruby;

require 'net/http'
require 'optparse'
require 'timeout'
require 'cgi'
require 'uri'

class Hash

  def to_query_string
    map { |k, v|
      if v.instance_of?(Hash)
        v.map { |sk, sv|
          "#{k}[#{sk}]=#{sv}"
        }.join('&')
      else
        "#{k}=#{v}"
      end
    }.join('&')
  end

end

module Pastie

  AVAILABLE_PARSERS = %w( objective-c++ actionscript ruby ruby_on_rails diff
    plain_text c++ css java javascript html html_rails shell shell-unix-generic
    sql php python pascal perl yaml csharp go apache lua io lisp d erlang fortran
    haskell literate_haskell makefile scala scheme smarty ini nu tex clojure
  )

  class API

    PASTIE_URL = URI.parse "http://pastie.org/pastes"

    def paste(body, format = 'plain_text', is_private = false)
      raise InvalidParser unless valid_parser? format

      http = Net::HTTP.new PASTIE_URL.host, PASTIE_URL.port

      query_string = { :paste => {
        :body => CGI.escape(body),
        :parser => format,
        :restricted => is_private,
        :authorization => 'burger'
      }}.to_query_string

      response, body = http.start do |http|
        http.post PASTIE_URL.path, query_string
      end

      raise Pastie::Error unless response.code == '302'

      response['location']
    end

    private

    def valid_parser?(format)
      Pastie::AVAILABLE_PARSERS.include? format
    end

  end

  class Error < StandardError; end
  class InvalidParser < StandardError; end

  class ConsoleOptions

    attr_reader :parser, :options

    def initialize
      @options = {
        :format => 'plain_text',
        :private => false
      }

      @parser = OptionParser.new do |cmd|
        cmd.banner = "Ruby Pastie CLI - takes paste input from STDIN"

        cmd.separator ''

        cmd.on('-h', '--help', 'Displays this help message') do
          puts @parser
          exit
        end

        cmd.on('-f', '--format FORMAT', "The format of the text being pasted. Available parsers: #{Pastie::AVAILABLE_PARSERS.join(', ')}") do |format|
          @options[:format] = format
        end

        cmd.on('-p', '--private', 'Create a private paste') do
          @options[:private] = true
        end
      end
    end

    def run arguments
      @parser.parse!(arguments)

      body = ''

#       Timeout.timeout(1) do
        body += STDIN.read
#       end

      if body.strip.empty?
        puts "Please pipe in some content to paste on STDIN."
        exit 1
      end

      pastie = API.new
      puts pastie.paste(body, @options[:format], @options[:private])

      exit 0
    rescue InvalidParser
      puts "Please specify a valid format parser."
      exit 1
    rescue Error
      puts "An unknown error occurred"
      exit 1
    rescue Timeout::Error
      puts "Could not read from STDIN."
      exit 1
    end
  end
end

if ($0 == __FILE__)
  app = Pastie::ConsoleOptions.new
  app.run(ARGV)
end