-- | Permission utilities
module Calamity.Utils.Permissions
    ( basePermissions
    , applyOverwrites
    , PermissionsIn(..)
    , PermissionsIn'(..) ) where

import           Calamity.Client.Types
import           Calamity.Types.Model.Channel.Guild
import           Calamity.Types.Model.Guild.Guild
import           Calamity.Types.Model.Guild.Member
import           Calamity.Types.Model.Guild.Overwrite
import           Calamity.Types.Model.Guild.Permissions
import           Calamity.Types.Model.User
import           Calamity.Types.Snowflake
import           Calamity.Types.Upgradeable

import           Control.Lens

import           Data.Flags
import qualified Data.Vector.Unboxed                    as V

import qualified Polysemy                               as P

-- | Calculate a 'Member''s 'Permissions' in a 'Guild'
basePermissions :: Guild -> Member -> Permissions
basePermissions :: Guild -> Member -> Permissions
basePermissions g :: Guild
g m :: Member
m
  | (Guild
g Guild
-> Getting (Snowflake User) Guild (Snowflake User)
-> Snowflake User
forall s a. s -> Getting a s a -> a
^. IsLabel "ownerID" (Getting (Snowflake User) Guild (Snowflake User))
Getting (Snowflake User) Guild (Snowflake User)
#ownerID Snowflake User -> Snowflake User -> Bool
forall a. Eq a => a -> a -> Bool
== Member -> Snowflake User
forall b a. HasID b a => a -> Snowflake b
getID Member
m) = Permissions
forall α. BoundedFlags α => α
allFlags
  | Bool
otherwise = let everyoneRole :: Maybe Role
everyoneRole  = Guild
g Guild -> Getting (Maybe Role) Guild (Maybe Role) -> Maybe Role
forall s a. s -> Getting a s a -> a
^. IsLabel
  "roles"
  ((SnowflakeMap Role -> Const (Maybe Role) (SnowflakeMap Role))
   -> Guild -> Const (Maybe Role) Guild)
(SnowflakeMap Role -> Const (Maybe Role) (SnowflakeMap Role))
-> Guild -> Const (Maybe Role) Guild
#roles ((SnowflakeMap Role -> Const (Maybe Role) (SnowflakeMap Role))
 -> Guild -> Const (Maybe Role) Guild)
-> ((Maybe Role -> Const (Maybe Role) (Maybe Role))
    -> SnowflakeMap Role -> Const (Maybe Role) (SnowflakeMap Role))
-> Getting (Maybe Role) Guild (Maybe Role)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index (SnowflakeMap Role)
-> Lens' (SnowflakeMap Role) (Maybe (IxValue (SnowflakeMap Role)))
forall m. At m => Index m -> Lens' m (Maybe (IxValue m))
at (Snowflake Guild -> Index (SnowflakeMap Role)
forall a b. Snowflake a -> Snowflake b
coerceSnowflake (Snowflake Guild -> Index (SnowflakeMap Role))
-> Snowflake Guild -> Index (SnowflakeMap Role)
forall a b. (a -> b) -> a -> b
$ Guild -> Snowflake Guild
forall b a. HasID b a => a -> Snowflake b
getID @Guild Guild
g)
                    permsEveryone :: Permissions
permsEveryone = Permissions -> (Role -> Permissions) -> Maybe Role -> Permissions
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Permissions
forall α. Flags α => α
noFlags (Role -> Getting Permissions Role Permissions -> Permissions
forall s a. s -> Getting a s a -> a
^. IsLabel "permissions" (Getting Permissions Role Permissions)
Getting Permissions Role Permissions
#permissions) Maybe Role
everyoneRole
                    rolePerms :: [Permissions]
rolePerms     = Guild
g Guild
-> Getting (Endo [Permissions]) Guild Permissions -> [Permissions]
forall s a. s -> Getting (Endo [a]) s a -> [a]
^.. IsLabel
  "roles"
  ((SnowflakeMap Role
    -> Const (Endo [Permissions]) (SnowflakeMap Role))
   -> Guild -> Const (Endo [Permissions]) Guild)
(SnowflakeMap Role
 -> Const (Endo [Permissions]) (SnowflakeMap Role))
-> Guild -> Const (Endo [Permissions]) Guild
#roles ((SnowflakeMap Role
  -> Const (Endo [Permissions]) (SnowflakeMap Role))
 -> Guild -> Const (Endo [Permissions]) Guild)
-> ((Permissions -> Const (Endo [Permissions]) Permissions)
    -> SnowflakeMap Role
    -> Const (Endo [Permissions]) (SnowflakeMap Role))
-> Getting (Endo [Permissions]) Guild Permissions
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Snowflake Role
 -> (Role -> Const (Endo [Permissions]) Role)
 -> SnowflakeMap Role
 -> Const (Endo [Permissions]) (SnowflakeMap Role))
-> [Snowflake Role]
-> (Role -> Const (Endo [Permissions]) Role)
-> SnowflakeMap Role
-> Const (Endo [Permissions]) (SnowflakeMap Role)
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Snowflake Role
-> (Role -> Const (Endo [Permissions]) Role)
-> SnowflakeMap Role
-> Const (Endo [Permissions]) (SnowflakeMap Role)
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix (Vector (Snowflake Role) -> [Snowflake Role]
forall a. Unbox a => Vector a -> [a]
V.toList (Vector (Snowflake Role) -> [Snowflake Role])
-> Vector (Snowflake Role) -> [Snowflake Role]
forall a b. (a -> b) -> a -> b
$ Member
m Member
-> Getting
     (Vector (Snowflake Role)) Member (Vector (Snowflake Role))
-> Vector (Snowflake Role)
forall s a. s -> Getting a s a -> a
^. IsLabel
  "roles"
  (Getting
     (Vector (Snowflake Role)) Member (Vector (Snowflake Role)))
Getting (Vector (Snowflake Role)) Member (Vector (Snowflake Role))
#roles) ((Role -> Const (Endo [Permissions]) Role)
 -> SnowflakeMap Role
 -> Const (Endo [Permissions]) (SnowflakeMap Role))
-> ((Permissions -> Const (Endo [Permissions]) Permissions)
    -> Role -> Const (Endo [Permissions]) Role)
-> (Permissions -> Const (Endo [Permissions]) Permissions)
-> SnowflakeMap Role
-> Const (Endo [Permissions]) (SnowflakeMap Role)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IsLabel
  "permissions"
  ((Permissions -> Const (Endo [Permissions]) Permissions)
   -> Role -> Const (Endo [Permissions]) Role)
(Permissions -> Const (Endo [Permissions]) Permissions)
-> Role -> Const (Endo [Permissions]) Role
#permissions
                    perms :: Permissions
perms         = (Permissions -> Permissions -> Permissions)
-> Permissions -> [Permissions] -> Permissions
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl Permissions -> Permissions -> Permissions
forall α. Flags α => α -> α -> α
andFlags Permissions
forall α. Flags α => α
noFlags (Permissions
permsEveryonePermissions -> [Permissions] -> [Permissions]
forall a. a -> [a] -> [a]
:[Permissions]
rolePerms)
                in if Permissions
perms Permissions -> Permissions -> Bool
forall α. Flags α => α -> α -> Bool
.<=. Permissions
administrator
                   then Permissions
forall α. BoundedFlags α => α
allFlags
                   else Permissions
perms

-- | Apply any 'Overwrite's for a 'GuildChannel' onto some 'Permissions'
applyOverwrites :: GuildChannel -> Member -> Permissions -> Permissions
applyOverwrites :: GuildChannel -> Member -> Permissions -> Permissions
applyOverwrites c :: GuildChannel
c m :: Member
m p :: Permissions
p
  | Permissions
p Permissions -> Permissions -> Bool
forall α. Flags α => α -> α -> Bool
.<=. Permissions
administrator = Permissions
forall α. BoundedFlags α => α
allFlags
  | Bool
otherwise =
    let everyoneOverwrite :: Maybe Overwrite
everyoneOverwrite = GuildChannel
c GuildChannel
-> Getting (Maybe Overwrite) GuildChannel (Maybe Overwrite)
-> Maybe Overwrite
forall s a. s -> Getting a s a -> a
^. IsLabel
  "permissionOverwrites"
  ((SnowflakeMap Overwrite
    -> Const (Maybe Overwrite) (SnowflakeMap Overwrite))
   -> GuildChannel -> Const (Maybe Overwrite) GuildChannel)
(SnowflakeMap Overwrite
 -> Const (Maybe Overwrite) (SnowflakeMap Overwrite))
-> GuildChannel -> Const (Maybe Overwrite) GuildChannel
#permissionOverwrites ((SnowflakeMap Overwrite
  -> Const (Maybe Overwrite) (SnowflakeMap Overwrite))
 -> GuildChannel -> Const (Maybe Overwrite) GuildChannel)
-> ((Maybe Overwrite -> Const (Maybe Overwrite) (Maybe Overwrite))
    -> SnowflakeMap Overwrite
    -> Const (Maybe Overwrite) (SnowflakeMap Overwrite))
-> Getting (Maybe Overwrite) GuildChannel (Maybe Overwrite)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index (SnowflakeMap Overwrite)
-> Lens'
     (SnowflakeMap Overwrite) (Maybe (IxValue (SnowflakeMap Overwrite)))
forall m. At m => Index m -> Lens' m (Maybe (IxValue m))
at (Snowflake Guild -> Index (SnowflakeMap Overwrite)
forall a b. Snowflake a -> Snowflake b
coerceSnowflake (Snowflake Guild -> Index (SnowflakeMap Overwrite))
-> Snowflake Guild -> Index (SnowflakeMap Overwrite)
forall a b. (a -> b) -> a -> b
$ GuildChannel -> Snowflake Guild
forall b a. HasID b a => a -> Snowflake b
getID @Guild GuildChannel
c)
        everyoneAllow :: Permissions
everyoneAllow     = Permissions
-> (Overwrite -> Permissions) -> Maybe Overwrite -> Permissions
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Permissions
forall α. Flags α => α
noFlags (Overwrite
-> Getting Permissions Overwrite Permissions -> Permissions
forall s a. s -> Getting a s a -> a
^. IsLabel "allow" (Getting Permissions Overwrite Permissions)
Getting Permissions Overwrite Permissions
#allow) Maybe Overwrite
everyoneOverwrite
        everyoneDeny :: Permissions
everyoneDeny      = Permissions
-> (Overwrite -> Permissions) -> Maybe Overwrite -> Permissions
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Permissions
forall α. Flags α => α
noFlags (Overwrite
-> Getting Permissions Overwrite Permissions -> Permissions
forall s a. s -> Getting a s a -> a
^. IsLabel "deny" (Getting Permissions Overwrite Permissions)
Getting Permissions Overwrite Permissions
#deny) Maybe Overwrite
everyoneOverwrite
        p' :: Permissions
p'                = Permissions
p Permissions -> Permissions -> Permissions
forall α. Flags α => α -> α -> α
.-. Permissions
everyoneDeny Permissions -> Permissions -> Permissions
forall α. Flags α => α -> α -> α
.+. Permissions
everyoneAllow
        roleOverwrites :: [Overwrite]
roleOverwrites    = GuildChannel
c GuildChannel
-> Getting (Endo [Overwrite]) GuildChannel Overwrite -> [Overwrite]
forall s a. s -> Getting (Endo [a]) s a -> [a]
^.. IsLabel
  "permissionOverwrites"
  ((SnowflakeMap Overwrite
    -> Const (Endo [Overwrite]) (SnowflakeMap Overwrite))
   -> GuildChannel -> Const (Endo [Overwrite]) GuildChannel)
(SnowflakeMap Overwrite
 -> Const (Endo [Overwrite]) (SnowflakeMap Overwrite))
-> GuildChannel -> Const (Endo [Overwrite]) GuildChannel
#permissionOverwrites ((SnowflakeMap Overwrite
  -> Const (Endo [Overwrite]) (SnowflakeMap Overwrite))
 -> GuildChannel -> Const (Endo [Overwrite]) GuildChannel)
-> ((Overwrite -> Const (Endo [Overwrite]) Overwrite)
    -> SnowflakeMap Overwrite
    -> Const (Endo [Overwrite]) (SnowflakeMap Overwrite))
-> Getting (Endo [Overwrite]) GuildChannel Overwrite
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Snowflake Overwrite
 -> (Overwrite -> Const (Endo [Overwrite]) Overwrite)
 -> SnowflakeMap Overwrite
 -> Const (Endo [Overwrite]) (SnowflakeMap Overwrite))
-> [Snowflake Overwrite]
-> (Overwrite -> Const (Endo [Overwrite]) Overwrite)
-> SnowflakeMap Overwrite
-> Const (Endo [Overwrite]) (SnowflakeMap Overwrite)
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Snowflake Overwrite
-> (Overwrite -> Const (Endo [Overwrite]) Overwrite)
-> SnowflakeMap Overwrite
-> Const (Endo [Overwrite]) (SnowflakeMap Overwrite)
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix
          ((Snowflake Role -> Snowflake Overwrite)
-> [Snowflake Role] -> [Snowflake Overwrite]
forall a b. (a -> b) -> [a] -> [b]
map (Snowflake Role -> Snowflake Overwrite
forall a b. Snowflake a -> Snowflake b
coerceSnowflake @_ @Overwrite) ([Snowflake Role] -> [Snowflake Overwrite])
-> (Vector (Snowflake Role) -> [Snowflake Role])
-> Vector (Snowflake Role)
-> [Snowflake Overwrite]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector (Snowflake Role) -> [Snowflake Role]
forall a. Unbox a => Vector a -> [a]
V.toList (Vector (Snowflake Role) -> [Snowflake Overwrite])
-> Vector (Snowflake Role) -> [Snowflake Overwrite]
forall a b. (a -> b) -> a -> b
$ Member
m Member
-> Getting
     (Vector (Snowflake Role)) Member (Vector (Snowflake Role))
-> Vector (Snowflake Role)
forall s a. s -> Getting a s a -> a
^. IsLabel
  "roles"
  (Getting
     (Vector (Snowflake Role)) Member (Vector (Snowflake Role)))
Getting (Vector (Snowflake Role)) Member (Vector (Snowflake Role))
#roles)
        roleAllow :: Permissions
roleAllow         = (Permissions -> Permissions -> Permissions)
-> Permissions -> [Permissions] -> Permissions
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl Permissions -> Permissions -> Permissions
forall α. Flags α => α -> α -> α
andFlags Permissions
forall α. Flags α => α
noFlags ([Overwrite]
roleOverwrites [Overwrite]
-> Getting (Endo [Permissions]) [Overwrite] Permissions
-> [Permissions]
forall s a. s -> Getting (Endo [a]) s a -> [a]
^.. (Overwrite -> Const (Endo [Permissions]) Overwrite)
-> [Overwrite] -> Const (Endo [Permissions]) [Overwrite]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse ((Overwrite -> Const (Endo [Permissions]) Overwrite)
 -> [Overwrite] -> Const (Endo [Permissions]) [Overwrite])
-> ((Permissions -> Const (Endo [Permissions]) Permissions)
    -> Overwrite -> Const (Endo [Permissions]) Overwrite)
-> Getting (Endo [Permissions]) [Overwrite] Permissions
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IsLabel
  "allow"
  ((Permissions -> Const (Endo [Permissions]) Permissions)
   -> Overwrite -> Const (Endo [Permissions]) Overwrite)
(Permissions -> Const (Endo [Permissions]) Permissions)
-> Overwrite -> Const (Endo [Permissions]) Overwrite
#allow)
        roleDeny :: Permissions
roleDeny          = (Permissions -> Permissions -> Permissions)
-> Permissions -> [Permissions] -> Permissions
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl Permissions -> Permissions -> Permissions
forall α. Flags α => α -> α -> α
andFlags Permissions
forall α. Flags α => α
noFlags ([Overwrite]
roleOverwrites [Overwrite]
-> Getting (Endo [Permissions]) [Overwrite] Permissions
-> [Permissions]
forall s a. s -> Getting (Endo [a]) s a -> [a]
^.. (Overwrite -> Const (Endo [Permissions]) Overwrite)
-> [Overwrite] -> Const (Endo [Permissions]) [Overwrite]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse ((Overwrite -> Const (Endo [Permissions]) Overwrite)
 -> [Overwrite] -> Const (Endo [Permissions]) [Overwrite])
-> ((Permissions -> Const (Endo [Permissions]) Permissions)
    -> Overwrite -> Const (Endo [Permissions]) Overwrite)
-> Getting (Endo [Permissions]) [Overwrite] Permissions
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IsLabel
  "deny"
  ((Permissions -> Const (Endo [Permissions]) Permissions)
   -> Overwrite -> Const (Endo [Permissions]) Overwrite)
(Permissions -> Const (Endo [Permissions]) Permissions)
-> Overwrite -> Const (Endo [Permissions]) Overwrite
#deny)
        p'' :: Permissions
p''               = Permissions
p' Permissions -> Permissions -> Permissions
forall α. Flags α => α -> α -> α
.-. Permissions
roleDeny Permissions -> Permissions -> Permissions
forall α. Flags α => α -> α -> α
.+. Permissions
roleAllow
        memberOverwrite :: Maybe Overwrite
memberOverwrite   = GuildChannel
c GuildChannel
-> Getting (Maybe Overwrite) GuildChannel (Maybe Overwrite)
-> Maybe Overwrite
forall s a. s -> Getting a s a -> a
^. IsLabel
  "permissionOverwrites"
  ((SnowflakeMap Overwrite
    -> Const (Maybe Overwrite) (SnowflakeMap Overwrite))
   -> GuildChannel -> Const (Maybe Overwrite) GuildChannel)
(SnowflakeMap Overwrite
 -> Const (Maybe Overwrite) (SnowflakeMap Overwrite))
-> GuildChannel -> Const (Maybe Overwrite) GuildChannel
#permissionOverwrites ((SnowflakeMap Overwrite
  -> Const (Maybe Overwrite) (SnowflakeMap Overwrite))
 -> GuildChannel -> Const (Maybe Overwrite) GuildChannel)
-> ((Maybe Overwrite -> Const (Maybe Overwrite) (Maybe Overwrite))
    -> SnowflakeMap Overwrite
    -> Const (Maybe Overwrite) (SnowflakeMap Overwrite))
-> Getting (Maybe Overwrite) GuildChannel (Maybe Overwrite)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index (SnowflakeMap Overwrite)
-> Lens'
     (SnowflakeMap Overwrite) (Maybe (IxValue (SnowflakeMap Overwrite)))
forall m. At m => Index m -> Lens' m (Maybe (IxValue m))
at (Snowflake Member -> Snowflake Overwrite
forall a b. Snowflake a -> Snowflake b
coerceSnowflake @_ @Overwrite (Snowflake Member -> Index (SnowflakeMap Overwrite))
-> Snowflake Member -> Index (SnowflakeMap Overwrite)
forall a b. (a -> b) -> a -> b
$ Member -> Snowflake Member
forall b a. HasID b a => a -> Snowflake b
getID @Member Member
m)
        memberAllow :: Permissions
memberAllow       = Permissions
-> (Overwrite -> Permissions) -> Maybe Overwrite -> Permissions
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Permissions
forall α. Flags α => α
noFlags (Overwrite
-> Getting Permissions Overwrite Permissions -> Permissions
forall s a. s -> Getting a s a -> a
^. IsLabel "allow" (Getting Permissions Overwrite Permissions)
Getting Permissions Overwrite Permissions
#allow) Maybe Overwrite
memberOverwrite
        memberDeny :: Permissions
memberDeny        = Permissions
-> (Overwrite -> Permissions) -> Maybe Overwrite -> Permissions
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Permissions
forall α. Flags α => α
noFlags (Overwrite
-> Getting Permissions Overwrite Permissions -> Permissions
forall s a. s -> Getting a s a -> a
^. IsLabel "deny" (Getting Permissions Overwrite Permissions)
Getting Permissions Overwrite Permissions
#deny) Maybe Overwrite
memberOverwrite
        p''' :: Permissions
p'''              = Permissions
p'' Permissions -> Permissions -> Permissions
forall α. Flags α => α -> α -> α
.-. Permissions
memberDeny Permissions -> Permissions -> Permissions
forall α. Flags α => α -> α -> α
.+. Permissions
memberAllow
    in Permissions
p'''

-- | Things that 'Member's have 'Permissions' in
class PermissionsIn a where
  -- | Calculate a 'Member''s 'Permissions' in something
  permissionsIn :: a -> Member -> Permissions

-- | A 'Member''s 'Permissions' in a channel are their roles and overwrites
instance PermissionsIn (Guild, GuildChannel) where
  permissionsIn :: (Guild, GuildChannel) -> Member -> Permissions
permissionsIn (g :: Guild
g, c :: GuildChannel
c) m :: Member
m = GuildChannel -> Member -> Permissions -> Permissions
applyOverwrites GuildChannel
c Member
m (Permissions -> Permissions) -> Permissions -> Permissions
forall a b. (a -> b) -> a -> b
$ Guild -> Member -> Permissions
basePermissions Guild
g Member
m

-- | A 'Member''s 'Permissions' in a guild are just their roles
instance PermissionsIn Guild where
  permissionsIn :: Guild -> Member -> Permissions
permissionsIn g :: Guild
g m :: Member
m = Guild -> Member -> Permissions
basePermissions Guild
g Member
m

-- | A variant of 'PermissionsIn' that will use the cache/http.
class PermissionsIn' a where
  -- | Calculate the permissions of something that has a 'User' id
  --
  -- If permissions could not be calculated because something couldn't be found
  -- in the cache, this will return an empty set of permissions. Use
  -- 'permissionsIn' if you want to handle cases where something might not exist
  -- in cache.
  permissionsIn' :: (BotC r, HasID User u) => a -> u -> P.Sem r Permissions

-- | A 'User''s 'Permissions' in a channel are their roles and overwrites
--
-- This will fetch the guild from the cache or http as needed
instance PermissionsIn' GuildChannel where
  permissionsIn' :: GuildChannel -> u -> Sem r Permissions
permissionsIn' c :: GuildChannel
c (forall a. HasID User a => a -> Snowflake User
forall b a. HasID b a => a -> Snowflake b
getID @User -> Snowflake User
uid) = do
    Maybe Member
m <- (Snowflake Guild, Snowflake Member) -> Sem r (Maybe Member)
forall a ids (r :: [(* -> *) -> * -> *]).
(Upgradeable a ids, BotC r) =>
ids -> Sem r (Maybe a)
upgrade (GuildChannel -> Snowflake Guild
forall b a. HasID b a => a -> Snowflake b
getID @Guild GuildChannel
c, Snowflake User -> Snowflake Member
forall a b. Snowflake a -> Snowflake b
coerceSnowflake @_ @Member Snowflake User
uid)
    Maybe Guild
g <- Snowflake Guild -> Sem r (Maybe Guild)
forall a ids (r :: [(* -> *) -> * -> *]).
(Upgradeable a ids, BotC r) =>
ids -> Sem r (Maybe a)
upgrade (GuildChannel -> Snowflake Guild
forall b a. HasID b a => a -> Snowflake b
getID @Guild GuildChannel
c)
    case (Maybe Member
m, Maybe Guild
g) of
      (Just m :: Member
m, Just g' :: Guild
g') -> Permissions -> Sem r Permissions
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Permissions -> Sem r Permissions)
-> Permissions -> Sem r Permissions
forall a b. (a -> b) -> a -> b
$ (Guild, GuildChannel) -> Member -> Permissions
forall a. PermissionsIn a => a -> Member -> Permissions
permissionsIn (Guild
g', GuildChannel
c) Member
m
      _                 -> Permissions -> Sem r Permissions
forall (f :: * -> *) a. Applicative f => a -> f a
pure Permissions
forall α. Flags α => α
noFlags

-- | A 'Member''s 'Permissions' in a guild are just their roles
instance PermissionsIn' Guild where
  permissionsIn' :: Guild -> u -> Sem r Permissions
permissionsIn' g :: Guild
g (forall a. HasID User a => a -> Snowflake User
forall b a. HasID b a => a -> Snowflake b
getID @User -> Snowflake User
uid) = do
    Maybe Member
m <- (Snowflake Guild, Snowflake Member) -> Sem r (Maybe Member)
forall a ids (r :: [(* -> *) -> * -> *]).
(Upgradeable a ids, BotC r) =>
ids -> Sem r (Maybe a)
upgrade (Guild -> Snowflake Guild
forall b a. HasID b a => a -> Snowflake b
getID @Guild Guild
g, Snowflake User -> Snowflake Member
forall a b. Snowflake a -> Snowflake b
coerceSnowflake @_ @Member Snowflake User
uid)
    case Maybe Member
m of
      Just m' :: Member
m' -> Permissions -> Sem r Permissions
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Permissions -> Sem r Permissions)
-> Permissions -> Sem r Permissions
forall a b. (a -> b) -> a -> b
$ Guild -> Member -> Permissions
forall a. PermissionsIn a => a -> Member -> Permissions
permissionsIn Guild
g Member
m'
      Nothing -> Permissions -> Sem r Permissions
forall (f :: * -> *) a. Applicative f => a -> f a
pure Permissions
forall α. Flags α => α
noFlags

-- | A 'Member''s 'Permissions' in a channel are their roles and overwrites
--
-- This will fetch the guild and channel from the cache or http as needed
instance PermissionsIn' (Snowflake GuildChannel) where
  permissionsIn' :: Snowflake GuildChannel -> u -> Sem r Permissions
permissionsIn' cid :: Snowflake GuildChannel
cid u :: u
u = do
    Maybe GuildChannel
c <- Snowflake GuildChannel -> Sem r (Maybe GuildChannel)
forall a ids (r :: [(* -> *) -> * -> *]).
(Upgradeable a ids, BotC r) =>
ids -> Sem r (Maybe a)
upgrade Snowflake GuildChannel
cid
    case Maybe GuildChannel
c of
      Just c' :: GuildChannel
c' -> GuildChannel -> u -> Sem r Permissions
forall a (r :: [(* -> *) -> * -> *]) u.
(PermissionsIn' a, BotC r, HasID User u) =>
a -> u -> Sem r Permissions
permissionsIn' GuildChannel
c' u
u
      _       -> Permissions -> Sem r Permissions
forall (f :: * -> *) a. Applicative f => a -> f a
pure Permissions
forall α. Flags α => α
noFlags

-- | A 'Member''s 'Permissions' in a guild are just their roles
--
-- This will fetch the guild from the cache or http as needed
instance PermissionsIn' (Snowflake Guild) where
  permissionsIn' :: Snowflake Guild -> u -> Sem r Permissions
permissionsIn' gid :: Snowflake Guild
gid u :: u
u = do
    Maybe Guild
g <- Snowflake Guild -> Sem r (Maybe Guild)
forall a ids (r :: [(* -> *) -> * -> *]).
(Upgradeable a ids, BotC r) =>
ids -> Sem r (Maybe a)
upgrade Snowflake Guild
gid
    case Maybe Guild
g of
      Just g' :: Guild
g' -> Guild -> u -> Sem r Permissions
forall a (r :: [(* -> *) -> * -> *]) u.
(PermissionsIn' a, BotC r, HasID User u) =>
a -> u -> Sem r Permissions
permissionsIn' Guild
g' u
u
      Nothing -> Permissions -> Sem r Permissions
forall (f :: * -> *) a. Applicative f => a -> f a
pure Permissions
forall α. Flags α => α
noFlags