packages feed

esotericbot-0.0.1: Esotericbot/Chanop.hs

{-# OPTIONS -fglasgow-exts #-}
module Esotericbot.Chanop where

import Data.Attoparsec
import Data.List.Stream as L
import Data.Time
import Data.Map as M
import Data.ByteString.Unsafe

import Control.Concurrent.STM
import Control.Concurrent

import System.IO

import Esotericbot.EBTypes
import Esotericbot.BSH
import Esotericbot.IRCCom
import Esotericbot.BSUtils

op_cmd :: Handle -> Command -> SmallBotM ( )
op_cmd h cmd = do
   sb <- get
   maybe ( do not_in_room <- liftIO $ unsafePackAddressLen 42 "You can't do that unless you're in a room."#
              privmsg h ( irc_user cmd ) not_in_room )
         id
         $ do chan <- irc_chan cmd
              chan_op_search <- M.lookup chan $ searching sb
              return $ known_op_cmd h chan_op_search cmd

-- this is some multiplexing right here boyo
known_op_cmd :: Handle -> TVar ChanOpSearch -> Command -> SmallBotM ( )
known_op_cmd h op_search_var cmd = do
   sb <- get
   let Just chan = irc_chan cmd
       wait_for_end = atomically $ do
         op_search <- readTVar op_search_var
         if done op_search
            then do 
               op_search <- readTVar op_search_var
               let other_threads = threads_waiting op_search - 1
               if other_threads < 1
                  then writeTVar op_search_var initial_op_search
                  else writeTVar op_search_var $ op_search { threads_waiting = other_threads }
               return $ ops op_search
            else do 
               retry
       start_gathering = do
          starting <- liftIO $ atomically $ do op_search <- readTVar op_search_var
                                               if not $ underway op_search
                                                  then do writeTVar op_search_var $ op_search { underway = True }
                                                          return True
                                                  else return False
          request_names <- liftIO $ ls2bs 6 "NAMES "#
          writeMsg h $ request_names `hAppend` chan
          liftIO $ wait_for_end
   -- if the names are being gathered
      -- wait until the end
   -- if the names are not being gathered, start gathering
   op_search <- liftIO $ atomically $ do op_search <- readTVar op_search_var
                                         writeTVar op_search_var $ op_search { threads_waiting = threads_waiting op_search + 1 }
                                         return op_search
   the_ops <- if underway op_search
                 then liftIO $ wait_for_end
                 else start_gathering
   if irc_user cmd `L.elem` the_ops
      then do
         know_better <- liftIO $ ls2bs 27 "Pull yourself together man!"#
         talk <- liftIO $ ls2bs 6 "enable"#
         dont <- liftIO $ ls2bs 7 "disable"#
       
         either ( const $ priv_msg h cmd know_better )
                id
                $ snd $ parse ( op_cmd_p sb h talk dont chan ) $ irc_cmd cmd
      else do
         denied <- liftIO $ ls2bs 3 "HA!"#
         privmsg h chan denied

op_cmd_p sb h talk dont chan = do
   spaces
   try ( do string talk
            return $ do enabled <- liftIO $ ls2bs 7 "Enabled"#
                        enable_bot chan
                        privmsg h chan enabled
       )
       <|> do string dont
              return $ do disabled <- liftIO $ ls2bs 8 "Disabled"#
                          disable_bot chan
                          privmsg h chan disabled

enable_bot chan =
   write_listening chan True

disable_bot chan =
   write_listening chan False

write_listening chan p = do
   sb <- get
   let Just lvar = M.lookup chan $ listening sb
   liftIO $ atomically $ writeTVar lvar p