module Lambdabot.Plugin.Social.Seen.UserStatus where
import Control.Applicative
import Data.Binary
import qualified Data.ByteString as BS
import Data.List
import Lambdabot.Compat.AltTime
import Lambdabot.Compat.PackedNick
import Lambdabot.Plugin.Social.Seen.StopWatch
type Channel = BS.ByteString
type LastSpoke = Maybe (ClockTime, TimeDiff)
data UserStatus
= Present !LastSpoke [Channel]
| NotPresent !ClockTime !StopWatch [Channel]
| WasPresent !ClockTime !StopWatch !LastSpoke [Channel]
| NewNick !PackedNick
deriving (Int -> UserStatus -> ShowS
[UserStatus] -> ShowS
UserStatus -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [UserStatus] -> ShowS
$cshowList :: [UserStatus] -> ShowS
show :: UserStatus -> String
$cshow :: UserStatus -> String
showsPrec :: Int -> UserStatus -> ShowS
$cshowsPrec :: Int -> UserStatus -> ShowS
Show, ReadPrec [UserStatus]
ReadPrec UserStatus
Int -> ReadS UserStatus
ReadS [UserStatus]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [UserStatus]
$creadListPrec :: ReadPrec [UserStatus]
readPrec :: ReadPrec UserStatus
$creadPrec :: ReadPrec UserStatus
readList :: ReadS [UserStatus]
$creadList :: ReadS [UserStatus]
readsPrec :: Int -> ReadS UserStatus
$creadsPrec :: Int -> ReadS UserStatus
Read)
instance Binary UserStatus where
put :: UserStatus -> Put
put (Present LastSpoke
sp [Channel]
ch) = Word8 -> Put
putWord8 Word8
0 forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall t. Binary t => t -> Put
put LastSpoke
sp forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall t. Binary t => t -> Put
put [Channel]
ch
put (NotPresent ClockTime
ct StopWatch
sw [Channel]
ch) = Word8 -> Put
putWord8 Word8
1 forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall t. Binary t => t -> Put
put ClockTime
ct forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall t. Binary t => t -> Put
put StopWatch
sw forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall t. Binary t => t -> Put
put [Channel]
ch
put (WasPresent ClockTime
ct StopWatch
sw LastSpoke
sp [Channel]
ch) = Word8 -> Put
putWord8 Word8
2 forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall t. Binary t => t -> Put
put ClockTime
ct forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall t. Binary t => t -> Put
put StopWatch
sw forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall t. Binary t => t -> Put
put LastSpoke
sp forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall t. Binary t => t -> Put
put [Channel]
ch
put (NewNick Channel
n) = Word8 -> Put
putWord8 Word8
3 forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall t. Binary t => t -> Put
put Channel
n
get :: Get UserStatus
get = Get Word8
getWord8 forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Word8
h -> case Word8
h of
Word8
0 -> LastSpoke -> [Channel] -> UserStatus
Present forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall t. Binary t => Get t
get forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall t. Binary t => Get t
get
Word8
1 -> ClockTime -> StopWatch -> [Channel] -> UserStatus
NotPresent forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall t. Binary t => Get t
get forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall t. Binary t => Get t
get forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall t. Binary t => Get t
get
Word8
2 -> ClockTime -> StopWatch -> LastSpoke -> [Channel] -> UserStatus
WasPresent forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall t. Binary t => Get t
get forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall t. Binary t => Get t
get forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall t. Binary t => Get t
get forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall t. Binary t => Get t
get
Word8
3 -> Channel -> UserStatus
NewNick forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall t. Binary t => Get t
get
Word8
_ -> forall a. HasCallStack => String -> a
error String
"Seen.UserStatus.get"
updateJ :: Maybe ClockTime
-> [Channel]
-> UserStatus
-> UserStatus
updateJ :: Maybe ClockTime -> [Channel] -> UserStatus -> UserStatus
updateJ Maybe ClockTime
_ [Channel]
c (Present LastSpoke
ct [Channel]
cs) = LastSpoke -> [Channel] -> UserStatus
Present LastSpoke
ct forall a b. (a -> b) -> a -> b
$ forall a. Eq a => [a] -> [a]
nub ([Channel]
c forall a. [a] -> [a] -> [a]
++ [Channel]
cs)
updateJ (Just ClockTime
now) [Channel]
cs (WasPresent ClockTime
lastSeen StopWatch
_ (Just (ClockTime
lastSpoke, TimeDiff
missed)) [Channel]
channels)
| forall a. [a] -> a
head [Channel]
channels forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Channel]
cs
= let newMissed :: TimeDiff
newMissed = TimeDiff -> ClockTime -> ClockTime
addToClockTime TimeDiff
missed ClockTime
now ClockTime -> ClockTime -> TimeDiff
`diffClockTimes` ClockTime
lastSeen
in TimeDiff
newMissed seq :: forall a b. a -> b -> b
`seq` LastSpoke -> [Channel] -> UserStatus
Present (forall a. a -> Maybe a
Just (ClockTime
lastSpoke, TimeDiff
newMissed)) [Channel]
cs
updateJ Maybe ClockTime
_ [Channel]
cs UserStatus
_ = LastSpoke -> [Channel] -> UserStatus
Present forall a. Maybe a
Nothing [Channel]
cs
updateNP :: ClockTime -> Channel -> UserStatus -> UserStatus
updateNP :: ClockTime -> Channel -> UserStatus -> UserStatus
updateNP ClockTime
now Channel
_ (NotPresent ClockTime
ct StopWatch
missed [Channel]
c)
= ClockTime -> StopWatch -> [Channel] -> UserStatus
NotPresent ClockTime
ct (ClockTime -> StopWatch -> StopWatch
stopWatch ClockTime
now StopWatch
missed) [Channel]
c
updateNP ClockTime
now Channel
chan (WasPresent ClockTime
lastSeen StopWatch
missed LastSpoke
_ [Channel]
cs)
| forall a. [a] -> a
head [Channel]
cs forall a. Eq a => a -> a -> Bool
== Channel
chan = ClockTime -> StopWatch -> LastSpoke -> [Channel] -> UserStatus
WasPresent ClockTime
lastSeen (ClockTime -> StopWatch -> StopWatch
stopWatch ClockTime
now StopWatch
missed) forall a. Maybe a
Nothing [Channel]
cs
updateNP ClockTime
_ Channel
_ UserStatus
status = UserStatus
status