{-# LANGUAGE OverloadedStrings #-} {-# OPTIONS_HADDOCK prune, not-home #-} -- | Query info about connected Guilds and Channels module Discord.Gateway.Cache where import Prelude hiding (log) import Data.Monoid ((<>)) import Control.Concurrent.MVar import Control.Concurrent.Chan import qualified Data.Map.Strict as M import Discord.Types data Cache = Cache { _currentUser :: User , _dmChannels :: M.Map Snowflake Channel , _guilds :: M.Map Snowflake (Guild, GuildInfo) , _channels :: M.Map Snowflake Channel } deriving (Show) emptyCache :: IO (MVar Cache) emptyCache = newEmptyMVar addEvent :: MVar Cache -> Chan Event -> Chan String -> IO () addEvent cache eventChan log = do ready <- readChan eventChan case ready of (Ready _ user dmChannels _unavailableGuilds _) -> do let dmChans = M.fromList (zip (map channelId dmChannels) dmChannels) putMVar cache (Cache user dmChans M.empty M.empty) loop _ -> do writeChan log ("Cache error - expected Ready, but got " <> show ready) addEvent cache eventChan log where loop :: IO () loop = do event <- readChan eventChan minfo <- takeMVar cache putMVar cache (adjustCache minfo event) loop adjustCache :: Cache -> Event -> Cache adjustCache minfo event = case event of --ChannelCreate Channel --ChannelUpdate Channel --ChannelDelete Channel GuildCreate guild info -> let newChans = map (setChanGuildID (guildId guild)) $ guildChannels info g = M.insert (guildId guild) (guild, info { guildChannels = newChans }) (_guilds minfo) c = M.unionWith (\a _ -> a) (M.fromList [ (channelId ch, ch) | ch <- newChans ]) (_channels minfo) in minfo { _guilds = g, _channels = c } --GuildUpdate guild -> do -- let g = M.insert (guildId guild) guild (_guilds minfo) -- m2 = minfo { _guilds = g } -- putMVar cache m2 --GuildDelete guild -> do -- let g = M.delete (guildId guild) (_guilds minfo) -- c = M.filterWithKey (\(keyGuildId,_) _ -> keyGuildId /= guildId guild) (_channels minfo) -- m2 = minfo { _guilds = g, _channels = c } -- putMVar cache m2 _ -> minfo setChanGuildID :: Snowflake -> Channel -> Channel setChanGuildID s c = if isGuildChannel c then c { channelGuild = s } else c