Ranka-0.1: Omegle.hs
module Omegle (
OmegleState,
newOmegleState,
getOmegleState,
startOmegle,
stopOmegle,
sendToOmegle,
startAndSendToOmegle
) where
import Network.XMPP
import Network.XMPP.MUC
import Network
import Data.IORef
import Control.Concurrent
import Network.HTTP
import Network.URI
import Text.JSON
import Text.JSON.String
import Codec.Binary.UTF8.String
import Data.List
-- | Omegle connection state.
type OmegleState = IORef Omegle
data Omegle = NoConnect | Connect OmegleID
type OmegleID = String
-- | Create IORef.
newOmegleState :: IO OmegleState
newOmegleState = newIORef NoConnect
-- | Get state.
getOmegleState :: OmegleState -> IO String
getOmegleState omegleState = do
omegle <- readIORef omegleState
return $ case omegle of
NoConnect -> "not connected"
Connect oID -> "connected, id:"++oID
-- | Start new omegle chat.
startOmegle :: OmegleState -> TCPConnection -> String -> IO String
startOmegle omegleState c room = do
omegle <- readIORef omegleState
case omegle of
Connect oID -> return $ "FAIL, already connected, id:"++oID
NoConnect -> do oID <- getNewOmegleID
writeIORef omegleState (Connect oID)
forkIO $ runOmegleEvents omegleState c room
return ""
-- | Stop omegle chat.
stopOmegle :: OmegleState -> IO String
stopOmegle omegleState = do
omegle <- readIORef omegleState
case omegle of
NoConnect -> return "FAIL, not connected"
Connect oID -> do writeIORef omegleState NoConnect
sendOmegleDisconnect oID
return ""
-- | Send message to omegle chat.
sendToOmegle :: OmegleState -> String -> IO String
sendToOmegle omegleState msg = do
omegle <- readIORef omegleState
case omegle of
NoConnect -> return "FAIL, not connected"
Connect oID -> do responce <- sendToOmegleID oID msg
return $ if responce == "fail"
then "FAIL"
else ""
-- | Start and send.
startAndSendToOmegle :: OmegleState
-> TCPConnection
-> String
-> String
-> IO String
startAndSendToOmegle omegleState c room msg = do
omegle <- readIORef omegleState
case omegle of
Connect oID -> sendToOmegle omegleState msg
NoConnect -> do startOmegle omegleState c room
threadDelay 300000 -- waiting before sending
-- message after connect
startAndSendToOmegle omegleState c room msg
-----------------------------------------------
-- | Check omegle event, sleep and run again.
runOmegleEvents :: OmegleState -> TCPConnection -> String -> IO ()
runOmegleEvents omegleState c room = do
omegle <- readIORef omegleState
case omegle of
NoConnect -> return ()
Connect oID -> do
responce <- getOmegleResponce oID
print responce
case runGetJSON readJSArray responce of
Right (JSArray a) -> do
msgs' <- mapM parseArr a
let msgs = filt msgs'
if null msgs
then return ()
else runXMPP c $ sendGroupchatMessage room msgs
threadDelay 3000000 -- waiting before new loop
runOmegleEvents omegleState c room
_ -> do stopOmegle omegleState
runXMPP c $ sendGroupchatMessage room "[disconnect]"
where
parseArr (JSArray [JSString jscmd, JSString jsmsg])
| pJSStr jscmd "gotMessage" = return $ fromJSString jsmsg
parseArr (JSArray [JSString jscmd, JSString jsmsg])
| pJSStr jscmd "strangerDisconnected" = stopOmegle omegleState >>
return "[disconnect]"
parseArr _ = return ""
pJSStr jsStr = (==) (fromJSString jsStr)
filt = intercalate "\n" . filter (not . null)
-- | Get omegle id.
getNewOmegleID :: IO OmegleID
getNewOmegleID = do
id' <- post "http://omegle.com/start" ""
return $ init $ tail $ id'
-- | Get responce from omegle.
getOmegleResponce :: OmegleID -> IO String
getOmegleResponce oID = post "http://omegle.com/events" ("id="++oID)
-- | Disconnect from omegle.
sendOmegleDisconnect :: OmegleID -> IO String
sendOmegleDisconnect oID = post "http://omegle.com/disconnect" ("id="++oID)
-- | Send msg to omegle.
sendToOmegleID :: OmegleID -> String -> IO String
sendToOmegleID oID msg = let msg' = urlEncode $ encodeString msg
in post "http://omegle.com/send"
("msg="++msg'++"&id="++oID)
-----------------------------------------------
-- | Do post request and return responce body
post :: String -> String -> IO String
post uriStr body =
let uri = maybe nullURI id $ parseURI uriStr
in simpleHTTP (request uri body) >>= getResponseBody
-- | Request construcion.
request :: URI -> String -> Request String
request uri body =
Request { rqURI = uri
, rqMethod = POST
, rqHeaders = [ Header HdrContentLength (show $ length body)
, Header HdrContentType
"application/x-www-form-urlencoded; charset=utf-8"
]
, rqBody = body
}