HaskellからAOJにサブミットする

http-enumerator使って書いた。
大したコードじゃないので、ここに貼っておくことにする。
twitter-enumeratorのコードを参考にした。
気が向いたら、公開されているAPIのためのコードも書いてまとめるかもしれない

{-# LANGUAGE OverloadedStrings #-}

import Prelude hiding (dropWhile)
import Network.HTTP.Enumerator
import qualified Network.HTTP.Types as HT

import Data.Enumerator (Iteratee, throwError, run_)
import Data.Enumerator.List (dropWhile)

import Data.ByteString (ByteString)

import Control.Monad.Trans.Class (lift)
import Control.Monad.IO.Class (liftIO)

endpoint :: String
endpoint = "http://judge.u-aizu.ac.jp/onlinejudge/servlet/Submit"

userID :: ByteString
userID = "your user id"

password :: ByteString
password = "your password"

api :: ByteString -- method
       -> String  -- url
       -> HT.Query -- query 
       -> Iteratee ByteString IO a
       -> Iteratee ByteString IO a
api m url query iter = do
  req <- lift $ makeRequest m url query
  mgr <- lift newManager
  http req (handleError iter) mgr
  where
    handleError iter' st@(HT.Status sc _) _ =
      if 200 <= sc && sc < 300
      then iter'
      else throwError $ StatusCodeException sc "Bad Status Code"

makeRequest :: ByteString -> String -> HT.Query -> IO (Request IO)
makeRequest m url query = do
  pu <- liftIO $ parseUrl url
  return $ pu { method = m, queryString = query }

submitQuery user pass pid lang src =
  [("userID"    , Just user),
   ("password"  , Just pass),
   ("language"  , Just lang),
   ("problemNO" , Just pid),
   ("sourceCode", Just src)]

submit :: ByteString -- problem id
          -> ByteString -- language
          -> ByteString -- source code
          -> Iteratee ByteString IO a -- iter
          -> Iteratee ByteString IO a
submit pid lang src = api "POST" endpoint (submitQuery userID password pid lang src)

main :: IO ()
main = do
  run_ $ submit "0000" "C" "int main(){return 0;}" (dropWhile (const True))