{-# LANGUAGE DeriveDataTypeable #-}
-- pastepipe.hs
--
-- A CLI for Hpaste.org.
--
-- Authored by Rogan Creswick (creswick_at_googles_mail_service.)
--
-- Pastepipe reads from stdin, posting to hpaste, and prints out the
-- resulting url (the last line of output). Parameters control various
-- hpaste form fields:
--
-- -u username (defaults to $USER)
-- -l language (defaults to haskell, of course)
-- -t title (defaults to the empty string)
--
-- It will auto-detect your local username, but -u overrides this detection.
--
-- compile with:
-- ghci --make -package HTTP pastepipe.hs -o pastepipe
module Main where
import Network.HTTP.Base
import Network.URI
import Network.Browser
import Data.Maybe
import System.Environment (getEnv)
import System.Console.CmdArgs
main :: IO ()
main = do
realUser <- getEnv "USER"
conf <- cmdArgs "PastePipe v1.3, (C) Rogan Creswick 2009" [config realUser]
content <- getContents
let postFn = if test conf then fakePost else post
resultUrl <- postFn conf content
putStrLn $ show resultUrl
-- | Configuration type for PastePipe:
data Config = Config { userName :: String
, language :: String
, title :: String
, uri :: String
, test :: Bool }
deriving (Show, Data, Typeable)
-- | Default config.
-- The string passed in is the current user's username.
config :: String -> Mode Config
config realUser = mode $ Config {
userName = realUser &= text
"Your user name"
& typ "USER"
& explicit & flag "user" & flag "u"
, language = "haskell" &= text
"The language used for syntax highlighting"
& typ "LANGUAGE"
, title = "" &= text
"The title of the snippet"
& typ "TITLE"
& explicit & flag "title" & flag "t"
, uri = defaultUri &= text
"The URI of the hpaste instance to post to"
& typ "URL"
, test = False &= text
"Prevents PastePipe from actually posting content, just echos the configuration and input"
}
-- | Define an output handler based on the user-specified verbosity.
outHandler :: String -> IO ()
outHandler str = do
loud <- isLoud -- are we running in verbose mode?
if loud then (putStr str) else (const (return()) str)
-- | The "root" uri for hpaste.org
defaultUri :: String
defaultUri = "http://hpaste.org/fastcgi/hpaste.fcgi/"
-- | The URI for posting new pastes to hpaste.
-- This isn't guaranteed to trigger a failure on all execution paths, as-is.
saveUri :: String -> URI
saveUri coreUri = buildURI coreUri "save"
-- | composes the core uri and a string to create a usable URI
buildURI :: String -> String -> URI
buildURI coreUri str = fromJust $ parseURI $ coreUri ++ str
-- | Posts the given content to hpaste.org, returning the new uri.
post :: Config -> String -> IO URI
post conf str = do
(url, _) <- Network.Browser.browse $ do
setOutHandler outHandler
setAllowRedirects True -- handle HTTP redirects
request $ buildRequest conf str
return url
-- | Creates the request to post a chunk of content.
buildRequest :: Config -> String -> Request String
buildRequest conf str = formToRequest $ Form POST (saveUri $ uri conf)
[ ("title", title conf)
, ("author", userName conf)
, ("content", str)
, ("language", language conf)
, ("channel", "")]
fakePost :: Config -> String -> IO URI
fakePost conf str = do
putStrLn $ "uri: "++uri conf
putStrLn $ "user: "++userName conf
putStrLn $ "lang: "++language conf
putStrLn $ "title: "++title conf
putStrLn $ "content: "++str
return $ fromJust $ parseURI $ uri conf