mattermost-api 40400.0.0 → 40600.0.0
raw patch · 21 files changed
+5739/−209 lines, 21 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Network.Mattermost: instance Network.Stream.Stream Network.Connection.Types.Connection
- Network.Mattermost.Types: millisecondsToUTCTime :: Integer -> UTCTime
- Network.Mattermost.Types: utcTimeToMilliseconds :: UTCTime -> Int
+ Network.Mattermost: [minChannelTeamId] :: MinChannel -> TeamId
+ Network.Mattermost: [minComTeamId] :: MinCommand -> TeamId
+ Network.Mattermost: [postEditAt] :: Post -> ServerTime
+ Network.Mattermost: mmGetClientConfig :: Session -> IO Value
+ Network.Mattermost.Endpoints: FlaggedPostsQuery :: Maybe Int -> Maybe Int -> Maybe TeamId -> Maybe ChannelId -> FlaggedPostsQuery
+ Network.Mattermost.Endpoints: PostQuery :: Maybe Int -> Maybe Int -> Maybe UTCTime -> Maybe PostId -> Maybe PostId -> PostQuery
+ Network.Mattermost.Endpoints: UserQuery :: Maybe Int -> Maybe Int -> Maybe TeamId -> Maybe TeamId -> Maybe ChannelId -> Maybe ChannelId -> Maybe Bool -> Maybe UserQuerySort -> UserQuery
+ Network.Mattermost.Endpoints: UserQuerySortByCreation :: UserQuerySort
+ Network.Mattermost.Endpoints: UserQuerySortByLastActivity :: UserQuerySort
+ Network.Mattermost.Endpoints: [flaggedPostsQueryChannelId] :: FlaggedPostsQuery -> Maybe ChannelId
+ Network.Mattermost.Endpoints: [flaggedPostsQueryPage] :: FlaggedPostsQuery -> Maybe Int
+ Network.Mattermost.Endpoints: [flaggedPostsQueryPerPage] :: FlaggedPostsQuery -> Maybe Int
+ Network.Mattermost.Endpoints: [flaggedPostsQueryTeamId] :: FlaggedPostsQuery -> Maybe TeamId
+ Network.Mattermost.Endpoints: [postQueryAfter] :: PostQuery -> Maybe PostId
+ Network.Mattermost.Endpoints: [postQueryBefore] :: PostQuery -> Maybe PostId
+ Network.Mattermost.Endpoints: [postQueryPage] :: PostQuery -> Maybe Int
+ Network.Mattermost.Endpoints: [postQueryPerPage] :: PostQuery -> Maybe Int
+ Network.Mattermost.Endpoints: [postQuerySince] :: PostQuery -> Maybe UTCTime
+ Network.Mattermost.Endpoints: [userQueryInChannel] :: UserQuery -> Maybe ChannelId
+ Network.Mattermost.Endpoints: [userQueryInTeam] :: UserQuery -> Maybe TeamId
+ Network.Mattermost.Endpoints: [userQueryNotInChannel] :: UserQuery -> Maybe ChannelId
+ Network.Mattermost.Endpoints: [userQueryNotInTeam] :: UserQuery -> Maybe TeamId
+ Network.Mattermost.Endpoints: [userQueryPage] :: UserQuery -> Maybe Int
+ Network.Mattermost.Endpoints: [userQueryPerPage] :: UserQuery -> Maybe Int
+ Network.Mattermost.Endpoints: [userQuerySort] :: UserQuery -> Maybe UserQuerySort
+ Network.Mattermost.Endpoints: [userQueryWithoutTeam] :: UserQuery -> Maybe Bool
+ Network.Mattermost.Endpoints: data FlaggedPostsQuery
+ Network.Mattermost.Endpoints: data PostQuery
+ Network.Mattermost.Endpoints: data UserQuery
+ Network.Mattermost.Endpoints: data UserQuerySort
+ Network.Mattermost.Endpoints: defaultFlaggedPostsQuery :: FlaggedPostsQuery
+ Network.Mattermost.Endpoints: defaultPostQuery :: PostQuery
+ Network.Mattermost.Endpoints: defaultUserQuery :: UserQuery
+ Network.Mattermost.Endpoints: getUserStatusesByIds :: Seq UserId -> Session -> IO (HashMap UserId Text)
+ Network.Mattermost.Endpoints: mmAddUser :: ChannelId -> MinChannelMember -> Session -> IO ChannelMember
+ Network.Mattermost.Endpoints: mmAddUserToTeam :: TeamId -> TeamMember -> Session -> IO TeamMember
+ Network.Mattermost.Endpoints: mmCreateChannel :: MinChannel -> Session -> IO Channel
+ Network.Mattermost.Endpoints: mmCreateDirectMessageChannel :: (UserId, UserId) -> Session -> IO Channel
+ Network.Mattermost.Endpoints: mmCreateGroupMessageChannel :: Seq UserId -> Session -> IO Channel
+ Network.Mattermost.Endpoints: mmCreatePost :: RawPost -> Session -> IO Post
+ Network.Mattermost.Endpoints: mmCreateTeam :: TeamsCreate -> Session -> IO Team
+ Network.Mattermost.Endpoints: mmCreateUser :: UsersCreate -> Session -> IO User
+ Network.Mattermost.Endpoints: mmDeactivateUserAccount :: UserParam -> Session -> IO ()
+ Network.Mattermost.Endpoints: mmDeleteChannel :: ChannelId -> Session -> IO ()
+ Network.Mattermost.Endpoints: mmDeletePost :: PostId -> Session -> IO ()
+ Network.Mattermost.Endpoints: mmDeleteUsersPreferences :: UserParam -> (Seq Preference) -> Session -> IO ()
+ Network.Mattermost.Endpoints: mmExecuteCommand :: MinCommand -> Session -> IO CommandResponse
+ Network.Mattermost.Endpoints: mmFlagPost :: UserId -> PostId -> Session -> IO ()
+ Network.Mattermost.Endpoints: mmGetChannel :: ChannelId -> Session -> IO Channel
+ Network.Mattermost.Endpoints: mmGetChannelByName :: TeamId -> Text -> Session -> IO Channel
+ Network.Mattermost.Endpoints: mmGetChannelMember :: ChannelId -> UserParam -> Session -> IO ChannelMember
+ Network.Mattermost.Endpoints: mmGetChannelMembersForUser :: UserParam -> TeamId -> Session -> IO (Seq ChannelMember)
+ Network.Mattermost.Endpoints: mmGetChannelStatistics :: ChannelId -> Session -> IO ChannelStats
+ Network.Mattermost.Endpoints: mmGetChannelsForUser :: UserParam -> TeamId -> Session -> IO (Seq Channel)
+ Network.Mattermost.Endpoints: mmGetClientConfiguration :: Maybe Text -> Session -> IO ClientConfig
+ Network.Mattermost.Endpoints: mmGetConfiguration :: Session -> IO ServerConfig
+ Network.Mattermost.Endpoints: mmGetFile :: FileId -> Session -> IO ByteString
+ Network.Mattermost.Endpoints: mmGetListOfChannelsByIds :: TeamId -> Seq ChannelId -> Session -> IO (Seq Channel)
+ Network.Mattermost.Endpoints: mmGetListOfFlaggedPosts :: UserParam -> FlaggedPostsQuery -> Session -> IO Posts
+ Network.Mattermost.Endpoints: mmGetMetadataForFile :: FileId -> Session -> IO FileInfo
+ Network.Mattermost.Endpoints: mmGetPost :: PostId -> Session -> IO Post
+ Network.Mattermost.Endpoints: mmGetPostsForChannel :: ChannelId -> PostQuery -> Session -> IO Posts
+ Network.Mattermost.Endpoints: mmGetPublicChannels :: TeamId -> Maybe Int -> Maybe Int -> Session -> IO (Seq Channel)
+ Network.Mattermost.Endpoints: mmGetReactionsForPost :: PostId -> Session -> IO (Seq Reaction)
+ Network.Mattermost.Endpoints: mmGetSpecificUserPreference :: UserParam -> Text -> Text -> Session -> IO Preference
+ Network.Mattermost.Endpoints: mmGetTeam :: TeamId -> Session -> IO Team
+ Network.Mattermost.Endpoints: mmGetTeamByName :: Text -> Session -> IO Team
+ Network.Mattermost.Endpoints: mmGetTeamMember :: TeamId -> UserParam -> Session -> IO TeamMember
+ Network.Mattermost.Endpoints: mmGetTeamMembersByIds :: TeamId -> Seq UserId -> Session -> IO (Seq TeamMember)
+ Network.Mattermost.Endpoints: mmGetTeamMembersForUser :: UserParam -> Session -> IO (Seq TeamMember)
+ Network.Mattermost.Endpoints: mmGetTeams :: Maybe Integer -> Maybe Integer -> Session -> IO (Seq Team)
+ Network.Mattermost.Endpoints: mmGetThread :: PostId -> Session -> IO Posts
+ Network.Mattermost.Endpoints: mmGetUnreadMessages :: UserParam -> ChannelId -> Session -> IO ChannelUnread
+ Network.Mattermost.Endpoints: mmGetUser :: UserParam -> Session -> IO User
+ Network.Mattermost.Endpoints: mmGetUserStatus :: UserParam -> Session -> IO Text
+ Network.Mattermost.Endpoints: mmGetUserStatusByIds :: Seq UserId -> Session -> IO (Seq Status)
+ Network.Mattermost.Endpoints: mmGetUsers :: UserQuery -> Session -> IO (Seq User)
+ Network.Mattermost.Endpoints: mmGetUsersByUsernames :: (Seq Text) -> Session -> IO (Seq User)
+ Network.Mattermost.Endpoints: mmGetUsersPreferences :: UserParam -> Session -> IO (Seq Preference)
+ Network.Mattermost.Endpoints: mmGetUsersTeams :: UserParam -> Session -> IO (Seq Team)
+ Network.Mattermost.Endpoints: mmInitialUser :: ConnectionData -> UsersCreate -> IO User
+ Network.Mattermost.Endpoints: mmListUsersPreferencesByCategory :: UserParam -> Text -> Session -> IO (Seq Preference)
+ Network.Mattermost.Endpoints: mmLogin :: ConnectionData -> Login -> IO (Either LoginFailureException (Session, User))
+ Network.Mattermost.Endpoints: mmPatchChannel :: ChannelId -> ChannelPatch -> Session -> IO Channel
+ Network.Mattermost.Endpoints: mmRemoveUserFromChannel :: ChannelId -> UserParam -> Session -> IO ()
+ Network.Mattermost.Endpoints: mmRemoveUserFromTeam :: TeamId -> UserParam -> Session -> IO ()
+ Network.Mattermost.Endpoints: mmSaveUsersPreferences :: UserParam -> (Seq Preference) -> Session -> IO ()
+ Network.Mattermost.Endpoints: mmSearchChannels :: TeamId -> Text -> Session -> IO (Seq Channel)
+ Network.Mattermost.Endpoints: mmSearchForTeamPosts :: TeamId -> SearchPosts -> Session -> IO Posts
+ Network.Mattermost.Endpoints: mmSearchTeams :: Text -> Session -> IO (Seq Team)
+ Network.Mattermost.Endpoints: mmSearchUsers :: UserSearch -> Session -> IO (Seq User)
+ Network.Mattermost.Endpoints: mmUnflagPost :: UserId -> PostId -> Session -> IO ()
+ Network.Mattermost.Endpoints: mmUpdateConfiguration :: ServerConfig -> Session -> IO ServerConfig
+ Network.Mattermost.Endpoints: mmUpdatePost :: PostId -> PostUpdate -> Session -> IO Post
+ Network.Mattermost.Endpoints: mmUpdateUsersRoles :: UserId -> Text -> Session -> IO ()
+ Network.Mattermost.Endpoints: mmViewChannel :: UserParam -> ChannelId -> Maybe ChannelId -> Session -> IO ()
+ Network.Mattermost.Endpoints: postQueryToQueryString :: PostQuery -> String
+ Network.Mattermost.Endpoints: userQueryToQueryString :: UserQuery -> String
+ Network.Mattermost.Exceptions: MattermostError :: Text -> Text -> Text -> Int -> Bool -> MattermostError
+ Network.Mattermost.Exceptions: [mattermostErrorId] :: MattermostError -> Text
+ Network.Mattermost.Exceptions: [mattermostErrorIsOAuth] :: MattermostError -> Bool
+ Network.Mattermost.Exceptions: [mattermostErrorMessage] :: MattermostError -> Text
+ Network.Mattermost.Exceptions: [mattermostErrorRequestId] :: MattermostError -> Text
+ Network.Mattermost.Exceptions: [mattermostErrorStatusCode] :: MattermostError -> Int
+ Network.Mattermost.Exceptions: data MattermostError
+ Network.Mattermost.Exceptions: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Exceptions.MattermostError
+ Network.Mattermost.Exceptions: instance GHC.Exception.Exception Network.Mattermost.Exceptions.MattermostError
+ Network.Mattermost.Exceptions: instance GHC.Show.Show Network.Mattermost.Exceptions.MattermostError
+ Network.Mattermost.Lenses: postEditAtL :: Lens' Post ServerTime
+ Network.Mattermost.Types: AI :: Id -> AppId
+ Network.Mattermost.Types: ChannelMember :: Integer -> UserId -> Text -> Int -> ServerTime -> ChannelId -> ServerTime -> ChannelNotifyProps -> ChannelMember
+ Network.Mattermost.Types: ChannelPatch :: Maybe Text -> Maybe Text -> Maybe Text -> Maybe Text -> ChannelPatch
+ Network.Mattermost.Types: ChannelStats :: Text -> Int -> ChannelStats
+ Network.Mattermost.Types: ChannelUnread :: Text -> Text -> Int -> Int -> ChannelUnread
+ Network.Mattermost.Types: EI :: Id -> EmojiId
+ Network.Mattermost.Types: HI :: Id -> HookId
+ Network.Mattermost.Types: II :: Id -> InviteId
+ Network.Mattermost.Types: InitialTeamData :: Text -> Text -> Text -> InitialTeamData
+ Network.Mattermost.Types: JI :: Id -> JobId
+ Network.Mattermost.Types: MinChannelMember :: UserId -> ChannelId -> MinChannelMember
+ Network.Mattermost.Types: PostUpdate :: Maybe Bool -> Text -> Maybe Bool -> Maybe (Seq FileId) -> Maybe Text -> PostUpdate
+ Network.Mattermost.Types: RI :: Id -> ReportId
+ Network.Mattermost.Types: RawPost :: ChannelId -> Text -> Seq FileId -> Maybe PostId -> RawPost
+ Network.Mattermost.Types: Status :: UserId -> Text -> Bool -> ServerTime -> Status
+ Network.Mattermost.Types: TkI :: Id -> TokenId
+ Network.Mattermost.Types: UserById :: UserId -> UserParam
+ Network.Mattermost.Types: UserMe :: UserParam
+ Network.Mattermost.Types: UserSearch :: Text -> Bool -> Bool -> Text -> Text -> Text -> Text -> UserSearch
+ Network.Mattermost.Types: [channelMemberChannelId] :: ChannelMember -> ChannelId
+ Network.Mattermost.Types: [channelMemberLastUpdateAt] :: ChannelMember -> ServerTime
+ Network.Mattermost.Types: [channelMemberLastViewedAt] :: ChannelMember -> ServerTime
+ Network.Mattermost.Types: [channelMemberMentionCount] :: ChannelMember -> Int
+ Network.Mattermost.Types: [channelMemberMsgCount] :: ChannelMember -> Integer
+ Network.Mattermost.Types: [channelMemberNotifyProps] :: ChannelMember -> ChannelNotifyProps
+ Network.Mattermost.Types: [channelMemberRoles] :: ChannelMember -> Text
+ Network.Mattermost.Types: [channelMemberUserId] :: ChannelMember -> UserId
+ Network.Mattermost.Types: [channelPatchDisplayName] :: ChannelPatch -> Maybe Text
+ Network.Mattermost.Types: [channelPatchHeader] :: ChannelPatch -> Maybe Text
+ Network.Mattermost.Types: [channelPatchName] :: ChannelPatch -> Maybe Text
+ Network.Mattermost.Types: [channelPatchPurpose] :: ChannelPatch -> Maybe Text
+ Network.Mattermost.Types: [channelStatsChannelId] :: ChannelStats -> Text
+ Network.Mattermost.Types: [channelStatsMemberCount] :: ChannelStats -> Int
+ Network.Mattermost.Types: [channelUnreadChannelId] :: ChannelUnread -> Text
+ Network.Mattermost.Types: [channelUnreadMentionCount] :: ChannelUnread -> Int
+ Network.Mattermost.Types: [channelUnreadMsgCount] :: ChannelUnread -> Int
+ Network.Mattermost.Types: [channelUnreadTeamId] :: ChannelUnread -> Text
+ Network.Mattermost.Types: [initialTeamDataDisplayName] :: InitialTeamData -> Text
+ Network.Mattermost.Types: [initialTeamDataName] :: InitialTeamData -> Text
+ Network.Mattermost.Types: [initialTeamDataType] :: InitialTeamData -> Text
+ Network.Mattermost.Types: [minChannelMemberChannelId] :: MinChannelMember -> ChannelId
+ Network.Mattermost.Types: [minChannelMemberUserId] :: MinChannelMember -> UserId
+ Network.Mattermost.Types: [minChannelTeamId] :: MinChannel -> TeamId
+ Network.Mattermost.Types: [minComTeamId] :: MinCommand -> TeamId
+ Network.Mattermost.Types: [postEditAt] :: Post -> ServerTime
+ Network.Mattermost.Types: [postUpdateFileIds] :: PostUpdate -> Maybe (Seq FileId)
+ Network.Mattermost.Types: [postUpdateHasReactions] :: PostUpdate -> Maybe Bool
+ Network.Mattermost.Types: [postUpdateIsPinned] :: PostUpdate -> Maybe Bool
+ Network.Mattermost.Types: [postUpdateMessage] :: PostUpdate -> Text
+ Network.Mattermost.Types: [postUpdateProps] :: PostUpdate -> Maybe Text
+ Network.Mattermost.Types: [rawPostChannelId] :: RawPost -> ChannelId
+ Network.Mattermost.Types: [rawPostFileIds] :: RawPost -> Seq FileId
+ Network.Mattermost.Types: [rawPostMessage] :: RawPost -> Text
+ Network.Mattermost.Types: [rawPostRootId] :: RawPost -> Maybe PostId
+ Network.Mattermost.Types: [statusLastActivityAt] :: Status -> ServerTime
+ Network.Mattermost.Types: [statusManual] :: Status -> Bool
+ Network.Mattermost.Types: [statusStatus] :: Status -> Text
+ Network.Mattermost.Types: [statusUserId] :: Status -> UserId
+ Network.Mattermost.Types: [unAI] :: AppId -> Id
+ Network.Mattermost.Types: [unEI] :: EmojiId -> Id
+ Network.Mattermost.Types: [unHI] :: HookId -> Id
+ Network.Mattermost.Types: [unII] :: InviteId -> Id
+ Network.Mattermost.Types: [unJI] :: JobId -> Id
+ Network.Mattermost.Types: [unRI] :: ReportId -> Id
+ Network.Mattermost.Types: [unTkI] :: TokenId -> Id
+ Network.Mattermost.Types: [userSearchAllowInactive] :: UserSearch -> Bool
+ Network.Mattermost.Types: [userSearchInChannelId] :: UserSearch -> Text
+ Network.Mattermost.Types: [userSearchNotInChannelId] :: UserSearch -> Text
+ Network.Mattermost.Types: [userSearchNotInTeamId] :: UserSearch -> Text
+ Network.Mattermost.Types: [userSearchTeamId] :: UserSearch -> Text
+ Network.Mattermost.Types: [userSearchTerm] :: UserSearch -> Text
+ Network.Mattermost.Types: [userSearchWithoutTeam] :: UserSearch -> Bool
+ Network.Mattermost.Types: data ChannelMember
+ Network.Mattermost.Types: data ChannelPatch
+ Network.Mattermost.Types: data ChannelStats
+ Network.Mattermost.Types: data ChannelUnread
+ Network.Mattermost.Types: data InitialTeamData
+ Network.Mattermost.Types: data MinChannelMember
+ Network.Mattermost.Types: data PostUpdate
+ Network.Mattermost.Types: data RawPost
+ Network.Mattermost.Types: data Status
+ Network.Mattermost.Types: data UserParam
+ Network.Mattermost.Types: data UserSearch
+ Network.Mattermost.Types: defaultChannelPatch :: ChannelPatch
+ Network.Mattermost.Types: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.AppId
+ Network.Mattermost.Types: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.ChannelMember
+ Network.Mattermost.Types: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.ChannelPatch
+ Network.Mattermost.Types: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.ChannelStats
+ Network.Mattermost.Types: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.ChannelUnread
+ Network.Mattermost.Types: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.Command
+ Network.Mattermost.Types: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.EmojiId
+ Network.Mattermost.Types: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.HookId
+ Network.Mattermost.Types: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.InitialTeamData
+ Network.Mattermost.Types: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.InviteId
+ Network.Mattermost.Types: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.JobId
+ Network.Mattermost.Types: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.MinChannelMember
+ Network.Mattermost.Types: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.PostUpdate
+ Network.Mattermost.Types: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.RawPost
+ Network.Mattermost.Types: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.ReportId
+ Network.Mattermost.Types: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.Status
+ Network.Mattermost.Types: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.TokenId
+ Network.Mattermost.Types: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.UserSearch
+ Network.Mattermost.Types: instance Data.Aeson.Types.FromJSON.FromJSONKey Network.Mattermost.Types.AppId
+ Network.Mattermost.Types: instance Data.Aeson.Types.FromJSON.FromJSONKey Network.Mattermost.Types.EmojiId
+ Network.Mattermost.Types: instance Data.Aeson.Types.FromJSON.FromJSONKey Network.Mattermost.Types.HookId
+ Network.Mattermost.Types: instance Data.Aeson.Types.FromJSON.FromJSONKey Network.Mattermost.Types.InviteId
+ Network.Mattermost.Types: instance Data.Aeson.Types.FromJSON.FromJSONKey Network.Mattermost.Types.JobId
+ Network.Mattermost.Types: instance Data.Aeson.Types.FromJSON.FromJSONKey Network.Mattermost.Types.ReportId
+ Network.Mattermost.Types: instance Data.Aeson.Types.FromJSON.FromJSONKey Network.Mattermost.Types.TokenId
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.AppId
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.BoolString
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.ChannelMember
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.ChannelNotifyProps
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.ChannelPatch
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.ChannelStats
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.ChannelUnread
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.Command
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.EmojiId
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.FileInfo
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.HookId
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.InitialTeamData
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.InviteId
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.JobId
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.MinChannelMember
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.NotifyOption
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.PostUpdate
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.RawPost
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.ReportId
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.Status
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.Team
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.TeamMember
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.TokenId
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.User
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.UserNotifyProps
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.UserSearch
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSON t => Data.Aeson.Types.ToJSON.ToJSON (Network.Mattermost.Types.WithDefault t)
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSONKey Network.Mattermost.Types.AppId
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSONKey Network.Mattermost.Types.EmojiId
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSONKey Network.Mattermost.Types.HookId
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSONKey Network.Mattermost.Types.InviteId
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSONKey Network.Mattermost.Types.JobId
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSONKey Network.Mattermost.Types.ReportId
+ Network.Mattermost.Types: instance Data.Aeson.Types.ToJSON.ToJSONKey Network.Mattermost.Types.TokenId
+ Network.Mattermost.Types: instance Data.Hashable.Class.Hashable Network.Mattermost.Types.AppId
+ Network.Mattermost.Types: instance Data.Hashable.Class.Hashable Network.Mattermost.Types.EmojiId
+ Network.Mattermost.Types: instance Data.Hashable.Class.Hashable Network.Mattermost.Types.HookId
+ Network.Mattermost.Types: instance Data.Hashable.Class.Hashable Network.Mattermost.Types.InviteId
+ Network.Mattermost.Types: instance Data.Hashable.Class.Hashable Network.Mattermost.Types.JobId
+ Network.Mattermost.Types: instance Data.Hashable.Class.Hashable Network.Mattermost.Types.ReportId
+ Network.Mattermost.Types: instance Data.Hashable.Class.Hashable Network.Mattermost.Types.TokenId
+ Network.Mattermost.Types: instance GHC.Classes.Eq Network.Mattermost.Types.AppId
+ Network.Mattermost.Types: instance GHC.Classes.Eq Network.Mattermost.Types.ChannelMember
+ Network.Mattermost.Types: instance GHC.Classes.Eq Network.Mattermost.Types.ChannelPatch
+ Network.Mattermost.Types: instance GHC.Classes.Eq Network.Mattermost.Types.ChannelStats
+ Network.Mattermost.Types: instance GHC.Classes.Eq Network.Mattermost.Types.ChannelUnread
+ Network.Mattermost.Types: instance GHC.Classes.Eq Network.Mattermost.Types.EmojiId
+ Network.Mattermost.Types: instance GHC.Classes.Eq Network.Mattermost.Types.HookId
+ Network.Mattermost.Types: instance GHC.Classes.Eq Network.Mattermost.Types.InitialTeamData
+ Network.Mattermost.Types: instance GHC.Classes.Eq Network.Mattermost.Types.InviteId
+ Network.Mattermost.Types: instance GHC.Classes.Eq Network.Mattermost.Types.JobId
+ Network.Mattermost.Types: instance GHC.Classes.Eq Network.Mattermost.Types.MinChannelMember
+ Network.Mattermost.Types: instance GHC.Classes.Eq Network.Mattermost.Types.PostUpdate
+ Network.Mattermost.Types: instance GHC.Classes.Eq Network.Mattermost.Types.RawPost
+ Network.Mattermost.Types: instance GHC.Classes.Eq Network.Mattermost.Types.ReportId
+ Network.Mattermost.Types: instance GHC.Classes.Eq Network.Mattermost.Types.TokenId
+ Network.Mattermost.Types: instance GHC.Classes.Eq Network.Mattermost.Types.UserParam
+ Network.Mattermost.Types: instance GHC.Classes.Eq Network.Mattermost.Types.UserSearch
+ Network.Mattermost.Types: instance GHC.Classes.Ord Network.Mattermost.Types.AppId
+ Network.Mattermost.Types: instance GHC.Classes.Ord Network.Mattermost.Types.EmojiId
+ Network.Mattermost.Types: instance GHC.Classes.Ord Network.Mattermost.Types.HookId
+ Network.Mattermost.Types: instance GHC.Classes.Ord Network.Mattermost.Types.InviteId
+ Network.Mattermost.Types: instance GHC.Classes.Ord Network.Mattermost.Types.JobId
+ Network.Mattermost.Types: instance GHC.Classes.Ord Network.Mattermost.Types.ReportId
+ Network.Mattermost.Types: instance GHC.Classes.Ord Network.Mattermost.Types.TokenId
+ Network.Mattermost.Types: instance GHC.Classes.Ord Network.Mattermost.Types.UserParam
+ Network.Mattermost.Types: instance GHC.Read.Read Network.Mattermost.Types.AppId
+ Network.Mattermost.Types: instance GHC.Read.Read Network.Mattermost.Types.ChannelMember
+ Network.Mattermost.Types: instance GHC.Read.Read Network.Mattermost.Types.ChannelPatch
+ Network.Mattermost.Types: instance GHC.Read.Read Network.Mattermost.Types.ChannelStats
+ Network.Mattermost.Types: instance GHC.Read.Read Network.Mattermost.Types.ChannelUnread
+ Network.Mattermost.Types: instance GHC.Read.Read Network.Mattermost.Types.EmojiId
+ Network.Mattermost.Types: instance GHC.Read.Read Network.Mattermost.Types.HookId
+ Network.Mattermost.Types: instance GHC.Read.Read Network.Mattermost.Types.InitialTeamData
+ Network.Mattermost.Types: instance GHC.Read.Read Network.Mattermost.Types.InviteId
+ Network.Mattermost.Types: instance GHC.Read.Read Network.Mattermost.Types.JobId
+ Network.Mattermost.Types: instance GHC.Read.Read Network.Mattermost.Types.MinChannelMember
+ Network.Mattermost.Types: instance GHC.Read.Read Network.Mattermost.Types.PostUpdate
+ Network.Mattermost.Types: instance GHC.Read.Read Network.Mattermost.Types.RawPost
+ Network.Mattermost.Types: instance GHC.Read.Read Network.Mattermost.Types.ReportId
+ Network.Mattermost.Types: instance GHC.Read.Read Network.Mattermost.Types.TokenId
+ Network.Mattermost.Types: instance GHC.Read.Read Network.Mattermost.Types.UserParam
+ Network.Mattermost.Types: instance GHC.Read.Read Network.Mattermost.Types.UserSearch
+ Network.Mattermost.Types: instance GHC.Show.Show Network.Mattermost.Types.AppId
+ Network.Mattermost.Types: instance GHC.Show.Show Network.Mattermost.Types.ChannelMember
+ Network.Mattermost.Types: instance GHC.Show.Show Network.Mattermost.Types.ChannelPatch
+ Network.Mattermost.Types: instance GHC.Show.Show Network.Mattermost.Types.ChannelStats
+ Network.Mattermost.Types: instance GHC.Show.Show Network.Mattermost.Types.ChannelUnread
+ Network.Mattermost.Types: instance GHC.Show.Show Network.Mattermost.Types.EmojiId
+ Network.Mattermost.Types: instance GHC.Show.Show Network.Mattermost.Types.HookId
+ Network.Mattermost.Types: instance GHC.Show.Show Network.Mattermost.Types.InitialTeamData
+ Network.Mattermost.Types: instance GHC.Show.Show Network.Mattermost.Types.InviteId
+ Network.Mattermost.Types: instance GHC.Show.Show Network.Mattermost.Types.JobId
+ Network.Mattermost.Types: instance GHC.Show.Show Network.Mattermost.Types.MinChannelMember
+ Network.Mattermost.Types: instance GHC.Show.Show Network.Mattermost.Types.PostUpdate
+ Network.Mattermost.Types: instance GHC.Show.Show Network.Mattermost.Types.RawPost
+ Network.Mattermost.Types: instance GHC.Show.Show Network.Mattermost.Types.ReportId
+ Network.Mattermost.Types: instance GHC.Show.Show Network.Mattermost.Types.TokenId
+ Network.Mattermost.Types: instance GHC.Show.Show Network.Mattermost.Types.UserParam
+ Network.Mattermost.Types: instance GHC.Show.Show Network.Mattermost.Types.UserSearch
+ Network.Mattermost.Types: instance Network.Mattermost.Types.IsId Network.Mattermost.Types.AppId
+ Network.Mattermost.Types: instance Network.Mattermost.Types.IsId Network.Mattermost.Types.EmojiId
+ Network.Mattermost.Types: instance Network.Mattermost.Types.IsId Network.Mattermost.Types.HookId
+ Network.Mattermost.Types: instance Network.Mattermost.Types.IsId Network.Mattermost.Types.InviteId
+ Network.Mattermost.Types: instance Network.Mattermost.Types.IsId Network.Mattermost.Types.JobId
+ Network.Mattermost.Types: instance Network.Mattermost.Types.IsId Network.Mattermost.Types.ReportId
+ Network.Mattermost.Types: instance Network.Mattermost.Types.IsId Network.Mattermost.Types.TokenId
+ Network.Mattermost.Types: instance Text.Printf.PrintfArg Network.Mattermost.Types.AppId
+ Network.Mattermost.Types: instance Text.Printf.PrintfArg Network.Mattermost.Types.ChannelId
+ Network.Mattermost.Types: instance Text.Printf.PrintfArg Network.Mattermost.Types.CommandId
+ Network.Mattermost.Types: instance Text.Printf.PrintfArg Network.Mattermost.Types.EmojiId
+ Network.Mattermost.Types: instance Text.Printf.PrintfArg Network.Mattermost.Types.FileId
+ Network.Mattermost.Types: instance Text.Printf.PrintfArg Network.Mattermost.Types.HookId
+ Network.Mattermost.Types: instance Text.Printf.PrintfArg Network.Mattermost.Types.InviteId
+ Network.Mattermost.Types: instance Text.Printf.PrintfArg Network.Mattermost.Types.JobId
+ Network.Mattermost.Types: instance Text.Printf.PrintfArg Network.Mattermost.Types.PostId
+ Network.Mattermost.Types: instance Text.Printf.PrintfArg Network.Mattermost.Types.ReportId
+ Network.Mattermost.Types: instance Text.Printf.PrintfArg Network.Mattermost.Types.TeamId
+ Network.Mattermost.Types: instance Text.Printf.PrintfArg Network.Mattermost.Types.TokenId
+ Network.Mattermost.Types: instance Text.Printf.PrintfArg Network.Mattermost.Types.UserId
+ Network.Mattermost.Types: instance Text.Printf.PrintfArg Network.Mattermost.Types.UserParam
+ Network.Mattermost.Types: newtype AppId
+ Network.Mattermost.Types: newtype EmojiId
+ Network.Mattermost.Types: newtype HookId
+ Network.Mattermost.Types: newtype InviteId
+ Network.Mattermost.Types: newtype JobId
+ Network.Mattermost.Types: newtype ReportId
+ Network.Mattermost.Types: newtype TokenId
+ Network.Mattermost.Types: postUpdate :: Text -> PostUpdate
+ Network.Mattermost.Types: rawPost :: Text -> ChannelId -> RawPost
+ Network.Mattermost.Types: timeFromServer :: Integer -> ServerTime
+ Network.Mattermost.Types: timeToServer :: ServerTime -> Int
+ Network.Mattermost.Types: userParamString :: UserParam -> Text
+ Network.Mattermost.Types.Base: ServerTime :: UTCTime -> ServerTime
+ Network.Mattermost.Types.Base: [withServerTime] :: ServerTime -> UTCTime
+ Network.Mattermost.Types.Base: instance GHC.Classes.Eq Network.Mattermost.Types.Base.ServerTime
+ Network.Mattermost.Types.Base: instance GHC.Classes.Ord Network.Mattermost.Types.Base.ServerTime
+ Network.Mattermost.Types.Base: instance GHC.Read.Read Network.Mattermost.Types.Base.ServerTime
+ Network.Mattermost.Types.Base: instance GHC.Show.Show Network.Mattermost.Types.Base.ServerTime
+ Network.Mattermost.Types.Base: newtype ServerTime
+ Network.Mattermost.Types.Config: ClientConfig :: Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Maybe Text -> Maybe Text -> Maybe Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> Text -> ClientConfig
+ Network.Mattermost.Types.Config: ComplianceSettings :: Text -> Bool -> Bool -> ComplianceSettings
+ Network.Mattermost.Types.Config: EmailSettings :: Bool -> Maybe Text -> Bool -> Text -> Int -> Text -> Bool -> Text -> Text -> Bool -> Text -> Text -> Bool -> Int -> Text -> Text -> Text -> Bool -> Text -> Text -> Bool -> EmailSettings
+ Network.Mattermost.Types.Config: LogSettings :: Bool -> Text -> Text -> Bool -> Bool -> Text -> Text -> Bool -> LogSettings
+ Network.Mattermost.Types.Config: MetricsSettings :: Integer -> Bool -> Text -> MetricsSettings
+ Network.Mattermost.Types.Config: NativeAppSettings :: Text -> Text -> Text -> NativeAppSettings
+ Network.Mattermost.Types.Config: PasswordSettings :: Bool -> Bool -> Bool -> Bool -> Int -> PasswordSettings
+ Network.Mattermost.Types.Config: PrivacySettings :: Bool -> Bool -> PrivacySettings
+ Network.Mattermost.Types.Config: RateLimitSettings :: Bool -> Bool -> Int -> Int -> Text -> Int -> RateLimitSettings
+ Network.Mattermost.Types.Config: ServerConfig :: LogSettings -> ComplianceSettings -> EmailSettings -> NativeAppSettings -> PasswordSettings -> TeamSettings -> SupportSettings -> MetricsSettings -> WebrtcSettings -> ServerConfig
+ Network.Mattermost.Types.Config: SupportSettings :: Text -> Text -> Text -> Text -> Text -> Text -> SupportSettings
+ Network.Mattermost.Types.Config: TeamSettings :: Text -> Text -> Int -> Text -> Bool -> Bool -> Text -> Text -> Int -> Text -> Bool -> Text -> Text -> Int -> Text -> Int -> Bool -> Text -> Text -> Text -> TeamSettings
+ Network.Mattermost.Types.Config: WebrtcSettings :: Text -> Text -> Bool -> Text -> Text -> Text -> Text -> Text -> WebrtcSettings
+ Network.Mattermost.Types.Config: [clientConfigAboutLink] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigAdministratorsGuideLink] :: ClientConfig -> Maybe Text
+ Network.Mattermost.Types.Config: [clientConfigAllowEditPost] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigAndroidAppDownloadLink] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigAppDownloadLink] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigAvailableLocales] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigBuildDate] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigBuildEnterpriseReady] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigBuildHashEnterprise] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigBuildHash] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigBuildNumber] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigCommercialSupportLink] :: ClientConfig -> Maybe Text
+ Network.Mattermost.Types.Config: [clientConfigDefaultClientLocale] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigDiagnosticId] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigDiagnosticsEnabled] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigEnableChannelViewedMessages] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigEnableCommands] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigEnableCustomEmoji] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigEnableDeveloper] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigEnableDiagnostics] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigEnableEmailBatching] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigEnableEmojiPicker] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigEnableFileAttachments] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigEnableIncomingWebhooks] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigEnableLinkPreviews] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigEnableOAuthServiceProvider] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigEnableOnlyAdminIntegrations] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigEnableOpenServer] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigEnableOutgoingWebhooks] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigEnablePostIconOverride] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigEnablePostUsernameOverride] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigEnablePublicLink] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigEnableSignInWithEmail] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigEnableSignInWithUsername] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigEnableSignUpWithEmail] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigEnableSignUpWithGitLab] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigEnableTeamCreation] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigEnableTesting] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigEnableUserCreation] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigEnableUserTypingMessages] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigEnableWebrtc] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigGoogleDeveloperKey] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigHelpLink] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigIosAppDownloadLink] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigMaxFileSize] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigMaxNotificationsPerChannel] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigPostEditTimeLimit] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigPrivacyPolicyLink] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigReportAProblemLink] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigRequireEmailVerification] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigRestrictCustomEmojiCreation] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigRestrictDirectMessage] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigRestrictPostDelete] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigRestrictPrivateChannelCreation] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigRestrictPrivateChannelDeletion] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigRestrictPrivateChannelManageMembers] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigRestrictPrivateChannelManagement] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigRestrictPublicChannelCreation] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigRestrictPublicChannelDeletion] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigRestrictPublicChannelManagement] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigRestrictTeamInvite] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigSQLDriverName] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigSendEmailNotifications] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigSendPushNotifications] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigShowEmailAddress] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigSiteName] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigSiteURL] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigSupportEmail] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigTeammateNameDisplay] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigTermsOfServiceLink] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigTimeBetweenUserTypingUpdatesMilliseconds] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigTroubleshootingForumLink] :: ClientConfig -> Maybe Text
+ Network.Mattermost.Types.Config: [clientConfigVersion] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigWebsocketPort] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [clientConfigWebsocketSecurePort] :: ClientConfig -> Text
+ Network.Mattermost.Types.Config: [complianceSettingsDirectory] :: ComplianceSettings -> Text
+ Network.Mattermost.Types.Config: [complianceSettingsEnable] :: ComplianceSettings -> Bool
+ Network.Mattermost.Types.Config: [complianceSettingsEnabledaily] :: ComplianceSettings -> Bool
+ Network.Mattermost.Types.Config: [configCompliancesettings] :: ServerConfig -> ComplianceSettings
+ Network.Mattermost.Types.Config: [configEmailsettings] :: ServerConfig -> EmailSettings
+ Network.Mattermost.Types.Config: [configLogsettings] :: ServerConfig -> LogSettings
+ Network.Mattermost.Types.Config: [configMetricssettings] :: ServerConfig -> MetricsSettings
+ Network.Mattermost.Types.Config: [configNativeappsettings] :: ServerConfig -> NativeAppSettings
+ Network.Mattermost.Types.Config: [configPasswordsettings] :: ServerConfig -> PasswordSettings
+ Network.Mattermost.Types.Config: [configSupportsettings] :: ServerConfig -> SupportSettings
+ Network.Mattermost.Types.Config: [configTeamsettings] :: ServerConfig -> TeamSettings
+ Network.Mattermost.Types.Config: [configWebrtcsettings] :: ServerConfig -> WebrtcSettings
+ Network.Mattermost.Types.Config: [emailSettingsConnectionsecurity] :: EmailSettings -> Text
+ Network.Mattermost.Types.Config: [emailSettingsEmailbatchingbuffersize] :: EmailSettings -> Int
+ Network.Mattermost.Types.Config: [emailSettingsEmailbatchinginterval] :: EmailSettings -> Int
+ Network.Mattermost.Types.Config: [emailSettingsEnableemailbatching] :: EmailSettings -> Bool
+ Network.Mattermost.Types.Config: [emailSettingsEnablesigninwithemail] :: EmailSettings -> Bool
+ Network.Mattermost.Types.Config: [emailSettingsEnablesigninwithusername] :: EmailSettings -> Bool
+ Network.Mattermost.Types.Config: [emailSettingsEnablesignupwithemail] :: EmailSettings -> Bool
+ Network.Mattermost.Types.Config: [emailSettingsFeedbackemail] :: EmailSettings -> Text
+ Network.Mattermost.Types.Config: [emailSettingsFeedbackname] :: EmailSettings -> Text
+ Network.Mattermost.Types.Config: [emailSettingsFeedbackorganization] :: EmailSettings -> Text
+ Network.Mattermost.Types.Config: [emailSettingsInvitesalt] :: EmailSettings -> Text
+ Network.Mattermost.Types.Config: [emailSettingsPasswordresetsalt] :: EmailSettings -> Maybe Text
+ Network.Mattermost.Types.Config: [emailSettingsPushnotificationcontents] :: EmailSettings -> Text
+ Network.Mattermost.Types.Config: [emailSettingsPushnotificationserver] :: EmailSettings -> Text
+ Network.Mattermost.Types.Config: [emailSettingsRequireemailverification] :: EmailSettings -> Bool
+ Network.Mattermost.Types.Config: [emailSettingsSendemailnotifications] :: EmailSettings -> Bool
+ Network.Mattermost.Types.Config: [emailSettingsSendpushnotifications] :: EmailSettings -> Bool
+ Network.Mattermost.Types.Config: [emailSettingsSmtppassword] :: EmailSettings -> Text
+ Network.Mattermost.Types.Config: [emailSettingsSmtpport] :: EmailSettings -> Text
+ Network.Mattermost.Types.Config: [emailSettingsSmtpserver] :: EmailSettings -> Text
+ Network.Mattermost.Types.Config: [emailSettingsSmtpusername] :: EmailSettings -> Text
+ Network.Mattermost.Types.Config: [logSettingsConsolelevel] :: LogSettings -> Text
+ Network.Mattermost.Types.Config: [logSettingsEnableconsole] :: LogSettings -> Bool
+ Network.Mattermost.Types.Config: [logSettingsEnablediagnostics] :: LogSettings -> Bool
+ Network.Mattermost.Types.Config: [logSettingsEnablefile] :: LogSettings -> Bool
+ Network.Mattermost.Types.Config: [logSettingsEnablewebhookdebugging] :: LogSettings -> Bool
+ Network.Mattermost.Types.Config: [logSettingsFileformat] :: LogSettings -> Text
+ Network.Mattermost.Types.Config: [logSettingsFilelevel] :: LogSettings -> Text
+ Network.Mattermost.Types.Config: [logSettingsFilelocation] :: LogSettings -> Text
+ Network.Mattermost.Types.Config: [metricsSettingsBlockprofilerate] :: MetricsSettings -> Integer
+ Network.Mattermost.Types.Config: [metricsSettingsEnable] :: MetricsSettings -> Bool
+ Network.Mattermost.Types.Config: [metricsSettingsListenaddress] :: MetricsSettings -> Text
+ Network.Mattermost.Types.Config: [nativeAppSettingsAndroidappdownloadlink] :: NativeAppSettings -> Text
+ Network.Mattermost.Types.Config: [nativeAppSettingsAppdownloadlink] :: NativeAppSettings -> Text
+ Network.Mattermost.Types.Config: [nativeAppSettingsIosappdownloadlink] :: NativeAppSettings -> Text
+ Network.Mattermost.Types.Config: [passwordSettingsLowercase] :: PasswordSettings -> Bool
+ Network.Mattermost.Types.Config: [passwordSettingsMinimumlength] :: PasswordSettings -> Int
+ Network.Mattermost.Types.Config: [passwordSettingsNumber] :: PasswordSettings -> Bool
+ Network.Mattermost.Types.Config: [passwordSettingsSymbol] :: PasswordSettings -> Bool
+ Network.Mattermost.Types.Config: [passwordSettingsUppercase] :: PasswordSettings -> Bool
+ Network.Mattermost.Types.Config: [privacySettingsShowemailaddress] :: PrivacySettings -> Bool
+ Network.Mattermost.Types.Config: [privacySettingsShowfullname] :: PrivacySettings -> Bool
+ Network.Mattermost.Types.Config: [rateLimitSettingsEnable] :: RateLimitSettings -> Bool
+ Network.Mattermost.Types.Config: [rateLimitSettingsMaxburst] :: RateLimitSettings -> Int
+ Network.Mattermost.Types.Config: [rateLimitSettingsMemorystoresize] :: RateLimitSettings -> Int
+ Network.Mattermost.Types.Config: [rateLimitSettingsPersec] :: RateLimitSettings -> Int
+ Network.Mattermost.Types.Config: [rateLimitSettingsVarybyheader] :: RateLimitSettings -> Text
+ Network.Mattermost.Types.Config: [rateLimitSettingsVarybyremoteaddr] :: RateLimitSettings -> Bool
+ Network.Mattermost.Types.Config: [supportSettingsAboutlink] :: SupportSettings -> Text
+ Network.Mattermost.Types.Config: [supportSettingsHelplink] :: SupportSettings -> Text
+ Network.Mattermost.Types.Config: [supportSettingsPrivacypolicylink] :: SupportSettings -> Text
+ Network.Mattermost.Types.Config: [supportSettingsReportaproblemlink] :: SupportSettings -> Text
+ Network.Mattermost.Types.Config: [supportSettingsSupportemail] :: SupportSettings -> Text
+ Network.Mattermost.Types.Config: [supportSettingsTermsofservicelink] :: SupportSettings -> Text
+ Network.Mattermost.Types.Config: [teamSettingsCustombrandtext] :: TeamSettings -> Text
+ Network.Mattermost.Types.Config: [teamSettingsCustomdescriptiontext] :: TeamSettings -> Text
+ Network.Mattermost.Types.Config: [teamSettingsEnablecustombrand] :: TeamSettings -> Bool
+ Network.Mattermost.Types.Config: [teamSettingsEnableopenserver] :: TeamSettings -> Bool
+ Network.Mattermost.Types.Config: [teamSettingsEnableteamcreation] :: TeamSettings -> Bool
+ Network.Mattermost.Types.Config: [teamSettingsEnableusercreation] :: TeamSettings -> Bool
+ Network.Mattermost.Types.Config: [teamSettingsMaxchannelsperteam] :: TeamSettings -> Int
+ Network.Mattermost.Types.Config: [teamSettingsMaxnotificationsperchannel] :: TeamSettings -> Int
+ Network.Mattermost.Types.Config: [teamSettingsMaxusersperteam] :: TeamSettings -> Int
+ Network.Mattermost.Types.Config: [teamSettingsRestrictcreationtodomains] :: TeamSettings -> Text
+ Network.Mattermost.Types.Config: [teamSettingsRestrictdirectmessage] :: TeamSettings -> Text
+ Network.Mattermost.Types.Config: [teamSettingsRestrictprivatechannelcreation] :: TeamSettings -> Text
+ Network.Mattermost.Types.Config: [teamSettingsRestrictprivatechanneldeletion] :: TeamSettings -> Text
+ Network.Mattermost.Types.Config: [teamSettingsRestrictprivatechannelmanagement] :: TeamSettings -> Text
+ Network.Mattermost.Types.Config: [teamSettingsRestrictpublicchannelcreation] :: TeamSettings -> Text
+ Network.Mattermost.Types.Config: [teamSettingsRestrictpublicchanneldeletion] :: TeamSettings -> Text
+ Network.Mattermost.Types.Config: [teamSettingsRestrictpublicchannelmanagement] :: TeamSettings -> Text
+ Network.Mattermost.Types.Config: [teamSettingsRestrictteaminvite] :: TeamSettings -> Text
+ Network.Mattermost.Types.Config: [teamSettingsSitename] :: TeamSettings -> Text
+ Network.Mattermost.Types.Config: [teamSettingsUserstatusawaytimeout] :: TeamSettings -> Int
+ Network.Mattermost.Types.Config: [webrtcSettingsEnable] :: WebrtcSettings -> Bool
+ Network.Mattermost.Types.Config: [webrtcSettingsGatewayadminsecret] :: WebrtcSettings -> Text
+ Network.Mattermost.Types.Config: [webrtcSettingsGatewayadminurl] :: WebrtcSettings -> Text
+ Network.Mattermost.Types.Config: [webrtcSettingsGatewaywebsocketurl] :: WebrtcSettings -> Text
+ Network.Mattermost.Types.Config: [webrtcSettingsStunuri] :: WebrtcSettings -> Text
+ Network.Mattermost.Types.Config: [webrtcSettingsTurnsharedkey] :: WebrtcSettings -> Text
+ Network.Mattermost.Types.Config: [webrtcSettingsTurnuri] :: WebrtcSettings -> Text
+ Network.Mattermost.Types.Config: [webrtcSettingsTurnusername] :: WebrtcSettings -> Text
+ Network.Mattermost.Types.Config: data ClientConfig
+ Network.Mattermost.Types.Config: data ComplianceSettings
+ Network.Mattermost.Types.Config: data EmailSettings
+ Network.Mattermost.Types.Config: data LogSettings
+ Network.Mattermost.Types.Config: data MetricsSettings
+ Network.Mattermost.Types.Config: data NativeAppSettings
+ Network.Mattermost.Types.Config: data PasswordSettings
+ Network.Mattermost.Types.Config: data PrivacySettings
+ Network.Mattermost.Types.Config: data RateLimitSettings
+ Network.Mattermost.Types.Config: data ServerConfig
+ Network.Mattermost.Types.Config: data SupportSettings
+ Network.Mattermost.Types.Config: data TeamSettings
+ Network.Mattermost.Types.Config: data WebrtcSettings
+ Network.Mattermost.Types.Config: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.Config.ClientConfig
+ Network.Mattermost.Types.Config: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.Config.ComplianceSettings
+ Network.Mattermost.Types.Config: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.Config.EmailSettings
+ Network.Mattermost.Types.Config: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.Config.LogSettings
+ Network.Mattermost.Types.Config: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.Config.MetricsSettings
+ Network.Mattermost.Types.Config: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.Config.NativeAppSettings
+ Network.Mattermost.Types.Config: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.Config.PasswordSettings
+ Network.Mattermost.Types.Config: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.Config.PrivacySettings
+ Network.Mattermost.Types.Config: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.Config.RateLimitSettings
+ Network.Mattermost.Types.Config: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.Config.ServerConfig
+ Network.Mattermost.Types.Config: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.Config.SupportSettings
+ Network.Mattermost.Types.Config: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.Config.TeamSettings
+ Network.Mattermost.Types.Config: instance Data.Aeson.Types.FromJSON.FromJSON Network.Mattermost.Types.Config.WebrtcSettings
+ Network.Mattermost.Types.Config: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.Config.ComplianceSettings
+ Network.Mattermost.Types.Config: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.Config.EmailSettings
+ Network.Mattermost.Types.Config: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.Config.LogSettings
+ Network.Mattermost.Types.Config: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.Config.MetricsSettings
+ Network.Mattermost.Types.Config: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.Config.NativeAppSettings
+ Network.Mattermost.Types.Config: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.Config.PasswordSettings
+ Network.Mattermost.Types.Config: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.Config.PrivacySettings
+ Network.Mattermost.Types.Config: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.Config.RateLimitSettings
+ Network.Mattermost.Types.Config: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.Config.ServerConfig
+ Network.Mattermost.Types.Config: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.Config.SupportSettings
+ Network.Mattermost.Types.Config: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.Config.TeamSettings
+ Network.Mattermost.Types.Config: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.Types.Config.WebrtcSettings
+ Network.Mattermost.Types.Config: instance GHC.Classes.Eq Network.Mattermost.Types.Config.ClientConfig
+ Network.Mattermost.Types.Config: instance GHC.Classes.Eq Network.Mattermost.Types.Config.ComplianceSettings
+ Network.Mattermost.Types.Config: instance GHC.Classes.Eq Network.Mattermost.Types.Config.EmailSettings
+ Network.Mattermost.Types.Config: instance GHC.Classes.Eq Network.Mattermost.Types.Config.LogSettings
+ Network.Mattermost.Types.Config: instance GHC.Classes.Eq Network.Mattermost.Types.Config.MetricsSettings
+ Network.Mattermost.Types.Config: instance GHC.Classes.Eq Network.Mattermost.Types.Config.NativeAppSettings
+ Network.Mattermost.Types.Config: instance GHC.Classes.Eq Network.Mattermost.Types.Config.PasswordSettings
+ Network.Mattermost.Types.Config: instance GHC.Classes.Eq Network.Mattermost.Types.Config.PrivacySettings
+ Network.Mattermost.Types.Config: instance GHC.Classes.Eq Network.Mattermost.Types.Config.RateLimitSettings
+ Network.Mattermost.Types.Config: instance GHC.Classes.Eq Network.Mattermost.Types.Config.ServerConfig
+ Network.Mattermost.Types.Config: instance GHC.Classes.Eq Network.Mattermost.Types.Config.SupportSettings
+ Network.Mattermost.Types.Config: instance GHC.Classes.Eq Network.Mattermost.Types.Config.TeamSettings
+ Network.Mattermost.Types.Config: instance GHC.Classes.Eq Network.Mattermost.Types.Config.WebrtcSettings
+ Network.Mattermost.Types.Config: instance GHC.Read.Read Network.Mattermost.Types.Config.ClientConfig
+ Network.Mattermost.Types.Config: instance GHC.Read.Read Network.Mattermost.Types.Config.ComplianceSettings
+ Network.Mattermost.Types.Config: instance GHC.Read.Read Network.Mattermost.Types.Config.EmailSettings
+ Network.Mattermost.Types.Config: instance GHC.Read.Read Network.Mattermost.Types.Config.LogSettings
+ Network.Mattermost.Types.Config: instance GHC.Read.Read Network.Mattermost.Types.Config.MetricsSettings
+ Network.Mattermost.Types.Config: instance GHC.Read.Read Network.Mattermost.Types.Config.NativeAppSettings
+ Network.Mattermost.Types.Config: instance GHC.Read.Read Network.Mattermost.Types.Config.PasswordSettings
+ Network.Mattermost.Types.Config: instance GHC.Read.Read Network.Mattermost.Types.Config.PrivacySettings
+ Network.Mattermost.Types.Config: instance GHC.Read.Read Network.Mattermost.Types.Config.RateLimitSettings
+ Network.Mattermost.Types.Config: instance GHC.Read.Read Network.Mattermost.Types.Config.ServerConfig
+ Network.Mattermost.Types.Config: instance GHC.Read.Read Network.Mattermost.Types.Config.SupportSettings
+ Network.Mattermost.Types.Config: instance GHC.Read.Read Network.Mattermost.Types.Config.TeamSettings
+ Network.Mattermost.Types.Config: instance GHC.Read.Read Network.Mattermost.Types.Config.WebrtcSettings
+ Network.Mattermost.Types.Config: instance GHC.Show.Show Network.Mattermost.Types.Config.ClientConfig
+ Network.Mattermost.Types.Config: instance GHC.Show.Show Network.Mattermost.Types.Config.ComplianceSettings
+ Network.Mattermost.Types.Config: instance GHC.Show.Show Network.Mattermost.Types.Config.EmailSettings
+ Network.Mattermost.Types.Config: instance GHC.Show.Show Network.Mattermost.Types.Config.LogSettings
+ Network.Mattermost.Types.Config: instance GHC.Show.Show Network.Mattermost.Types.Config.MetricsSettings
+ Network.Mattermost.Types.Config: instance GHC.Show.Show Network.Mattermost.Types.Config.NativeAppSettings
+ Network.Mattermost.Types.Config: instance GHC.Show.Show Network.Mattermost.Types.Config.PasswordSettings
+ Network.Mattermost.Types.Config: instance GHC.Show.Show Network.Mattermost.Types.Config.PrivacySettings
+ Network.Mattermost.Types.Config: instance GHC.Show.Show Network.Mattermost.Types.Config.RateLimitSettings
+ Network.Mattermost.Types.Config: instance GHC.Show.Show Network.Mattermost.Types.Config.ServerConfig
+ Network.Mattermost.Types.Config: instance GHC.Show.Show Network.Mattermost.Types.Config.SupportSettings
+ Network.Mattermost.Types.Config: instance GHC.Show.Show Network.Mattermost.Types.Config.TeamSettings
+ Network.Mattermost.Types.Config: instance GHC.Show.Show Network.Mattermost.Types.Config.WebrtcSettings
+ Network.Mattermost.Util: instance Network.Stream.Stream Network.Mattermost.Util.MMConn
+ Network.Mattermost.WebSocket: mmSendWSAction :: ConnectionData -> MMWebSocket -> WebsocketAction -> IO ()
+ Network.Mattermost.WebSocket.Types: UserTyping :: Int64 -> ChannelId -> Maybe PostId -> WebsocketAction
+ Network.Mattermost.WebSocket.Types: [waChannelId] :: WebsocketAction -> ChannelId
+ Network.Mattermost.WebSocket.Types: [waParentPostId] :: WebsocketAction -> Maybe PostId
+ Network.Mattermost.WebSocket.Types: [waSeq] :: WebsocketAction -> Int64
+ Network.Mattermost.WebSocket.Types: data WebsocketAction
+ Network.Mattermost.WebSocket.Types: instance Data.Aeson.Types.ToJSON.ToJSON Network.Mattermost.WebSocket.Types.WebsocketAction
+ Network.Mattermost.WebSocket.Types: instance GHC.Classes.Eq Network.Mattermost.WebSocket.Types.WebsocketAction
+ Network.Mattermost.WebSocket.Types: instance GHC.Classes.Ord Network.Mattermost.WebSocket.Types.WebsocketAction
+ Network.Mattermost.WebSocket.Types: instance GHC.Read.Read Network.Mattermost.WebSocket.Types.WebsocketAction
+ Network.Mattermost.WebSocket.Types: instance GHC.Show.Show Network.Mattermost.WebSocket.Types.WebsocketAction
+ Network.Mattermost.WebSocket.Types: instance Network.WebSockets.Types.WebSocketsData Network.Mattermost.WebSocket.Types.WebsocketAction
- Network.Mattermost: Channel :: ChannelId -> UTCTime -> UTCTime -> UTCTime -> Maybe TeamId -> Type -> Text -> Text -> Text -> Text -> UTCTime -> Int -> UTCTime -> Maybe UserId -> Channel
+ Network.Mattermost: Channel :: ChannelId -> ServerTime -> ServerTime -> ServerTime -> Maybe TeamId -> Type -> Text -> Text -> Text -> Text -> ServerTime -> Int -> ServerTime -> Maybe UserId -> Channel
- Network.Mattermost: ChannelData :: ChannelId -> UserId -> Text -> UTCTime -> Int -> Int -> ChannelNotifyProps -> UTCTime -> ChannelData
+ Network.Mattermost: ChannelData :: ChannelId -> UserId -> Text -> ServerTime -> Int -> Int -> ChannelNotifyProps -> ServerTime -> ChannelData
- Network.Mattermost: FileInfo :: FileId -> UserId -> Maybe PostId -> UTCTime -> UTCTime -> UTCTime -> Text -> Text -> Int -> Text -> Maybe Int -> Maybe Int -> Bool -> FileInfo
+ Network.Mattermost: FileInfo :: FileId -> UserId -> Maybe PostId -> ServerTime -> ServerTime -> ServerTime -> Text -> Text -> Int -> Text -> Maybe Int -> Maybe Int -> Bool -> FileInfo
- Network.Mattermost: MinChannel :: Text -> Text -> Maybe Text -> Maybe Text -> Type -> MinChannel
+ Network.Mattermost: MinChannel :: Text -> Text -> Maybe Text -> Maybe Text -> Type -> TeamId -> MinChannel
- Network.Mattermost: MinCommand :: ChannelId -> Text -> Maybe PostId -> Maybe PostId -> MinCommand
+ Network.Mattermost: MinCommand :: ChannelId -> Text -> Maybe PostId -> Maybe PostId -> TeamId -> MinCommand
- Network.Mattermost: PendingPost :: ChannelId -> Maybe UTCTime -> Seq FilePath -> Text -> PendingPostId -> UserId -> Maybe PostId -> Maybe PostId -> PendingPost
+ Network.Mattermost: PendingPost :: ChannelId -> Maybe ServerTime -> Seq FilePath -> Text -> PendingPostId -> UserId -> Maybe PostId -> Maybe PostId -> PendingPost
- Network.Mattermost: Post :: Maybe PostId -> Maybe PostId -> PostProps -> Maybe PostId -> Seq FileId -> PostId -> PostType -> Text -> Maybe UTCTime -> Text -> UTCTime -> Maybe UserId -> UTCTime -> Maybe PostId -> ChannelId -> Bool -> Post
+ Network.Mattermost: Post :: Maybe PostId -> Maybe PostId -> PostProps -> Maybe PostId -> Seq FileId -> PostId -> PostType -> Text -> Maybe ServerTime -> Text -> ServerTime -> ServerTime -> Maybe UserId -> ServerTime -> Maybe PostId -> ChannelId -> Bool -> Post
- Network.Mattermost: Reaction :: UserId -> PostId -> Text -> UTCTime -> Reaction
+ Network.Mattermost: Reaction :: UserId -> PostId -> Text -> ServerTime -> Reaction
- Network.Mattermost: Team :: TeamId -> UTCTime -> UTCTime -> UTCTime -> Text -> Text -> Text -> Type -> Text -> Text -> Id -> Bool -> Team
+ Network.Mattermost: Team :: TeamId -> ServerTime -> ServerTime -> ServerTime -> Text -> Text -> Text -> Type -> Text -> Text -> Id -> Bool -> Team
- Network.Mattermost: User :: UserId -> UTCTime -> UTCTime -> UTCTime -> Text -> Text -> Text -> Text -> Bool -> Text -> Text -> Text -> Text -> UserNotifyProps -> Maybe UTCTime -> Maybe UTCTime -> Text -> User
+ Network.Mattermost: User :: UserId -> ServerTime -> ServerTime -> ServerTime -> Text -> Text -> Text -> Text -> Bool -> Text -> Text -> Text -> Text -> UserNotifyProps -> Maybe ServerTime -> Maybe ServerTime -> Text -> User
- Network.Mattermost: [channelCreateAt] :: Channel -> UTCTime
+ Network.Mattermost: [channelCreateAt] :: Channel -> ServerTime
- Network.Mattermost: [channelDataLastUpdateAt] :: ChannelData -> UTCTime
+ Network.Mattermost: [channelDataLastUpdateAt] :: ChannelData -> ServerTime
- Network.Mattermost: [channelDataLastViewedAt] :: ChannelData -> UTCTime
+ Network.Mattermost: [channelDataLastViewedAt] :: ChannelData -> ServerTime
- Network.Mattermost: [channelDeleteAt] :: Channel -> UTCTime
+ Network.Mattermost: [channelDeleteAt] :: Channel -> ServerTime
- Network.Mattermost: [channelExtraUpdateAt] :: Channel -> UTCTime
+ Network.Mattermost: [channelExtraUpdateAt] :: Channel -> ServerTime
- Network.Mattermost: [channelLastPostAt] :: Channel -> UTCTime
+ Network.Mattermost: [channelLastPostAt] :: Channel -> ServerTime
- Network.Mattermost: [channelUpdateAt] :: Channel -> UTCTime
+ Network.Mattermost: [channelUpdateAt] :: Channel -> ServerTime
- Network.Mattermost: [fileInfoCreateAt] :: FileInfo -> UTCTime
+ Network.Mattermost: [fileInfoCreateAt] :: FileInfo -> ServerTime
- Network.Mattermost: [fileInfoDeleteAt] :: FileInfo -> UTCTime
+ Network.Mattermost: [fileInfoDeleteAt] :: FileInfo -> ServerTime
- Network.Mattermost: [fileInfoUpdateAt] :: FileInfo -> UTCTime
+ Network.Mattermost: [fileInfoUpdateAt] :: FileInfo -> ServerTime
- Network.Mattermost: [pendingPostCreateAt] :: PendingPost -> Maybe UTCTime
+ Network.Mattermost: [pendingPostCreateAt] :: PendingPost -> Maybe ServerTime
- Network.Mattermost: [postCreateAt] :: Post -> UTCTime
+ Network.Mattermost: [postCreateAt] :: Post -> ServerTime
- Network.Mattermost: [postDeleteAt] :: Post -> Maybe UTCTime
+ Network.Mattermost: [postDeleteAt] :: Post -> Maybe ServerTime
- Network.Mattermost: [postUpdateAt] :: Post -> UTCTime
+ Network.Mattermost: [postUpdateAt] :: Post -> ServerTime
- Network.Mattermost: [reactionCreateAt] :: Reaction -> UTCTime
+ Network.Mattermost: [reactionCreateAt] :: Reaction -> ServerTime
- Network.Mattermost: [teamCreateAt] :: Team -> UTCTime
+ Network.Mattermost: [teamCreateAt] :: Team -> ServerTime
- Network.Mattermost: [teamDeleteAt] :: Team -> UTCTime
+ Network.Mattermost: [teamDeleteAt] :: Team -> ServerTime
- Network.Mattermost: [teamUpdateAt] :: Team -> UTCTime
+ Network.Mattermost: [teamUpdateAt] :: Team -> ServerTime
- Network.Mattermost: [userCreateAt] :: User -> UTCTime
+ Network.Mattermost: [userCreateAt] :: User -> ServerTime
- Network.Mattermost: [userDeleteAt] :: User -> UTCTime
+ Network.Mattermost: [userDeleteAt] :: User -> ServerTime
- Network.Mattermost: [userLastPasswordUpdate] :: User -> Maybe UTCTime
+ Network.Mattermost: [userLastPasswordUpdate] :: User -> Maybe ServerTime
- Network.Mattermost: [userLastPictureUpdate] :: User -> Maybe UTCTime
+ Network.Mattermost: [userLastPictureUpdate] :: User -> Maybe ServerTime
- Network.Mattermost: [userUpdateAt] :: User -> UTCTime
+ Network.Mattermost: [userUpdateAt] :: User -> ServerTime
- Network.Mattermost: mmGetPostsSince :: Session -> TeamId -> ChannelId -> UTCTime -> IO Posts
+ Network.Mattermost: mmGetPostsSince :: Session -> TeamId -> ChannelId -> ServerTime -> IO Posts
- Network.Mattermost.Lenses: channelCreateAtL :: Lens' Channel UTCTime
+ Network.Mattermost.Lenses: channelCreateAtL :: Lens' Channel ServerTime
- Network.Mattermost.Lenses: channelDataLastUpdateAtL :: Lens' ChannelData UTCTime
+ Network.Mattermost.Lenses: channelDataLastUpdateAtL :: Lens' ChannelData ServerTime
- Network.Mattermost.Lenses: channelDataLastViewedAtL :: Lens' ChannelData UTCTime
+ Network.Mattermost.Lenses: channelDataLastViewedAtL :: Lens' ChannelData ServerTime
- Network.Mattermost.Lenses: channelDeleteAtL :: Lens' Channel UTCTime
+ Network.Mattermost.Lenses: channelDeleteAtL :: Lens' Channel ServerTime
- Network.Mattermost.Lenses: channelExtraUpdateAtL :: Lens' Channel UTCTime
+ Network.Mattermost.Lenses: channelExtraUpdateAtL :: Lens' Channel ServerTime
- Network.Mattermost.Lenses: channelLastPostAtL :: Lens' Channel UTCTime
+ Network.Mattermost.Lenses: channelLastPostAtL :: Lens' Channel ServerTime
- Network.Mattermost.Lenses: channelUpdateAtL :: Lens' Channel UTCTime
+ Network.Mattermost.Lenses: channelUpdateAtL :: Lens' Channel ServerTime
- Network.Mattermost.Lenses: pendingPostCreateAtL :: Lens' PendingPost (Maybe UTCTime)
+ Network.Mattermost.Lenses: pendingPostCreateAtL :: Lens' PendingPost (Maybe ServerTime)
- Network.Mattermost.Lenses: postCreateAtL :: Lens' Post UTCTime
+ Network.Mattermost.Lenses: postCreateAtL :: Lens' Post ServerTime
- Network.Mattermost.Lenses: postDeleteAtL :: Lens' Post (Maybe UTCTime)
+ Network.Mattermost.Lenses: postDeleteAtL :: Lens' Post (Maybe ServerTime)
- Network.Mattermost.Lenses: postUpdateAtL :: Lens' Post UTCTime
+ Network.Mattermost.Lenses: postUpdateAtL :: Lens' Post ServerTime
- Network.Mattermost.Lenses: reactionCreateAtL :: Lens' Reaction UTCTime
+ Network.Mattermost.Lenses: reactionCreateAtL :: Lens' Reaction ServerTime
- Network.Mattermost.Lenses: teamCreateAtL :: Lens' Team UTCTime
+ Network.Mattermost.Lenses: teamCreateAtL :: Lens' Team ServerTime
- Network.Mattermost.Lenses: teamDeleteAtL :: Lens' Team UTCTime
+ Network.Mattermost.Lenses: teamDeleteAtL :: Lens' Team ServerTime
- Network.Mattermost.Lenses: teamUpdateAtL :: Lens' Team UTCTime
+ Network.Mattermost.Lenses: teamUpdateAtL :: Lens' Team ServerTime
- Network.Mattermost.Lenses: userCreateAtL :: Lens' User UTCTime
+ Network.Mattermost.Lenses: userCreateAtL :: Lens' User ServerTime
- Network.Mattermost.Lenses: userDeleteAtL :: Lens' User UTCTime
+ Network.Mattermost.Lenses: userDeleteAtL :: Lens' User ServerTime
- Network.Mattermost.Lenses: userLastPasswordUpdateL :: Lens' User (Maybe UTCTime)
+ Network.Mattermost.Lenses: userLastPasswordUpdateL :: Lens' User (Maybe ServerTime)
- Network.Mattermost.Lenses: userLastPictureUpdateL :: Lens' User (Maybe UTCTime)
+ Network.Mattermost.Lenses: userLastPictureUpdateL :: Lens' User (Maybe ServerTime)
- Network.Mattermost.Lenses: userUpdateAtL :: Lens' User UTCTime
+ Network.Mattermost.Lenses: userUpdateAtL :: Lens' User ServerTime
- Network.Mattermost.Types: Channel :: ChannelId -> UTCTime -> UTCTime -> UTCTime -> Maybe TeamId -> Type -> Text -> Text -> Text -> Text -> UTCTime -> Int -> UTCTime -> Maybe UserId -> Channel
+ Network.Mattermost.Types: Channel :: ChannelId -> ServerTime -> ServerTime -> ServerTime -> Maybe TeamId -> Type -> Text -> Text -> Text -> Text -> ServerTime -> Int -> ServerTime -> Maybe UserId -> Channel
- Network.Mattermost.Types: ChannelData :: ChannelId -> UserId -> Text -> UTCTime -> Int -> Int -> ChannelNotifyProps -> UTCTime -> ChannelData
+ Network.Mattermost.Types: ChannelData :: ChannelId -> UserId -> Text -> ServerTime -> Int -> Int -> ChannelNotifyProps -> ServerTime -> ChannelData
- Network.Mattermost.Types: Command :: CommandId -> Token -> UTCTime -> UTCTime -> UTCTime -> UserId -> TeamId -> Text -> Text -> Text -> Text -> Bool -> Text -> Text -> Text -> Text -> Text -> Command
+ Network.Mattermost.Types: Command :: CommandId -> Token -> ServerTime -> ServerTime -> ServerTime -> UserId -> TeamId -> Text -> Text -> Text -> Text -> Bool -> Text -> Text -> Text -> Text -> Text -> Command
- Network.Mattermost.Types: FileInfo :: FileId -> UserId -> Maybe PostId -> UTCTime -> UTCTime -> UTCTime -> Text -> Text -> Int -> Text -> Maybe Int -> Maybe Int -> Bool -> FileInfo
+ Network.Mattermost.Types: FileInfo :: FileId -> UserId -> Maybe PostId -> ServerTime -> ServerTime -> ServerTime -> Text -> Text -> Int -> Text -> Maybe Int -> Maybe Int -> Bool -> FileInfo
- Network.Mattermost.Types: MinChannel :: Text -> Text -> Maybe Text -> Maybe Text -> Type -> MinChannel
+ Network.Mattermost.Types: MinChannel :: Text -> Text -> Maybe Text -> Maybe Text -> Type -> TeamId -> MinChannel
- Network.Mattermost.Types: MinCommand :: ChannelId -> Text -> Maybe PostId -> Maybe PostId -> MinCommand
+ Network.Mattermost.Types: MinCommand :: ChannelId -> Text -> Maybe PostId -> Maybe PostId -> TeamId -> MinCommand
- Network.Mattermost.Types: PendingPost :: ChannelId -> Maybe UTCTime -> Seq FilePath -> Text -> PendingPostId -> UserId -> Maybe PostId -> Maybe PostId -> PendingPost
+ Network.Mattermost.Types: PendingPost :: ChannelId -> Maybe ServerTime -> Seq FilePath -> Text -> PendingPostId -> UserId -> Maybe PostId -> Maybe PostId -> PendingPost
- Network.Mattermost.Types: Post :: Maybe PostId -> Maybe PostId -> PostProps -> Maybe PostId -> Seq FileId -> PostId -> PostType -> Text -> Maybe UTCTime -> Text -> UTCTime -> Maybe UserId -> UTCTime -> Maybe PostId -> ChannelId -> Bool -> Post
+ Network.Mattermost.Types: Post :: Maybe PostId -> Maybe PostId -> PostProps -> Maybe PostId -> Seq FileId -> PostId -> PostType -> Text -> Maybe ServerTime -> Text -> ServerTime -> ServerTime -> Maybe UserId -> ServerTime -> Maybe PostId -> ChannelId -> Bool -> Post
- Network.Mattermost.Types: Reaction :: UserId -> PostId -> Text -> UTCTime -> Reaction
+ Network.Mattermost.Types: Reaction :: UserId -> PostId -> Text -> ServerTime -> Reaction
- Network.Mattermost.Types: Team :: TeamId -> UTCTime -> UTCTime -> UTCTime -> Text -> Text -> Text -> Type -> Text -> Text -> Id -> Bool -> Team
+ Network.Mattermost.Types: Team :: TeamId -> ServerTime -> ServerTime -> ServerTime -> Text -> Text -> Text -> Type -> Text -> Text -> Id -> Bool -> Team
- Network.Mattermost.Types: User :: UserId -> UTCTime -> UTCTime -> UTCTime -> Text -> Text -> Text -> Text -> Bool -> Text -> Text -> Text -> Text -> UserNotifyProps -> Maybe UTCTime -> Maybe UTCTime -> Text -> User
+ Network.Mattermost.Types: User :: UserId -> ServerTime -> ServerTime -> ServerTime -> Text -> Text -> Text -> Text -> Bool -> Text -> Text -> Text -> Text -> UserNotifyProps -> Maybe ServerTime -> Maybe ServerTime -> Text -> User
- Network.Mattermost.Types: [channelCreateAt] :: Channel -> UTCTime
+ Network.Mattermost.Types: [channelCreateAt] :: Channel -> ServerTime
- Network.Mattermost.Types: [channelDataLastUpdateAt] :: ChannelData -> UTCTime
+ Network.Mattermost.Types: [channelDataLastUpdateAt] :: ChannelData -> ServerTime
- Network.Mattermost.Types: [channelDataLastViewedAt] :: ChannelData -> UTCTime
+ Network.Mattermost.Types: [channelDataLastViewedAt] :: ChannelData -> ServerTime
- Network.Mattermost.Types: [channelDeleteAt] :: Channel -> UTCTime
+ Network.Mattermost.Types: [channelDeleteAt] :: Channel -> ServerTime
- Network.Mattermost.Types: [channelExtraUpdateAt] :: Channel -> UTCTime
+ Network.Mattermost.Types: [channelExtraUpdateAt] :: Channel -> ServerTime
- Network.Mattermost.Types: [channelLastPostAt] :: Channel -> UTCTime
+ Network.Mattermost.Types: [channelLastPostAt] :: Channel -> ServerTime
- Network.Mattermost.Types: [channelUpdateAt] :: Channel -> UTCTime
+ Network.Mattermost.Types: [channelUpdateAt] :: Channel -> ServerTime
- Network.Mattermost.Types: [commandCreateAt] :: Command -> UTCTime
+ Network.Mattermost.Types: [commandCreateAt] :: Command -> ServerTime
- Network.Mattermost.Types: [commandDeleteAt] :: Command -> UTCTime
+ Network.Mattermost.Types: [commandDeleteAt] :: Command -> ServerTime
- Network.Mattermost.Types: [commandUpdateAt] :: Command -> UTCTime
+ Network.Mattermost.Types: [commandUpdateAt] :: Command -> ServerTime
- Network.Mattermost.Types: [fileInfoCreateAt] :: FileInfo -> UTCTime
+ Network.Mattermost.Types: [fileInfoCreateAt] :: FileInfo -> ServerTime
- Network.Mattermost.Types: [fileInfoDeleteAt] :: FileInfo -> UTCTime
+ Network.Mattermost.Types: [fileInfoDeleteAt] :: FileInfo -> ServerTime
- Network.Mattermost.Types: [fileInfoUpdateAt] :: FileInfo -> UTCTime
+ Network.Mattermost.Types: [fileInfoUpdateAt] :: FileInfo -> ServerTime
- Network.Mattermost.Types: [pendingPostCreateAt] :: PendingPost -> Maybe UTCTime
+ Network.Mattermost.Types: [pendingPostCreateAt] :: PendingPost -> Maybe ServerTime
- Network.Mattermost.Types: [postCreateAt] :: Post -> UTCTime
+ Network.Mattermost.Types: [postCreateAt] :: Post -> ServerTime
- Network.Mattermost.Types: [postDeleteAt] :: Post -> Maybe UTCTime
+ Network.Mattermost.Types: [postDeleteAt] :: Post -> Maybe ServerTime
- Network.Mattermost.Types: [postUpdateAt] :: Post -> UTCTime
+ Network.Mattermost.Types: [postUpdateAt] :: Post -> ServerTime
- Network.Mattermost.Types: [reactionCreateAt] :: Reaction -> UTCTime
+ Network.Mattermost.Types: [reactionCreateAt] :: Reaction -> ServerTime
- Network.Mattermost.Types: [teamCreateAt] :: Team -> UTCTime
+ Network.Mattermost.Types: [teamCreateAt] :: Team -> ServerTime
- Network.Mattermost.Types: [teamDeleteAt] :: Team -> UTCTime
+ Network.Mattermost.Types: [teamDeleteAt] :: Team -> ServerTime
- Network.Mattermost.Types: [teamUpdateAt] :: Team -> UTCTime
+ Network.Mattermost.Types: [teamUpdateAt] :: Team -> ServerTime
- Network.Mattermost.Types: [userCreateAt] :: User -> UTCTime
+ Network.Mattermost.Types: [userCreateAt] :: User -> ServerTime
- Network.Mattermost.Types: [userDeleteAt] :: User -> UTCTime
+ Network.Mattermost.Types: [userDeleteAt] :: User -> ServerTime
- Network.Mattermost.Types: [userLastPasswordUpdate] :: User -> Maybe UTCTime
+ Network.Mattermost.Types: [userLastPasswordUpdate] :: User -> Maybe ServerTime
- Network.Mattermost.Types: [userLastPictureUpdate] :: User -> Maybe UTCTime
+ Network.Mattermost.Types: [userLastPictureUpdate] :: User -> Maybe ServerTime
- Network.Mattermost.Types: [userUpdateAt] :: User -> UTCTime
+ Network.Mattermost.Types: [userUpdateAt] :: User -> ServerTime
- Network.Mattermost.Util: withConnection :: ConnectionData -> (Connection -> IO a) -> IO a
+ Network.Mattermost.Util: withConnection :: ConnectionData -> (MMConn -> IO a) -> IO a
Files
- CHANGELOG.md +27/−0
- README.md +1/−1
- examples/GetChannels.hs +7/−6
- examples/GetPosts.hs +11/−7
- examples/GetTeams.hs +5/−3
- examples/LocalConfig.hs +3/−3
- examples/MakePost.hs +20/−10
- mattermost-api.cabal +4/−1
- src/Network/Mattermost.hs +14/−21
- src/Network/Mattermost/Connection.hs +174/−0
- src/Network/Mattermost/Endpoints.hs +4014/−0
- src/Network/Mattermost/Exceptions.hs +23/−0
- src/Network/Mattermost/Types.hs +533/−61
- src/Network/Mattermost/Types/Base.hs +9/−0
- src/Network/Mattermost/Types/Config.hs +666/−0
- src/Network/Mattermost/Util.hs +21/−3
- src/Network/Mattermost/WebSocket.hs +6/−0
- src/Network/Mattermost/WebSocket/Types.hs +27/−0
- test/Main.hs +72/−35
- test/Tests/Types.hs +11/−10
- test/Tests/Util.hs +91/−48
CHANGELOG.md view
@@ -1,3 +1,30 @@+40600.0.0+=========++API changes:+ * This release provides implementations of many of Mattermost's version+ 4 API endpoints in the new Network.Mattermost.Endpoints module. The+ old version 3 API is still provided by Network.Mattermost but will+ be deprecated in a future release, and removed after that. Note+ that this release chiefly exposes version 4 endpoints used by the+ Matterhorn application; endpoints not used there have not been tested+ and so are left commented out in this release and may be enabled in+ future releases as needed.+ * This release also provides first-class Haskell types corresponding to+ the server-side configuration; see Network.Mattermost.Types.Config.+ * The Post data type got a new postEditAt field corresponding to the+ (at the time) undocumented `edit_at` field of posts.+ * Websockets got action support; see+ Network.Mattermost.WebSocket.mmSendWSAction and the new+ WebsocketAction type (thanks to Abhinav Sarkar for this change)+ * All UTCTimes received from the Mattermost server are wrapped in a+ `ServerTime` newtype to ensure that users cannot accidentally compare+ such timestamps to local UTCTimes, since the server time is not+ necessarily comparable.+ * Added Network.Mattermost.Endpoints.mmGetClientConfig to get the+ client configuration from the server (Thanks to Kelly McLaughlin for+ this change)+ 40400.0.0 =========
README.md view
@@ -1,4 +1,4 @@-[](https://hackage.haskell.org/package/mattermost-api) [](https://travis-ci.org/matterhorn-chat/mattermost-api) # mattermost-api Client side API for communicating with a Mattermost server, in Haskell.
examples/GetChannels.hs view
@@ -9,7 +9,9 @@ import Data.Foldable import Control.Monad ( when, join ) -import Network.Mattermost+import Network.Mattermost.Endpoints+import Network.Mattermost.Types+import Network.Mattermost.Util import Config import LocalConfig -- You will need to define a function:@@ -31,11 +33,10 @@ putStrLn "Authenticated as:" pPrint mmUser - i <- mmGetInitialLoad session- forM_ (initialLoadTeams i) $ \t -> do+ teams <- mmGetUsersTeams UserMe session+ forM_ teams $ \t -> do when (teamName t == configTeam config) $ do- chans <- mmGetChannels session (teamId t)+ chans <- mmGetChannelsForUser UserMe (getId t) session forM_ chans $ \chan -> do- channel <- mmGetChannel session (teamId t) (channelId chan)- pPrint channel+ pPrint chan putStrLn ""
examples/GetPosts.hs view
@@ -19,7 +19,8 @@ import System.Console.GetOpt import System.Environment ( getArgs, getProgName ) -import Network.Mattermost+import Network.Mattermost.Endpoints+import Network.Mattermost.Types import Network.Mattermost.Logging import Network.Mattermost.Util @@ -113,20 +114,23 @@ putStrLn "Authenticated as:" pPrint mmUser - i <- mmGetInitialLoad session+ teams <- mmGetUsersTeams UserMe session when (optVerbose opts) $ do- pPrint i- forM_ (initialLoadTeams i) $ \t -> do+ pPrint teams+ forM_ teams $ \t -> do when (teamName t == configTeam config) $ do- userMap <- mmGetProfiles session (getId t) 0 10000+ users <- mmGetUsers (defaultUserQuery { userQueryInTeam = Just (getId t), userQueryPerPage = Just 1000 }) session+ let userMap = HM.fromList [ (getId u, u) | u <- toList users ] when (optVerbose opts) $ do pPrint userMap- chans <- mmGetChannels session (getId t)+ chans <- mmGetChannelsForUser UserMe (getId t) session forM_ chans $ \chan -> do when (optVerbose opts) $ do pPrint chan when (channelName chan == optChannel opts) $ do- posts <- mmGetPosts session (getId t) (getId chan) (optOffset opts) (optLimit opts)+ posts <- mmGetPostsForChannel (getId chan) defaultPostQuery { postQueryPage = Just (optOffset opts)+ , postQueryPerPage = Just (optLimit opts)+ } session forM_ (reverse (toList (postsOrder posts))) $ \postId -> do -- this is just a toy program, so we don't care about -- this pattern match failure
examples/GetTeams.hs view
@@ -6,7 +6,9 @@ import Network.Connection import System.Process ( readProcess ) -import Network.Mattermost+import Network.Mattermost.Endpoints+import Network.Mattermost.Types+import Network.Mattermost.Util import Config import LocalConfig -- You will need to define a function:@@ -27,5 +29,5 @@ (session, mmUser) <- join (hoistE <$> mmLogin cd login) putStrLn "Authenticated as: " pPrint mmUser- i <- mmGetInitialLoad session- pPrint $ initialLoadTeams i+ teams <- mmGetUsersTeams UserMe session+ pPrint $ teams
examples/LocalConfig.hs view
@@ -9,9 +9,9 @@ let cmd = words "pass ldap" pass <- takeWhile (/='\n') <$> readProcess (head cmd) (tail cmd) "" return $ Config- { configUsername = T.pack "gdritter"- , configHostname = T.pack "matterhorn-dev.galois.com"- , configTeam = T.pack "galwegians"+ { configUsername = T.pack "USERNAME"+ , configHostname = T.pack "mattermost.example.com"+ , configTeam = T.pack "TEAMNAME" , configPort = 443 -- currently we only support HTTPS , configPassword = T.pack pass }
examples/MakePost.hs view
@@ -18,7 +18,8 @@ import System.Console.GetOpt import System.Environment ( getArgs, getProgName ) -import Network.Mattermost+import Network.Mattermost.Endpoints+import Network.Mattermost.Types import Network.Mattermost.Util import Config@@ -86,22 +87,31 @@ putStrLn "Authenticated as:" pPrint mmUser - i <- mmGetInitialLoad session+ teams <- mmGetUsersTeams UserMe session when (optVerbose opts) $ do- pPrint i- forM_ (initialLoadTeams i) $ \t -> do+ pPrint teams+ forM_ teams $ \t -> do when (teamName t == configTeam config) $ do- userMap <- mmGetProfiles session (getId t) 0 10000+ users <- mmGetUsers (defaultUserQuery { userQueryInTeam = Just (getId t)+ , userQueryPerPage = Just 1000+ }) session+ let userMap = HM.fromList [ (getId u, u) | u <- toList users ] when (optVerbose opts) $ do pPrint userMap- chans <- mmGetChannels session (getId t)+ chans <- mmGetChannelsForUser UserMe (getId t) session forM_ chans $ \chan -> do when (optVerbose opts) $ do pPrint chan when (channelName chan == optChannel opts) $ do when (not (T.null (optMessage opts))) $ do- pendingPost <- mkPendingPost (optMessage opts)- (getId mmUser)- (getId chan)- post <- mmPost session (getId t) pendingPost+ let pendingPost = RawPost+ { rawPostChannelId = getId chan+ , rawPostMessage = optMessage opts+ , rawPostFileIds = mempty+ , rawPostRootId = Nothing+ }+ -- pendingPost <- mkPendingPost (optMessage opts)+ -- (getId mmUser)+ -- (getId chan)+ post <- mmCreatePost pendingPost session when (optVerbose opts) (pPrint post)
mattermost-api.cabal view
@@ -1,5 +1,5 @@ name: mattermost-api-version: 40400.0.0+version: 40600.0.0 synopsis: Client API for Mattermost chat system description: Client API for Mattermost chat system license: BSD3@@ -32,8 +32,11 @@ Network.Mattermost.Version Network.Mattermost.Types Network.Mattermost.Types.Base+ Network.Mattermost.Types.Config Network.Mattermost.Types.Internal+ Network.Mattermost.Endpoints other-modules: Network.Mattermost.TH+ Network.Mattermost.Connection Paths_mattermost_api -- other-extensions: build-depends: base >=4.4 && <5
src/Network/Mattermost.hs view
@@ -1,7 +1,6 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TupleSections #-}-{-# OPTIONS_GHC -fno-warn-orphans #-} module Network.Mattermost ( -- * Types -- ** Mattermost-Related Types (deprecated: use Network.Mattermost.Types instead)@@ -105,6 +104,7 @@ , mmUpdatePost , mmExecute , mmGetConfig+, mmGetClientConfig , mmSetPreferences , mmSavePreferences , mmDeletePreferences@@ -125,11 +125,6 @@ import Text.Printf ( printf ) import qualified Data.ByteString.Char8 as B import qualified Data.ByteString.Lazy.Char8 as BL-import Data.Time.Clock ( UTCTime )-import Network.Connection ( Connection- , connectionGetLine- , connectionPut- , connectionClose ) import Network.HTTP.Headers ( HeaderName(..) , mkHeader , lookupHeader )@@ -138,7 +133,6 @@ , defaultUserAgent , Response_String , Response(..) )-import Network.Stream as NS ( Stream(..) ) import Network.URI ( URI, parseRelativeReference ) import Network.HTTP.Stream ( simpleHTTP_ ) import Data.HashMap.Strict ( HashMap )@@ -157,25 +151,14 @@ import qualified Data.Text as T import Control.Arrow ( left ) +import Network.Mattermost.Connection() import Network.Mattermost.Exceptions import Network.Mattermost.Util import Network.Mattermost.Types.Base import Network.Mattermost.Types.Internal import Network.Mattermost.Types -maxLineLength :: Int-maxLineLength = 2^(16::Int) --- | This instance allows us to use 'simpleHTTP' from 'Network.HTTP.Stream' with--- connections from the 'connection' package.-instance Stream Connection where- readLine con = Right . B.unpack . dropTrailingChar <$> connectionGetLine maxLineLength con- readBlock con n = Right . B.unpack <$> connectionGetExact con n- writeBlock con block = Right <$> connectionPut con (B.pack block)- close con = connectionClose con- closeOnEnd _ _ = return ()-- -- MM utility functions -- | Parse a path, failing if we cannot.@@ -437,14 +420,14 @@ mmGetPostsSince :: Session -> TeamId -> ChannelId- -> UTCTime+ -> ServerTime -> IO Posts mmGetPostsSince sess teamid chanid since = mmDoRequest sess "mmGetPostsSince" $ printf "/api/v3/teams/%s/channels/%s/posts/since/%d" (idString teamid) (idString chanid)- (utcTimeToMilliseconds since :: Int)+ (timeToServer since) -- | -- route: @\/api\/v3\/teams\/{team_id}\/channels\/{channel_id}\/posts\/{post_id}\/get@@@ -720,6 +703,16 @@ -> IO Value mmGetConfig sess = mmDoRequest sess "mmGetConfig" "/api/v3/admin/config"++-- | Get a subset of the server configuration needed by the client. Does not+-- require administrative permission. The format query parameter is currently+-- required with the value of "old".+--+-- route: @\/api\/v4\/config\/client@+mmGetClientConfig :: Session+ -> IO Value+mmGetClientConfig sess =+ mmDoRequest sess "mmGetClientConfig" "/api/v4/config/client?format=old" mmSaveConfig :: Session -> Value
+ src/Network/Mattermost/Connection.hs view
@@ -0,0 +1,174 @@+module Network.Mattermost.Connection where+++import Control.Arrow (left)+import Control.Exception (throwIO)+import qualified Data.Aeson as A+import qualified Data.ByteString.Char8 as B+import qualified Data.ByteString.Lazy.Char8 as BL+import qualified Data.List as List+import qualified Data.Text as T+import qualified Network.HTTP.Base as HTTP+import qualified Network.HTTP.Headers as HTTP+import qualified Network.HTTP.Stream as HTTP+import qualified Network.URI as URI++import Network.Mattermost.Exceptions+import Network.Mattermost.Types+import Network.Mattermost.Types.Internal+import Network.Mattermost.Util++-- | Parse a path, failing if we cannot.+mmPath :: String -> IO URI.URI+mmPath str =+ noteE (URI.parseRelativeReference str)+ (URIParseException ("mmPath: " ++ str))+++-- | Parse the JSON body out of a request, failing if it isn't an+-- 'application/json' response, or if the parsing failed+jsonResponse :: A.FromJSON t => HTTP.Response_String -> IO t+jsonResponse rsp = do+ contentType <- mmGetHeader rsp HTTP.HdrContentType+ assertE (contentType ~= "application/json")+ (ContentTypeException+ ("Expected content type 'application/json'" +++ " found " ++ contentType))++ hoistE $ left (\s -> JSONDecodeException s (HTTP.rspBody rsp))+ (A.eitherDecode (BL.pack (HTTP.rspBody rsp)))++-- | Parse the JSON body out of a request, failing if it isn't an+-- 'application/json' response, or if the parsing failed+bytestringResponse :: HTTP.Response_String -> IO B.ByteString+bytestringResponse rsp =+ return (B.pack (HTTP.rspBody rsp))+++noResponse :: HTTP.Response_String -> IO ()+noResponse _ = return ()+++-- | Grab a header from the response, failing if it isn't present+mmGetHeader :: HTTP.Response_String -> HTTP.HeaderName -> IO String+mmGetHeader rsp hdr =+ noteE (HTTP.lookupHeader hdr (HTTP.rspHeaders rsp))+ (HeaderNotFoundException ("mmGetHeader: " ++ show hdr))++-- | Parse the JSON body out of a request, failing if it isn't an+-- 'application/json' response, or if the parsing failed+mmGetJSONBody :: A.FromJSON t => String -> HTTP.Response_String -> IO (t)+mmGetJSONBody label rsp = do+ contentType <- mmGetHeader rsp HTTP.HdrContentType+ assertE (contentType ~= "application/json")+ (ContentTypeException+ ("mmGetJSONBody: " ++ label ++ ": " +++ "Expected content type 'application/json'" +++ " found " ++ contentType))++ let value = left (\s -> JSONDecodeException ("mmGetJSONBody: " ++ label ++ ": " ++ s)+ (HTTP.rspBody rsp))+ (A.eitherDecode (BL.pack (HTTP.rspBody rsp)))+ hoistE $ do+ y <- value+ return (y)++doRequest :: HTTP.RequestMethod -> String -> B.ByteString -> Session -> IO HTTP.Response_String+doRequest method uri payload (Session cd token) = do+ path <- mmPath ("/api/v4" ++ uri)+ rawResponse <- withConnection cd $ \con -> do+ let contentLength = B.length payload+ request = HTTP.Request+ { HTTP.rqURI = path+ , HTTP.rqMethod = method+ , HTTP.rqHeaders =+ [ HTTP.mkHeader HTTP.HdrAuthorization ("Bearer " ++ getTokenString token)+ , HTTP.mkHeader HTTP.HdrHost (T.unpack $ cdHostname cd)+ , HTTP.mkHeader HTTP.HdrUserAgent HTTP.defaultUserAgent+ , HTTP.mkHeader HTTP.HdrContentType "application/json"+ , HTTP.mkHeader HTTP.HdrContentLength (show contentLength)+ ] ++ autoCloseToHeader (cdAutoClose cd)+ , HTTP.rqBody = B.unpack payload+ }+ HTTP.simpleHTTP_ con request+ rsp <- hoistE (left ConnectionException rawResponse)+ case HTTP.rspCode rsp of+ (2, _, _) -> return rsp+ code -> do+ case A.eitherDecode (BL.pack (HTTP.rspBody rsp)) of+ Right err ->+ throwIO (err :: MattermostError)+ Left _ ->+ throwIO (HTTPResponseException ("Server returned unexpected " ++ show code ++ " response"))+++mkQueryString :: [Maybe (String, String)] -> String+mkQueryString ls =+ List.intercalate "&" [ k ++ "=" ++ v | Just (k, v) <- ls ]++jsonBody :: A.ToJSON i => i -> B.ByteString+jsonBody = BL.toStrict . A.encode++noBody :: B.ByteString+noBody = B.empty+++inPost+ :: String+ -> B.ByteString+ -> (HTTP.Response_String -> IO o)+ -> Session+ -> IO o+inPost uri payload k session =+ doRequest HTTP.POST uri payload session >>= k++inPut+ :: String+ -> B.ByteString+ -> (HTTP.Response_String -> IO o)+ -> Session+ -> IO o+inPut uri payload k session =+ doRequest HTTP.PUT uri payload session >>= k++inGet+ :: String+ -> B.ByteString+ -> (HTTP.Response_String -> IO o)+ -> Session+ -> IO o+inGet uri payload k session =+ doRequest HTTP.GET uri payload session >>= k++inDelete+ :: String+ -> B.ByteString+ -> (HTTP.Response_String -> IO o)+ -> Session+ -> IO o+inDelete uri payload k session =+ doRequest HTTP.DELETE uri payload session >>= k++++doUnauthRequest :: HTTP.RequestMethod -> String -> B.ByteString -> ConnectionData -> IO HTTP.Response_String+doUnauthRequest method uri payload cd = do+ path <- mmPath ("/api/v4" ++ uri)+ rawResponse <- withConnection cd $ \con -> do+ let contentLength = B.length payload+ request = HTTP.Request+ { HTTP.rqURI = path+ , HTTP.rqMethod = method+ , HTTP.rqHeaders =+ [ HTTP.mkHeader HTTP.HdrHost (T.unpack $ cdHostname cd)+ , HTTP.mkHeader HTTP.HdrUserAgent HTTP.defaultUserAgent+ , HTTP.mkHeader HTTP.HdrContentType "application/json"+ , HTTP.mkHeader HTTP.HdrContentLength (show contentLength)+ ] ++ autoCloseToHeader (cdAutoClose cd)+ , HTTP.rqBody = B.unpack payload+ }+ HTTP.simpleHTTP_ con request+ rsp <- hoistE (left ConnectionException rawResponse)+ case HTTP.rspCode rsp of+ (2, _, _) -> return rsp+ code -> throwIO (HTTPResponseException ("Server returned unexpected " ++ show code ++ " response"))
+ src/Network/Mattermost/Endpoints.hs view
@@ -0,0 +1,4014 @@+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE OverloadedStrings #-}++module Network.Mattermost.Endpoints where++import qualified Data.Aeson as A+import qualified Data.ByteString.Char8 as B+import qualified Data.HashMap.Strict as HM+import Data.Sequence (Seq)+import Data.Text (Text)+import qualified Data.Text as T+import Data.Time.Clock ( UTCTime )+import qualified Network.HTTP.Base as HTTP+import qualified Network.HTTP.Headers as HTTP+import Text.Printf (printf)++import Network.Mattermost.Connection+import Network.Mattermost.Exceptions+import Network.Mattermost.Types+import Network.Mattermost.Types.Config+import Network.Mattermost.Types.Internal+++mmLogin :: ConnectionData -> Login -> IO (Either LoginFailureException (Session, User))+mmLogin cd login = do+ rsp <- doUnauthRequest HTTP.POST "/users/login" (jsonBody login) cd+ case HTTP.rspCode rsp of+ (2, _, _) -> do+ token <- mmGetHeader rsp (HTTP.HdrCustom "Token")+ value <- mmGetJSONBody "User" rsp+ return (Right (Session cd (Token token), value))+ _ ->+ let eMsg = "Server returned unexpected " ++ show (HTTP.rspCode rsp) ++ " response"+ in return (Left (LoginFailureException eMsg))++mmInitialUser :: ConnectionData -> UsersCreate -> IO User+mmInitialUser cd users = do+ rsp <- doUnauthRequest HTTP.POST "/users" (jsonBody users) cd+ case HTTP.rspCode rsp of+ (2, _, _) -> mmGetJSONBody "User" rsp+ _ -> error ("Server returned unexpected " ++ show (HTTP.rspCode rsp) ++ " response")++-- * Endpoints++-- * Brand++-- -- | Uploads a brand image.+-- --+-- -- /Permissions/: Must have @manage_system@ permission.+-- mmUploadBrandImage :: Session -> IO ()+-- mmUploadBrandImage =+-- inPost "/brand/image" noBody jsonResponse++-- -- | Get the previously uploaded brand image. Returns 404 if no brand image+-- -- has been uploaded.+-- --+-- -- /Permissions/: No permission required.+-- mmGetBrandImage :: Session -> IO Text+-- mmGetBrandImage =+-- inGet "/brand/image" noBody jsonResponse++++-- * Channels++-- | Get all channel members on a team for a user.+--+-- /Permissions/: Logged in as the user and @view_team@ permission for+-- the team. Having @manage_system@ permission voids the previous+-- requirements.+mmGetChannelMembersForUser :: UserParam -> TeamId -> Session -> IO (Seq ChannelMember)+mmGetChannelMembersForUser userId teamId =+ inGet (printf "/users/%s/teams/%s/channels/members" userId teamId) noBody jsonResponse++-- | Get all the channels on a team for a user.+--+-- /Permissions/: Logged in as the user, or have @edit_other_users@+-- permission, and @view_team@ permission for the team.+mmGetChannelsForUser :: UserParam -> TeamId -> Session -> IO (Seq Channel)+mmGetChannelsForUser userId teamId =+ inGet (printf "/users/%s/teams/%s/channels" userId teamId) noBody jsonResponse++-- -- | Get a list of channel members based on the provided user ids.+-- --+-- -- /Permissions/: Must have the @read_channel@ permission.+-- mmGetChannelMembersByIds :: ChannelId -> (Seq Text) -> Session -> IO (Seq ChannelMember)+-- mmGetChannelMembersByIds channelId body =+-- inPost (printf "/channels/%s/members/ids" channelId) (jsonBody body) jsonResponse++-- | Perform all the actions involved in viewing a channel. This includes+-- marking channels as read, clearing push notifications, and updating+-- the active channel.+--+-- /Permissions/: Must be logged in as user or have @edit_other_users@+-- permission.+mmViewChannel :: UserParam -> ChannelId -> Maybe ChannelId -> Session -> IO ()+mmViewChannel userId chanId prevChanIdMb =+ inPost (printf "/channels/members/%s/view" userId) (jsonBody body) noResponse+ where body = HM.fromList $+ ("channel_id" :: T.Text, chanId)+ : case prevChanIdMb of+ Just prevChanId -> [ ("prev_channel_id", prevChanId) ]+ Nothing -> []++-- | Create a new group message channel to group of users. If the logged in+-- user's id is not included in the list, it will be appended to the end.+--+-- /Permissions/: Must have @create_group_channel@ permission.+mmCreateGroupMessageChannel :: Seq UserId -> Session -> IO Channel+mmCreateGroupMessageChannel body =+ inPost "/channels/group" (jsonBody body) jsonResponse++-- | Get the total unread messages and mentions for a channel for a user.+--+-- /Permissions/: Must be logged in as user and have the @read_channel@+-- permission, or have @edit_other_usrs@ permission.+mmGetUnreadMessages :: UserParam -> ChannelId -> Session -> IO ChannelUnread+mmGetUnreadMessages userId channelId =+ inGet (printf "/users/%s/channels/%s/unread" userId channelId) noBody jsonResponse++-- -- | Gets a channel from the provided team name and channel name strings.+-- --+-- -- /Permissions/: @read_channel@ permission for the channel.+-- mmGetChannelByNameAndTeamName :: Text -> Text -> Session -> IO Channel+-- mmGetChannelByNameAndTeamName teamName channelName =+-- inGet (printf "/teams/name/%s/channels/name/%s" teamName channelName) noBody jsonResponse++-- | Get a list of public channels on a team by id.+--+-- /Permissions/: @view_team@ for the team the channels are on.+mmGetListOfChannelsByIds :: TeamId -> Seq ChannelId -> Session -> IO (Seq Channel)+mmGetListOfChannelsByIds teamId body =+ inPost (printf "/teams/%s/channels/ids" teamId) (jsonBody body) jsonResponse++-- | Partially update a channel by providing only the fields you want to+-- update. Omitted fields will not be updated. The fields that can be+-- updated are defined in the request body, all other provided fields+-- will be ignored.+--+-- /Permissions/: If updating a public channel,+-- @manage_public_channel_members@ permission is required. If updating a+-- private channel, @manage_private_channel_members@ permission is+-- required.+mmPatchChannel :: ChannelId -> ChannelPatch -> Session -> IO Channel+mmPatchChannel channelId body =+ inPut (printf "/channels/%s/patch" channelId) (jsonBody body) jsonResponse++-- | Create a new direct message channel between two users.+--+-- /Permissions/: Must be one of the two users and have+-- @create_direct_channel@ permission. Having the @manage_system@+-- permission voids the previous requirements.+mmCreateDirectMessageChannel :: (UserId, UserId) -> Session -> IO Channel+mmCreateDirectMessageChannel body =+ inPost "/channels/direct" (jsonBody body) jsonResponse++-- -- | Get a list of pinned posts for channel.+-- mmGetChannelsPinnedPosts :: ChannelId -> Session -> IO PostList+-- mmGetChannelsPinnedPosts channelId =+-- inGet (printf "/channels/%s/pinned" channelId) noBody jsonResponse++-- | Get statistics for a channel.+--+-- /Permissions/: Must have the @read_channel@ permission.+mmGetChannelStatistics :: ChannelId -> Session -> IO ChannelStats+mmGetChannelStatistics channelId =+ inGet (printf "/channels/%s/stats" channelId) noBody jsonResponse++-- -- | Update a user's notification properties for a channel. Only the+-- -- provided fields are updated.+-- --+-- -- /Permissions/: Must be logged in as the user or have+-- -- @edit_other_users@ permission.+-- mmUpdateChannelNotifications :: ChannelId -> UserId -> XX17 -> Session -> IO ()+-- mmUpdateChannelNotifications channelId userId body =+-- inPut (printf "/channels/%s/members/%s/notify_props" channelId userId) (jsonBody body) jsonResponse++-- | Add a user to the channel.+mmAddUser :: ChannelId -> MinChannelMember -> Session -> IO ChannelMember+mmAddUser channelId body =+ inPost (printf "/channels/%s/members" channelId) (jsonBody body) jsonResponse++-- -- | Get a page of members for a channel.+-- --+-- -- /Permissions/: @read_channel@ permission for the channel.+-- mmGetChannelMembers :: ChannelId -> Maybe Integer -> Maybe Integer -> Session -> IO (Seq ChannelMember)+-- mmGetChannelMembers channelId page perPage =+-- inGet (printf "/channels/%s/members?%s" channelId (mkQueryString [ sequence ("page", fmap show page) , sequence ("per_page", fmap show perPage) ])) noBody jsonResponse++-- | Create a new channel.+--+-- /Permissions/: If creating a public channel, @create_public_channel@+-- permission is required. If creating a private channel,+-- @create_private_channel@ permission is required.+mmCreateChannel :: MinChannel -> Session -> IO Channel+mmCreateChannel body =+ inPost "/channels" (jsonBody body) jsonResponse++-- | Gets channel from the provided team id and channel name strings.+--+-- /Permissions/: @read_channel@ permission for the channel.+mmGetChannelByName :: TeamId -> Text -> Session -> IO Channel+mmGetChannelByName teamId channelName =+ inGet (printf "/teams/%s/channels/name/%s" teamId channelName) noBody jsonResponse++-- -- | Update a user's roles for a channel.+-- --+-- -- /Permissions/: Must have @manage_channel_roles@ permission for the+-- -- channel.+-- mmUpdateChannelRoles :: ChannelId -> UserId -> Text -> Session -> IO ()+-- mmUpdateChannelRoles channelId userId roles =+-- inPut (printf "/channels/%s/members/%s/roles" channelId userId) (jsonBody (A.object [ "roles" A..= roles ])) jsonResponse++-- -- | Update a channel. The fields that can be updated are listed as+-- -- paramters. Omitted fields will be treated as blanks.+-- --+-- -- /Permissions/: If updating a public channel,+-- -- @manage_public_channel_members@ permission is required. If updating a+-- -- private channel, @manage_private_channel_members@ permission is+-- -- required.+-- mmUpdateChannel :: ChannelId -> XX28 -> Session -> IO Channel+-- mmUpdateChannel channelId body =+-- inPut (printf "/channels/%s" channelId) (jsonBody body) jsonResponse++-- | Get channel from the provided channel id string.+--+-- /Permissions/: @read_channel@ permission for the channel.+mmGetChannel :: ChannelId -> Session -> IO Channel+mmGetChannel channelId =+ inGet (printf "/channels/%s" channelId) noBody jsonResponse++-- | Delete a channel based from provided channel id string.+--+-- /Permissions/: @delete_public_channel@ permission if the channel is+-- public,+--+-- @delete_private_channel@ permission if the channel is private,+--+-- or have @manage_system@ permission.+mmDeleteChannel :: ChannelId -> Session -> IO ()+mmDeleteChannel channelId =+ inDelete (printf "/channels/%s" channelId) noBody noResponse++-- -- | Restore channel from the provided channel id string.+-- --+-- --+-- -- /Minimum server version/: 3.10+-- --+-- --+-- -- /Permissions/: @manage_team@ permission for the team of channel.+-- mmRestoreChannel :: ChannelId -> Session -> IO Channel+-- mmRestoreChannel channelId =+-- inPost (printf "/channels/%s/restore" channelId) noBody jsonResponse++-- | Get a channel member.+--+-- /Permissions/: @read_channel@ permission for the channel.+mmGetChannelMember :: ChannelId -> UserParam -> Session -> IO ChannelMember+mmGetChannelMember channelId userId =+ inGet (printf "/channels/%s/members/%s" channelId userId) noBody jsonResponse++-- | Delete a channel member, effectively removing them from a channel.+--+-- /Permissions/: @manage_public_channel_members@ permission if the+-- channel is public.+--+-- @manage_private_channel_members@ permission if the channel is private.+mmRemoveUserFromChannel :: ChannelId -> UserParam -> Session -> IO ()+mmRemoveUserFromChannel channelId userId =+ inDelete (printf "/channels/%s/members/%s" channelId userId) noBody noResponse++++-- * Cluster++-- -- | Get a set of information for each node in the cluster, useful for+-- -- checking the status and health of each node.+-- --+-- -- /Permissions/: Must have @manage_system@ permission.+-- mmGetClusterStatus :: Session -> IO (Seq ClusterInfo)+-- mmGetClusterStatus =+-- inGet "/cluster/status" noBody jsonResponse++++-- * Commands++-- -- | Generate a new token for the command based on command id string.+-- --+-- -- /Permissions/: Must have @manage_slash_commands@ permission for the+-- -- team the command is in.+-- mmGenerateNewToken :: CommandId -> Session -> IO Text+-- mmGenerateNewToken commandId =+-- inPut (printf "/commands/%s/regen_token" commandId) noBody jsonResponse++-- | Execute a command on a team.+--+-- /Permissions/: Must have @use_slash_commands@ permission for the team+-- the command is in.+mmExecuteCommand :: MinCommand -> Session -> IO CommandResponse+mmExecuteCommand body =+ inPost "/commands/execute" (jsonBody body) jsonResponse++-- -- | Update a single command based on command id string and Command struct.+-- --+-- -- /Permissions/: Must have @manage_slash_commands@ permission for the+-- -- team the command is in.+-- mmUpdateCommand :: CommandId -> Command -> Session -> IO Command+-- mmUpdateCommand commandId body =+-- inPut (printf "/commands/%s" commandId) (jsonBody body) jsonResponse++-- -- | Delete a command based on command id string.+-- --+-- -- /Permissions/: Must have @manage_slash_commands@ permission for the+-- -- team the command is in.+-- mmDeleteCommand :: CommandId -> Session -> IO ()+-- mmDeleteCommand commandId =+-- inDelete (printf "/commands/%s" commandId) noBody jsonResponse++-- -- | List autocomplete commands in the team.+-- --+-- -- /Permissions/: @view_team@ for the team.+-- mmListAutocompleteCommands :: TeamId -> Session -> IO (Seq Command)+-- mmListAutocompleteCommands teamId =+-- inGet (printf "/teams/%s/commands/autocomplete" teamId) noBody jsonResponse++-- -- | Create a command for a team.+-- --+-- -- /Permissions/: @manage_slash_commands@ for the team the command is in.+-- mmCreateCommand :: XX32 -> Session -> IO Command+-- mmCreateCommand body =+-- inPost "/commands" (jsonBody body) jsonResponse++-- -- | List commands for a team.+-- --+-- -- /Permissions/: @manage_slash_commands@ if need list custom commands.+-- mmListCommandsForTeam :: TeamId -> Maybe Text -> Session -> IO (Seq Command)+-- mmListCommandsForTeam teamId customOnly =+-- inGet (printf "/commands?%s" (mkQueryString [ Just ("team_id", T.unpack (idString teamId)) , sequence ("custom_only", fmap T.unpack customOnly) ])) noBody jsonResponse++++-- * Compliance++-- -- | Get a compliance reports previously created.+-- --+-- -- /Permissions/: Must have @manage_system@ permission.+-- mmGetReport :: ReportId -> Session -> IO Compliance+-- mmGetReport reportId =+-- inGet (printf "/compliance/reports/%s" reportId) noBody jsonResponse++-- -- | Create and save a compliance report.+-- --+-- -- /Permissions/: Must have @manage_system@ permission.+-- mmCreateReport :: Session -> IO Compliance+-- mmCreateReport =+-- inPost "/compliance/reports" noBody jsonResponse++-- -- | Get a list of compliance reports previously created by page, selected+-- -- with @page@ and @per_page@ query parameters.+-- --+-- -- /Permissions/: Must have @manage_system@ permission.+-- mmGetReports :: Maybe Integer -> Maybe Integer -> Session -> IO (Seq Compliance)+-- mmGetReports page perPage =+-- inGet (printf "/compliance/reports?%s" (mkQueryString [ sequence ("page", fmap show page) , sequence ("per_page", fmap show perPage) ])) noBody jsonResponse++-- -- | Download the full contents of a report as a file.+-- --+-- -- /Permissions/: Must have @manage_system@ permission.+-- mmDownloadReport :: ReportId -> Session -> IO ()+-- mmDownloadReport reportId =+-- inGet (printf "/compliance/reports/%s/download" reportId) noBody jsonResponse++++-- * Elasticsearch++-- -- | Deletes all Elasticsearch indexes and their contents. After calling+-- -- this endpoint, it is+-- --+-- -- necessary to schedule a new Elasticsearch indexing job to repopulate+-- -- the indexes.+-- --+-- -- /Minimum server version/: 4.1+-- --+-- -- /Permissions/: Must have @manage_system@ permission.+-- mmPurgeAllElasticsearchIndexes :: Session -> IO ()+-- mmPurgeAllElasticsearchIndexes =+-- inPost "/elasticsearch/purge_indexes" noBody jsonResponse++-- -- | Test the current Elasticsearch configuration to see if the+-- -- Elasticsearch server can be contacted successfully.+-- --+-- -- Optionally provide a configuration in the request body to test. If no+-- -- valid configuration is present in the+-- --+-- -- request body the current server configuration will be tested.+-- --+-- --+-- -- /Minimum server version/: 4.1+-- --+-- -- /Permissions/: Must have @manage_system@ permission.+-- mmTestElasticsearchConfiguration :: Session -> IO ()+-- mmTestElasticsearchConfiguration =+-- inPost "/elasticsearch/test" noBody jsonResponse++++-- * Emoji++-- -- | Create a custom emoji for the team.+-- --+-- -- /Permissions/: Must be authenticated.+-- mmCreateCustomEmoji :: Session -> IO Emoji+-- mmCreateCustomEmoji =+-- inPost "/emoji" noBody jsonResponse++-- -- | Get a page of metadata for custom emoji on the system.+-- --+-- -- /Permissions/: Must be authenticated.+-- mmGetListOfCustomEmoji :: Maybe Integer -> Maybe Integer -> Session -> IO Emoji+-- mmGetListOfCustomEmoji page perPage =+-- inGet (printf "/emoji?%s" (mkQueryString [ sequence ("page", fmap show page) , sequence ("per_page", fmap show perPage) ])) noBody jsonResponse++-- -- | Get some metadata for a custom emoji.+-- --+-- -- /Permissions/: Must be authenticated.+-- mmGetCustomEmoji :: EmojiId -> Session -> IO Emoji+-- mmGetCustomEmoji emojiId =+-- inGet (printf "/emoji/%s" emojiId) noBody jsonResponse++-- -- | Delete a custom emoji.+-- --+-- -- /Permissions/: Must have the @manage_team@ or @manage_system@+-- -- permissions or be the user who created the emoji.+-- mmDeleteCustomEmoji :: EmojiId -> Session -> IO Emoji+-- mmDeleteCustomEmoji emojiId =+-- inDelete (printf "/emoji/%s" emojiId) noBody jsonResponse++-- -- | Get the image for a custom emoji.+-- --+-- -- /Permissions/: Must be authenticated.+-- mmGetCustomEmojiImage :: EmojiId -> Session -> IO ()+-- mmGetCustomEmojiImage emojiId =+-- inGet (printf "/emoji/%s/image" emojiId) noBody jsonResponse++++-- * Files++-- -- | Gets a public link for a file that can be accessed without logging+-- mmGetPublicFileLink :: FileId -> Session -> IO Text+-- mmGetPublicFileLink fileId =+-- inGet (printf "/files/%s/link" fileId) noBody jsonResponse++-- | Gets a file that has been uploaded previously.+--+-- /Permissions/: Must have @read_channel@ permission or be uploader of+-- the file.+mmGetFile :: FileId -> Session -> IO B.ByteString+mmGetFile fileId =+ inGet (printf "/files/%s" fileId) noBody bytestringResponse++-- -- | Uploads a file that can later be attached to a post.+-- --+-- -- /Permissions/: Must have @upload_file@ permission.+-- mmUploadFile :: Session -> IO XX15+-- mmUploadFile =+-- inPost "/files" noBody jsonResponse++-- | Gets a file's info.+--+-- /Permissions/: Must have @read_channel@ permission or be uploader of+-- the file.+mmGetMetadataForFile :: FileId -> Session -> IO FileInfo+mmGetMetadataForFile fileId =+ inGet (printf "/files/%s/info" fileId) noBody jsonResponse++-- -- | Gets a file's thumbnail.+-- --+-- -- /Permissions/: Must have @read_channel@ permission or be uploader of+-- -- the file.+-- mmGetFilesThumbnail :: FileId -> Session -> IO ()+-- mmGetFilesThumbnail fileId =+-- inGet (printf "/files/%s/thumbnail" fileId) noBody jsonResponse++-- -- | Gets a file's preview.+-- --+-- -- /Permissions/: Must have @read_channel@ permission or be uploader of+-- -- the file.+-- mmGetFilesPreview :: FileId -> Session -> IO ()+-- mmGetFilesPreview fileId =+-- inGet (printf "/files/%s/preview" fileId) noBody jsonResponse++++-- * Jobs++-- -- | Create a new job.+-- --+-- -- /Minimum server version: 4.1/+-- --+-- -- /Permissions/: Must have @manage_jobs@ permission.+-- mmCreateNewJob :: XX20 -> Session -> IO Job+-- mmCreateNewJob body =+-- inPost "/jobs" (jsonBody body) jsonResponse++-- -- | Get a page of jobs. Use the query parameters to modify the behaviour+-- -- of this endpoint.+-- --+-- -- /Minimum server version: 4.1/+-- --+-- -- /Permissions/: Must have @manage_jobs@ permission.+-- mmGetJobs :: Maybe Integer -> Maybe Integer -> Session -> IO (Seq Job)+-- mmGetJobs page perPage =+-- inGet (printf "/jobs?%s" (mkQueryString [ sequence ("page", fmap show page) , sequence ("per_page", fmap show perPage) ])) noBody jsonResponse++-- -- | Cancel a job.+-- --+-- -- /Minimum server version: 4.1/+-- --+-- -- /Permissions/: Must have @manage_jobs@ permission.+-- mmCancelJob :: JobId -> Session -> IO ()+-- mmCancelJob jobId =+-- inPost (printf "/jobs/%s/cancel" jobId) noBody jsonResponse++-- -- | Gets a single job.+-- --+-- -- /Minimum server version: 4.1/+-- --+-- -- /Permissions/: Must have @manage_jobs@ permission.+-- mmGetJob :: JobId -> Session -> IO Job+-- mmGetJob jobId =+-- inGet (printf "/jobs/%s" jobId) noBody jsonResponse++-- -- | Get a page of jobs of the given type. Use the query parameters to+-- -- modify the behaviour of this endpoint.+-- --+-- -- /Minimum server version: 4.1/+-- --+-- -- /Permissions/: Must have @manage_jobs@ permission.+-- mmGetJobsOfGivenType :: Text -> Maybe Integer -> Maybe Integer -> Session -> IO (Seq Job)+-- mmGetJobsOfGivenType type_ page perPage =+-- inGet (printf "/jobs/type/%s?%s" type_ (mkQueryString [ sequence ("page", fmap show page) , sequence ("per_page", fmap show perPage) ])) noBody jsonResponse++++-- * LDAP++-- -- | Test the current AD\/LDAP configuration to see if the AD\/LDAP server+-- -- can be contacted successfully.+-- --+-- -- /Permissions/: Must have @manage_system@ permission.+-- mmTestLdapConfiguration :: Session -> IO ()+-- mmTestLdapConfiguration =+-- inPost "/ldap/test" noBody jsonResponse++-- -- | Synchronize any user attribute changes in the configured AD\/LDAP+-- -- server with Mattermost.+-- --+-- -- /Permissions/: Must have @manage_system@ permission.+-- mmSyncWithLdap :: Session -> IO ()+-- mmSyncWithLdap =+-- inPost "/ldap/sync" noBody jsonResponse++++-- * OAuth++-- -- | Register an OAuth 2.0 client application with Mattermost as the+-- -- service provider.+-- --+-- -- /Permissions/: Must have @manage_oauth@ permission.+-- mmRegisterOauthApp :: XX13 -> Session -> IO OAuthApp+-- mmRegisterOauthApp body =+-- inPost "/oauth/apps" (jsonBody body) jsonResponse++-- -- | Get a page of OAuth 2.0 client applications registered with+-- -- Mattermost.+-- --+-- -- /Permissions/: With @manage_oauth@ permission, the apps registered by+-- -- the logged in user are returned. With @manage_system_wide_oauth@+-- -- permission, all apps regardless of creator are returned.+-- mmGetOauthApps :: Maybe Integer -> Maybe Integer -> Session -> IO (Seq OAuthApp)+-- mmGetOauthApps page perPage =+-- inGet (printf "/oauth/apps?%s" (mkQueryString [ sequence ("page", fmap show page) , sequence ("per_page", fmap show perPage) ])) noBody jsonResponse++-- -- | Get an OAuth 2.0 client application registered with Mattermost.+-- --+-- -- /Permissions/: If app creator, must have @mange_oauth@ permission+-- -- otherwise @manage_system_wide_oauth@ permission is required.+-- mmGetAnOauthApp :: AppId -> Session -> IO OAuthApp+-- mmGetAnOauthApp appId =+-- inGet (printf "/oauth/apps/%s" appId) noBody jsonResponse++-- -- | Delete and unregister an OAuth 2.0 client application+-- --+-- -- /Permissions/: If app creator, must have @mange_oauth@ permission+-- -- otherwise @manage_system_wide_oauth@ permission is required.+-- mmDeleteAnOauthApp :: AppId -> Session -> IO ()+-- mmDeleteAnOauthApp appId =+-- inDelete (printf "/oauth/apps/%s" appId) noBody jsonResponse++-- -- | Get public information about an OAuth 2.0 client application+-- -- registered with Mattermost. The application's client secret will be+-- -- blanked out.+-- --+-- -- /Permissions/: Must be authenticated.+-- mmGetInfoOnAnOauthApp :: AppId -> Session -> IO OAuthApp+-- mmGetInfoOnAnOauthApp appId =+-- inGet (printf "/oauth/apps/%s/info" appId) noBody jsonResponse++-- -- | Get a page of OAuth 2.0 client applications authorized to access a+-- -- user's account.+-- --+-- -- /Permissions/: Must be authenticated as the user or have+-- -- @edit_other_users@ permission.+-- mmGetAuthorizedOauthApps :: UserId -> Maybe Integer -> Maybe Integer -> Session -> IO (Seq OAuthApp)+-- mmGetAuthorizedOauthApps userId page perPage =+-- inGet (printf "/users/%s/oauth/apps/authorized?%s" userId (mkQueryString [ sequence ("page", fmap show page) , sequence ("per_page", fmap show perPage) ])) noBody jsonResponse++-- -- | Regenerate the client secret for an OAuth 2.0 client application+-- -- registered with Mattermost.+-- --+-- -- /Permissions/: If app creator, must have @mange_oauth@ permission+-- -- otherwise @manage_system_wide_oauth@ permission is required.+-- mmRegenerateOauthAppSecret :: AppId -> Session -> IO OAuthApp+-- mmRegenerateOauthAppSecret appId =+-- inPost (printf "/oauth/apps/%s/regen_secret" appId) noBody jsonResponse++++-- * Posts++-- | Create a new post in a channel. To create the post as a comment on+-- another post, provide @root_id@.+--+-- /Permissions/: Must have @create_post@ permission for the channel the+-- post is being created in.+mmCreatePost :: RawPost -> Session -> IO Post+mmCreatePost body =+ inPost "/posts" (jsonBody body) jsonResponse++-- | Search posts in the team and from the provided terms string.+--+-- /Permissions/: Must be authenticated and have the @view_team@+-- permission.+mmSearchForTeamPosts :: TeamId -> SearchPosts -> Session -> IO Posts+mmSearchForTeamPosts teamId body =+ inPost (printf "/teams/%s/posts/search" teamId) (jsonBody body) jsonResponse++-- -- | Pin a post to a channel it is in based from the provided post id+-- -- string.+-- --+-- -- /Permissions/: Must be authenticated and have the @read_channel@+-- -- permission to the channel the post is in.+-- mmPinPostToChannel :: PostId -> Session -> IO ()+-- mmPinPostToChannel postId =+-- inPost (printf "/posts/%s/pin" postId) noBody jsonResponse++-- | Get a post and the rest of the posts in the same thread.+--+-- /Permissions/: Must have @read_channel@ permission for the channel the+-- post is in or if the channel is public, have the+-- @read_public_channels@ permission for the team.+mmGetThread :: PostId -> Session -> IO Posts+mmGetThread postId =+ inGet (printf "/posts/%s/thread" postId) noBody jsonResponse++-- | Update a post. Only the fields listed below are updatable, omitted+-- fields will be treated as blank.+--+-- /Permissions/: Must have @edit_post@ permission for the channel the+-- post is in.+mmUpdatePost :: PostId -> PostUpdate -> Session -> IO Post+mmUpdatePost postId body =+ inPut (printf "/posts/%s" postId) (jsonBody body) jsonResponse++-- | Get a single post.+--+-- /Permissions/: Must have @read_channel@ permission for the channel the+-- post is in or if the channel is public, have the+-- @read_public_channels@ permission for the team.+mmGetPost :: PostId -> Session -> IO Post+mmGetPost postId =+ inGet (printf "/posts/%s" postId) noBody jsonResponse++-- | Soft deletes a post, by marking the post as deleted in the database.+-- Soft deleted posts will not be returned in post queries.+--+-- /Permissions/: Must be logged in as the user or have+-- @delete_others_posts@ permission.+mmDeletePost :: PostId -> Session -> IO ()+mmDeletePost postId =+ inDelete (printf "/posts/%s" postId) noBody noResponse++data FlaggedPostsQuery = FlaggedPostsQuery+ { flaggedPostsQueryPage :: Maybe Int+ , flaggedPostsQueryPerPage :: Maybe Int+ , flaggedPostsQueryTeamId :: Maybe TeamId+ , flaggedPostsQueryChannelId :: Maybe ChannelId+ }++defaultFlaggedPostsQuery :: FlaggedPostsQuery+defaultFlaggedPostsQuery = FlaggedPostsQuery+ { flaggedPostsQueryPage = Nothing+ , flaggedPostsQueryPerPage = Nothing+ , flaggedPostsQueryTeamId = Nothing+ , flaggedPostsQueryChannelId = Nothing+ }+++-- | Get a page of flagged posts of a user provided user id string. Selects+-- from a channel, team or all flagged posts by a user.+--+-- /Permissions/: Must be user or have @manage_system@ permission.+mmGetListOfFlaggedPosts :: UserParam -> FlaggedPostsQuery -> Session -> IO Posts+mmGetListOfFlaggedPosts userId FlaggedPostsQuery { .. } =+ inGet (printf "/users/%s/posts/flagged?%s" userId query) noBody jsonResponse+ where query = mkQueryString+ [ sequence ("team_id", fmap (T.unpack . idString) flaggedPostsQueryTeamId)+ , sequence ("channel_id", fmap (T.unpack . idString) flaggedPostsQueryChannelId)+ , sequence ("page", fmap show flaggedPostsQueryPage)+ , sequence ("per_page", fmap show flaggedPostsQueryPerPage)+ ]++-- -- | Unpin a post to a channel it is in based from the provided post id+-- -- string.+-- --+-- -- /Permissions/: Must be authenticated and have the @read_channel@+-- -- permission to the channel the post is in.+-- mmUnpinPostToChannel :: PostId -> Session -> IO ()+-- mmUnpinPostToChannel postId =+-- inPost (printf "/posts/%s/unpin" postId) noBody jsonResponse++-- -- | Partially update a post by providing only the fields you want to+-- -- update. Omitted fields will not be updated. The fields that can be+-- -- updated are defined in the request body, all other provided fields+-- -- will be ignored.+-- --+-- -- /Permissions/: Must have the @edit_post@ permission.+-- mmPatchPost :: PostId -> XX27 -> Session -> IO Post+-- mmPatchPost postId body =+-- inPut (printf "/posts/%s/patch" postId) (jsonBody body) jsonResponse++data PostQuery = PostQuery+ { postQueryPage :: Maybe Int+ , postQueryPerPage :: Maybe Int+ , postQuerySince :: Maybe UTCTime+ , postQueryBefore :: Maybe PostId+ , postQueryAfter :: Maybe PostId+ }++defaultPostQuery :: PostQuery+defaultPostQuery = PostQuery+ { postQueryPage = Nothing+ , postQueryPerPage = Nothing+ , postQuerySince = Nothing+ , postQueryBefore = Nothing+ , postQueryAfter = Nothing+ }++postQueryToQueryString :: PostQuery -> String+postQueryToQueryString PostQuery { .. } =+ mkQueryString+ [ sequence ("page", fmap show postQueryPage)+ , sequence ("per_page", fmap show postQueryPerPage)+ , sequence ("since", fmap show postQuerySince)+ , sequence ("before", fmap (T.unpack . idString) postQueryBefore)+ , sequence ("after", fmap (T.unpack . idString) postQueryAfter)+ ]++-- | Get a page of posts in a channel. Use the query parameters to modify+-- the behaviour of this endpoint. The parameters @since@, @before@ and+-- @after@ must not be used together.+--+-- /Permissions/: Must have @read_channel@ permission for the channel.+mmGetPostsForChannel :: ChannelId -> PostQuery -> Session -> IO Posts+mmGetPostsForChannel channelId postQuery =+ inGet (printf "/channels/%s/posts?%s" channelId (postQueryToQueryString postQuery)) noBody jsonResponse++-- -- | Gets a list of file information objects for the files attached to a+-- -- post.+-- --+-- -- /Permissions/: Must have @read_channel@ permission for the channel the+-- -- post is in.+-- mmGetFileInfoForPost :: PostId -> Session -> IO (Seq FileInfo)+-- mmGetFileInfoForPost postId =+-- inGet (printf "/posts/%s/files/info" postId) noBody jsonResponse++++-- * Preferences++-- | Gets a single preference for the current user with the given category+-- and name.+--+-- /Permissions/: Must be logged in as the user being updated or have the+-- @edit_other_users@ permission.+mmGetSpecificUserPreference :: UserParam -> Text -> Text -> Session -> IO Preference+mmGetSpecificUserPreference userId category preferenceName =+ inGet (printf "/users/%s/preferences/%s/name/%s" userId category preferenceName) noBody jsonResponse++-- | Save a list of the user's preferences.+--+-- /Permissions/: Must be logged in as the user being updated or have the+-- @edit_other_users@ permission.+mmSaveUsersPreferences :: UserParam -> (Seq Preference) -> Session -> IO ()+mmSaveUsersPreferences userId body =+ inPut (printf "/users/%s/preferences" userId) (jsonBody body) noResponse++-- | Get a list of the user's preferences.+--+-- /Permissions/: Must be logged in as the user being updated or have the+-- @edit_other_users@ permission.+mmGetUsersPreferences :: UserParam -> Session -> IO (Seq Preference)+mmGetUsersPreferences userId =+ inGet (printf "/users/%s/preferences" userId) noBody jsonResponse++-- | Delete a list of the user's preferences.+--+-- /Permissions/: Must be logged in as the user being updated or have the+-- @edit_other_users@ permission.+mmDeleteUsersPreferences :: UserParam -> (Seq Preference) -> Session -> IO ()+mmDeleteUsersPreferences userId body =+ inPost (printf "/users/%s/preferences/delete" userId) (jsonBody body) noResponse++-- | Lists the current user's stored preferences in the given category.+--+-- /Permissions/: Must be logged in as the user being updated or have the+-- @edit_other_users@ permission.+mmListUsersPreferencesByCategory :: UserParam -> Text -> Session -> IO (Seq Preference)+mmListUsersPreferencesByCategory userId category =+ inGet (printf "/users/%s/preferences/%s" userId category) noBody jsonResponse+++-- * Reactions++mmGetReactionsForPost :: PostId -> Session -> IO (Seq Reaction)+mmGetReactionsForPost postId =+ inGet (printf "/posts/%s/reactions" postId) noBody jsonResponse++-- mmPostReaction :: Session -> IO ()+-- mmPostReaction =+-- inPost (printf "/reactions") (jsonBody ()) noResponse++++-- * SAML++-- -- | Upload the private key to be used for encryption with your SAML+-- -- configuration. This will also set the filename for the PrivateKeyFile+-- -- setting in your @config.json@.+-- --+-- -- /Permissions/: Must have @manage_system@ permission.+-- mmUploadPrivateKey :: Session -> IO ()+-- mmUploadPrivateKey =+-- inPost "/saml/certificate/private" noBody noResponse++-- -- | Delete the current private key being used with your SAML+-- -- configuration. This will also disable encryption for SAML on your+-- -- system as this key is required for that.+-- --+-- -- /Permissions/: Must have @manage_system@ permission.+-- mmRemovePrivateKey :: Session -> IO ()+-- mmRemovePrivateKey =+-- inDelete "/saml/certificate/private" noBody jsonResponse++-- -- | Upload the public certificate to be used for encryption with your SAML+-- -- configuration. This will also set the filename for the+-- -- PublicCertificateFile setting in your @config.json@.+-- --+-- -- /Permissions/: Must have @manage_system@ permission.+-- mmUploadPublicCertificate :: Session -> IO ()+-- mmUploadPublicCertificate =+-- inPost "/saml/certificate/public" noBody jsonResponse++-- -- | Delete the current public certificate being used with your SAML+-- -- configuration. This will also disable encryption for SAML on your+-- -- system as this certificate is required for that.+-- --+-- -- /Permissions/: Must have @manage_system@ permission.+-- mmRemovePublicCertificate :: Session -> IO ()+-- mmRemovePublicCertificate =+-- inDelete "/saml/certificate/public" noBody jsonResponse++-- -- | Upload the IDP certificate to be used with your SAML configuration.+-- -- This will also set the filename for the IdpCertificateFile setting in+-- -- your @config.json@.+-- --+-- -- /Permissions/: Must have @manage_system@ permission.+-- mmUploadIdpCertificate :: Session -> IO ()+-- mmUploadIdpCertificate =+-- inPost "/saml/certificate/idp" noBody jsonResponse++-- -- | Delete the current IDP certificate being used with your SAML+-- -- configuration. This will also disable SAML on your system as this+-- -- certificate is required for SAML.+-- --+-- -- /Permissions/: Must have @manage_system@ permission.+-- mmRemoveIdpCertificate :: Session -> IO ()+-- mmRemoveIdpCertificate =+-- inDelete "/saml/certificate/idp" noBody jsonResponse++-- -- | Get the status of the uploaded certificates and keys in use by your+-- -- SAML configuration.+-- --+-- -- /Permissions/: Must have @manage_system@ permission.+-- mmGetCertificateStatus :: Session -> IO SamlCertificateStatus+-- mmGetCertificateStatus =+-- inGet "/saml/certificate/status" noBody jsonResponse++-- -- | Get SAML metadata from the server. SAML must be configured properly.+-- --+-- -- /Permissions/: No permission required.+-- mmGetMetadata :: Session -> IO Text+-- mmGetMetadata =+-- inGet "/saml/metadata" noBody jsonResponse+++-- * Statuses++mmGetUserStatusByIds :: Seq UserId -> Session -> IO (Seq Status)+mmGetUserStatusByIds body =+ inPost "/users/status/ids" (jsonBody body) jsonResponse+++-- * System++-- -- | Get a page of audits for all users on the system, selected with @page@+-- -- and @per_page@ query parameters.+-- --+-- -- /Permissions/: Must have @manage_system@ permission.+-- mmGetAudits :: Maybe Integer -> Maybe Integer -> Session -> IO (Seq Audit)+-- mmGetAudits page perPage =+-- inGet (printf "/audits?%s" (mkQueryString [ sequence ("page", fmap show page) , sequence ("per_page", fmap show perPage) ])) noBody jsonResponse++-- -- | Get a subset of the server license needed by the client.+-- --+-- -- /Permissions/: No permission required but having the @manage_system@+-- -- permission returns more information.+-- mmGetClientLicense :: Text -> Session -> IO ()+-- mmGetClientLicense format =+-- inGet (printf "/license/client?%s" (mkQueryString [ Just ("format", T.unpack format) ])) noBody jsonResponse++-- -- | Upload a license to enable enterprise features.+-- --+-- -- /Minimum server version/: 4.0+-- --+-- -- /Permissions/: Must have @manage_system@ permission.+-- mmUploadLicenseFile :: Session -> IO ()+-- mmUploadLicenseFile =+-- inPost "/license" noBody jsonResponse++-- -- | Remove the license file from the server. This will disable all+-- -- enterprise features.+-- --+-- -- /Minimum server version/: 4.0+-- --+-- -- /Permissions/: Must have @manage_system@ permission.+-- mmRemoveLicenseFile :: Session -> IO ()+-- mmRemoveLicenseFile =+-- inDelete "/license" noBody jsonResponse++-- -- | Get a valid WebRTC token, STUN and TURN server URLs along with TURN+-- -- credentials to use with the Mattermost WebRTC service. See+-- -- https:\/\/docs.mattermost.com\/administration\/config-settings.html+-- -- #webrtc-beta for WebRTC configutation settings. The token returned is+-- -- for the current user's session.+-- --+-- -- /Permissions/: Must be authenticated.+-- mmGetWebrtcToken :: Session -> IO XX8+-- mmGetWebrtcToken =+-- inGet "/webrtc/token" noBody jsonResponse++-- | Get a subset of the server configuration needed by the client.+--+-- /Permissions/: No permission required.+mmGetClientConfiguration :: Maybe Text -> Session -> IO ClientConfig+mmGetClientConfiguration format =+ inGet (printf "/config/client?%s" (mkQueryString [ sequence ("format", fmap T.unpack format) ])) noBody jsonResponse++-- -- | Reload the configuration file to pick up on any changes made to it.+-- --+-- -- /Permissions/: Must have @manage_system@ permission.+-- mmReloadConfiguration :: Session -> IO ()+-- mmReloadConfiguration =+-- inPost "/config/reload" noBody jsonResponse++-- -- | Purge all the in-memory caches for the Mattermost server. This can+-- -- have a temporary negative effect on performance while the caches are+-- -- re-populated.+-- --+-- -- /Permissions/: Must have @manage_system@ permission.+-- mmInvalidateAllCaches :: Session -> IO ()+-- mmInvalidateAllCaches =+-- inPost "/caches/invalidate" noBody jsonResponse++-- -- | Recycle database connections by closing and reconnecting all+-- -- connections to master and read replica databases.+-- --+-- -- /Permissions/: Must have @manage_system@ permission.+-- mmRecycleDatabaseConnections :: Session -> IO ()+-- mmRecycleDatabaseConnections =+-- inPost "/database/recycle" noBody jsonResponse++-- -- | Add log messages to the server logs.+-- --+-- -- /Permissions/: Must have @manage_system@ permission or if+-- -- @ServiceSettings.EnableDeveloper@ in the+-- --+-- -- config file is set to @true@ then any user can use this endpoint.+-- mmAddLogMessage :: XX26 -> Session -> IO UnknownType+-- mmAddLogMessage body =+-- inPost "/logs" (jsonBody body) jsonResponse++-- -- | Get a page of server logs, selected with @page@ and @per_page@ query+-- -- parameters.+-- --+-- -- /Permissions/: Must have @manage_system@ permission.+-- mmGetLogs :: Maybe Integer -> Maybe Integer -> Session -> IO (Seq Text)+-- mmGetLogs page perPage =+-- inGet (printf "/logs?%s" (mkQueryString [ sequence ("page", fmap show page) , sequence ("per_page", fmap show perPage) ])) noBody jsonResponse++-- -- | Send a test email to make sure you have your email settings configured+-- -- correctly. Optionally provide a configuration in the request body to+-- -- test. If no valid configuration is present in the request body the+-- -- current server configuration will be tested.+-- --+-- -- /Permissions/: Must have @manage_system@ permission.+-- mmSendTestEmail :: Session -> IO ()+-- mmSendTestEmail =+-- inPost "/email/test" noBody jsonResponse++-- -- | Check if the server is up and healthy based on the configuration+-- -- setting @GoRoutineHealthThreshold@. If @GoRoutineHealthThreshold@ and+-- -- the number of goroutines on the server exceeds that threshold the+-- -- server is considered unhealthy. If @GoRoutineHealthThreshold@ is not+-- -- set or the number of goroutines is below the threshold the server is+-- -- considered healthy.+-- --+-- -- /Minimum server version/: 3.10+-- --+-- -- /Permissions/: Must be logged in.+-- mmCheckSystemHealth :: Session -> IO UnknownType+-- mmCheckSystemHealth =+-- inGet "/system/ping" noBody jsonResponse++-- -- | Get some analytics data about the system. This endpoint uses the old+-- -- format, the @\/analytics@ route is reserved for the new format when it+-- -- gets implemented.+-- --+-- --+-- -- The returned JSON changes based on the @name@ query parameter but is+-- -- always key\/value pairs.+-- --+-- --+-- -- /Minimum server version/: 4.0+-- --+-- --+-- -- /Permissions/: Must have @manage_system@ permission.+-- mmGetAnalytics :: Maybe Text -> TeamId -> Session -> IO ()+-- mmGetAnalytics name teamId =+-- inGet (printf "/analytics/old?%s" (mkQueryString [ sequence ("name", fmap T.unpack name) , Just ("team_id", T.unpack (idString teamId)) ])) noBody jsonResponse++-- | Submit a new configuration for the server to use.+--+-- /Permissions/: Must have @manage_system@ permission.+mmUpdateConfiguration :: ServerConfig -> Session -> IO ServerConfig+mmUpdateConfiguration body =+ inPut "/config" (jsonBody body) jsonResponse++-- | Retrieve the current server configuration+--+-- /Permissions/: Must have @manage_system@ permission.+mmGetConfiguration :: Session -> IO ServerConfig+mmGetConfiguration =+ inGet "/config" noBody jsonResponse++++-- * Teams++-- | Get a team member on the system.+--+-- /Permissions/: Must be authenticated and have the @view_team@+-- permission.+mmGetTeamMember :: TeamId -> UserParam -> Session -> IO TeamMember+mmGetTeamMember teamId userId =+ inGet (printf "/teams/%s/members/%s" teamId userId) noBody jsonResponse++-- | Delete the team member object for a user, effectively removing them+-- from a team.+--+-- /Permissions/: Must be logged in as the user or have the+-- @remove_user_from_team@ permission.+mmRemoveUserFromTeam :: TeamId -> UserParam -> Session -> IO ()+mmRemoveUserFromTeam teamId userId =+ inDelete (printf "/teams/%s/members/%s" teamId userId) noBody jsonResponse++-- -- | Get a page of deleted channels on a team based on query string+-- -- parameters - team_id, page and per_page.+-- --+-- --+-- -- /Minimum server version/: 3.10+-- --+-- --+-- -- /Permissions/: Must be authenticated and have the @manage_team@+-- -- permission.+-- mmGetDeletedChannels :: TeamId -> Maybe Integer -> Maybe Integer -> Session -> IO (Seq Channel)+-- mmGetDeletedChannels teamId page perPage =+-- inGet (printf "/teams/%s/channels/deleted?%s" teamId (mkQueryString [ sequence ("page", fmap show page) , sequence ("per_page", fmap show perPage) ])) noBody jsonResponse++-- -- | Update a team member roles. Valid team roles are "team_user",+-- -- "team_admin" or both of them. Overwrites any previously assigned team+-- -- roles.+-- --+-- -- /Permissions/: Must be authenticated and have the @manage_team_roles@+-- -- permission.+-- mmUpdateTeamMemberRoles :: TeamId -> UserId -> Text -> Session -> IO ()+-- mmUpdateTeamMemberRoles teamId userId roles =+-- inPut (printf "/teams/%s/members/%s/roles" teamId userId) (jsonBody (A.object [ "roles" A..= roles ])) jsonResponse++-- | Get a page of public channels on a team based on query string+-- parameters - page and per_page.+--+-- /Permissions/: Must be authenticated and have the @list_team_channels@+-- permission.+mmGetPublicChannels :: TeamId -> Maybe Int -> Maybe Int -> Session -> IO (Seq Channel)+mmGetPublicChannels teamId page perPage =+ inGet (printf "/teams/%s/channels?%s" teamId (mkQueryString [ sequence ("page", fmap show page)+ , sequence ("per_page", fmap show perPage)+ ])) noBody jsonResponse++-- -- | Check if the team exists based on a team name.+-- mmCheckIfTeamExists :: Text -> Session -> IO TeamExists+-- mmCheckIfTeamExists name =+-- inGet (printf "/teams/name/%s/exists" name) noBody jsonResponse++-- | Create a new team on the system.+--+-- /Permissions/: Must be authenticated and have the @create_team@+-- permission.+mmCreateTeam :: TeamsCreate -> Session -> IO Team+mmCreateTeam body =+ inPost "/teams" (jsonBody body) jsonResponse++-- | For regular users only returns open teams. Users with the+-- "manage_system" permission will return teams regardless of type. The+-- result is based on query string parameters - page and per_page.+--+-- /Permissions/: Must be authenticated. "manage_system" permission is+-- required to show all teams.+mmGetTeams :: Maybe Integer -> Maybe Integer -> Session -> IO (Seq Team)+mmGetTeams page perPage =+ inGet (printf "/teams?%s"+ (mkQueryString [ sequence ("page", fmap show page)+ , sequence ("per_page", fmap show perPage)+ ])) noBody jsonResponse++-- | Search teams based on search term provided in the request body.+--+-- /Permissions/: Logged in user only shows open teams+--+-- Logged in user with "manage_system" permission shows all teams+mmSearchTeams :: Text -> Session -> IO (Seq Team)+mmSearchTeams term =+ inPost "/teams/search" (jsonBody (A.object [ "term" A..= term ])) jsonResponse++-- -- | Invite users to the existing team usign the user's email.+-- --+-- -- /Permissions/: Must have @invite_to_team@ permission for the team.+-- mmInviteUsersToTeamByEmail :: TeamId -> (Seq Text) -> Session -> IO ()+-- mmInviteUsersToTeamByEmail teamId body =+-- inPost (printf "/teams/%s/invite/email" teamId) (jsonBody body) jsonResponse++-- | Search public channels on a team based on the search term provided in+-- the request body.+--+-- /Permissions/: Must have the @list_team_channels@ permission.+mmSearchChannels :: TeamId -> Text -> Session -> IO (Seq Channel)+mmSearchChannels teamId term =+ inPost (printf "/teams/%s/channels/search" teamId) (jsonBody (A.object [ "term" A..= term ])) jsonResponse++-- -- | Get the count for unread messages and mentions in the teams the user+-- -- is a member of.+-- --+-- -- /Permissions/: Must be logged in.+-- mmGetTeamUnreadsForUser :: UserId -> Text -> Session -> IO (Seq TeamUnread)+-- mmGetTeamUnreadsForUser userId excludeTeam =+-- inGet (printf "/users/%s/teams/unread?%s" userId (mkQueryString [ Just ("exclude_team", T.unpack excludeTeam) ])) noBody jsonResponse++-- | Get a list of teams that a user is on.+--+-- /Permissions/: Must be authenticated as the user or have the+-- @manage_system@ permission.+mmGetUsersTeams :: UserParam -> Session -> IO (Seq Team)+mmGetUsersTeams userId =+ inGet (printf "/users/%s/teams" userId) noBody jsonResponse++-- -- | Using either an invite id or hash\/data pair from an email invite+-- -- link, add a user to a team.+-- --+-- -- /Permissions/: Must be authenticated.+-- mmAddUserToTeamFromInvite :: Text -> Text -> InviteId -> Session -> IO TeamMember+-- mmAddUserToTeamFromInvite hash data_ inviteId =+-- inPost (printf "/teams/members/invite?%s" (mkQueryString [ Just ("hash", T.unpack hash) , Just ("data", T.unpack data_) , Just ("invite_id", T.unpack (idString inviteId)) ])) noBody jsonResponse++-- -- | Get a team stats on the system.+-- --+-- -- /Permissions/: Must be authenticated and have the @view_team@+-- -- permission.+-- mmGetTeamStats :: TeamId -> Session -> IO TeamStats+-- mmGetTeamStats teamId =+-- inGet (printf "/teams/%s/stats" teamId) noBody jsonResponse++-- | Get a list of team members based on a provided array of user ids.+--+-- /Permissions/: Must have @view_team@ permission for the team.+mmGetTeamMembersByIds :: TeamId -> Seq UserId -> Session -> IO (Seq TeamMember)+mmGetTeamMembersByIds teamId body =+ inPost (printf "/teams/%s/members/ids" teamId) (jsonBody body) jsonResponse++-- -- | Partially update a team by providing only the fields you want to+-- -- update. Omitted fields will not be updated. The fields that can be+-- -- updated are defined in the request body, all other provided fields+-- -- will be ignored.+-- --+-- -- /Permissions/: Must have the @manage_team@ permission.+-- mmPatchTeam :: TeamId -> XX23 -> Session -> IO Team+-- mmPatchTeam teamId body =+-- inPut (printf "/teams/%s/patch" teamId) (jsonBody body) jsonResponse++-- | Get a list of team members for a user. Useful for getting the ids of+-- teams the user is on and the roles they have in those teams.+--+-- /Permissions/: Must be logged in as the user or have the+-- @edit_other_users@ permission.+mmGetTeamMembersForUser :: UserParam -> Session -> IO (Seq TeamMember)+mmGetTeamMembersForUser userId =+ inGet (printf "/users/%s/teams/members" userId) noBody jsonResponse++-- | Add user to the team by user_id.+--+-- /Permissions/: Must be authenticated and team be open to add self. For+-- adding another user, authenticated user must have the+-- @add_user_to_team@ permission.+mmAddUserToTeam :: TeamId -> TeamMember -> Session -> IO TeamMember+mmAddUserToTeam teamId body =+ inPost (printf "/teams/%s/members" teamId) (jsonBody body) jsonResponse++-- -- | Get a page team members list based on query string parameters - team+-- -- id, page and per page.+-- --+-- -- /Permissions/: Must be authenticated and have the @view_team@+-- -- permission.+-- mmGetTeamMembers :: TeamId -> Maybe Integer -> Maybe Integer -> Session -> IO (Seq TeamMember)+-- mmGetTeamMembers teamId page perPage =+-- inGet (printf "/teams/%s/members?%s" teamId (mkQueryString [ sequence ("page", fmap show page) , sequence ("per_page", fmap show perPage) ])) noBody jsonResponse++-- -- | Import a team into a existing team. Import users, channels, posts,+-- -- hooks.+-- --+-- -- /Permissions/: Must have @permission_import_team@ permission.+-- mmImportTeamFromOtherApplication :: TeamId -> Session -> IO Text+-- mmImportTeamFromOtherApplication teamId =+-- inPost (printf "/teams/%s/import" teamId) noBody jsonResponse++-- -- | Add a number of users to the team by user_id.+-- --+-- -- /Permissions/: Must be authenticated. Authenticated user must have the+-- -- @add_user_to_team@ permission.+-- mmAddMultipleUsersToTeam :: TeamId -> (Seq TeamMember) -> Session -> IO (Seq TeamMember)+-- mmAddMultipleUsersToTeam teamId body =+-- inPost (printf "/teams/%s/members/batch" teamId) (jsonBody body) jsonResponse++-- -- | Get the unread mention and message counts for a team for the specified+-- -- user.+-- --+-- -- /Permissions/: Must be the user or have @edit_other_users@ permission+-- -- and have @view_team@ permission for the team.+-- mmGetUnreadsForTeam :: UserId -> TeamId -> Session -> IO TeamUnread+-- mmGetUnreadsForTeam userId teamId =+-- inGet (printf "/users/%s/teams/%s/unread" userId teamId) noBody jsonResponse++-- -- | Get the @name@, @display_name@, @description@ and @id@ for a team from+-- -- the invite id.+-- --+-- --+-- -- /Minimum server version/: 4.0+-- --+-- --+-- -- /Permissions/: No authentication required.+-- mmGetInviteInfoForTeam :: InviteId -> Session -> IO XX34+-- mmGetInviteInfoForTeam inviteId =+-- inGet (printf "/teams/invite/%s" inviteId) noBody jsonResponse++-- | Get a team based on provided name string+--+-- /Permissions/: Must be authenticated, team type is open and have the+-- @view_team@ permission.+mmGetTeamByName :: Text -> Session -> IO Team+mmGetTeamByName name =+ inGet (printf "/teams/name/%s" name) noBody jsonResponse++-- -- | Update a team by providing the team object. The fields that can be+-- -- updated are defined in the request body, all other provided fields+-- -- will be ignored.+-- --+-- -- /Permissions/: Must have the @manage_team@ permission.+-- mmUpdateTeam :: TeamId -> XX36 -> Session -> IO Team+-- mmUpdateTeam teamId body =+-- inPut (printf "/teams/%s" teamId) (jsonBody body) jsonResponse++-- | Get a team on the system.+--+-- /Permissions/: Must be authenticated and have the @view_team@+-- permission.+mmGetTeam :: TeamId -> Session -> IO Team+mmGetTeam teamId =+ inGet (printf "/teams/%s" teamId) noBody jsonResponse++-- -- | Delete a team softly and put in archived only.+-- --+-- -- /Permissions/: Must have the @manage_team@ permission.+-- mmDeleteTeam :: TeamId -> Bool -> Session -> IO ()+-- mmDeleteTeam teamId permanent =+-- inDelete (printf "/teams/%s?%s" teamId (mkQueryString [ Just ("permanent", if permanent then "true" else "false") ])) noBody jsonResponse++++-- * Users++-- | Get a list of users based on search criteria provided in the request+-- body. Searches are typically done against username, full name,+-- nickname and email unless otherwise configured by the server.+--+-- /Permissions/: Requires an active session and @read_channel@ and\/or+-- @view_team@ permissions for any channels or teams specified in the+-- request body.+mmSearchUsers :: UserSearch -> Session -> IO (Seq User)+mmSearchUsers body =+ inPost "/users/search" (jsonBody body) jsonResponse++-- | Get a list of users based on a provided list of usernames.+--+-- /Permissions/: Requires an active session but no other permissions.+mmGetUsersByUsernames :: (Seq Text) -> Session -> IO (Seq User)+mmGetUsersByUsernames body =+ inPost "/users/usernames" (jsonBody body) jsonResponse++-- -- | Revokes a user session from the provided user id and session id+-- -- strings.+-- --+-- -- /Permissions/: Must be logged in as the user being updated or have the+-- -- @edit_other_users@ permission.+-- mmRevokeUserSession :: UserId -> Text -> Session -> IO ()+-- mmRevokeUserSession userId sessionId =+-- inPost (printf "/users/%s/sessions/revoke" userId) (jsonBody (A.object [ "session_id" A..= sessionId ])) jsonResponse++-- | Update a user's system-level roles. Valid user roles are+-- "system_user", "system_admin" or both of them. Overwrites any+-- previously assigned system-level roles.+--+-- /Permissions/: Must have the @manage_roles@ permission.+mmUpdateUsersRoles :: UserId -> Text -> Session -> IO ()+mmUpdateUsersRoles userId roles =+ inPut (printf "/users/%s/roles" userId) (jsonBody (A.object [ "roles" A..= roles ])) noResponse++-- -- | Send an email with a verification link to a user that has an email+-- -- matching the one in the request body. This endpoint will return+-- -- success even if the email does not match any users on the system.+-- --+-- -- /Permissions/: No permissions required.+-- mmSendVerificationEmail :: Text -> Session -> IO ()+-- mmSendVerificationEmail email =+-- inPost "/users/email/verify/send" (jsonBody (A.object [ "email" A..= email ])) jsonResponse++-- -- | Get a list of sessions by providing the user GUID. Sensitive+-- -- information will be sanitized out.+-- --+-- -- /Permissions/: Must be logged in as the user being updated or have the+-- -- @edit_other_users@ permission.+-- -- mmGetUsersSessions :: UserId -> Session -> IO (Seq Session)+-- -- mmGetUsersSessions userId =+-- -- inGet (printf "/users/%s/sessions" userId) noBody jsonResponse++-- -- | Check if a user has multi-factor authentication active on their+-- -- account by providing a login id. Used to check whether an MFA code+-- -- needs to be provided when logging in.+-- --+-- -- /Permissions/: No permission required.+-- mmCheckMfa :: Text -> Session -> IO Bool+-- mmCheckMfa loginId =+-- inPost "/users/mfa" (jsonBody (A.object [ "login_id" A..= loginId ])) jsonResponse++-- -- | Generate a user access token that can be used to authenticate with the+-- -- Mattermost REST API.+-- --+-- --+-- -- /Minimum server version/: 4.1+-- --+-- --+-- -- /Permissions/: Must have @create_user_access_token@ permission. For+-- -- non-self requests, must also have the @edit_other_users@ permission.+-- mmCreateUserAccessToken :: UserId -> Text -> Session -> IO UserAccessToken+-- mmCreateUserAccessToken userId description =+-- inPost (printf "/users/%s/tokens" userId) (jsonBody (A.object [ "description" A..= description ])) jsonResponse++-- -- | Get a list of user access tokens for a user. Does not include the+-- -- actual authentication tokens. Use query paremeters for paging.+-- --+-- --+-- -- /Minimum server version/: 4.1+-- --+-- --+-- -- /Permissions/: Must have @read_user_access_token@ permission. For non-+-- -- self requests, must also have the @edit_other_users@ permission.+-- mmGetUserAccessTokens :: UserId -> Maybe Integer -> Maybe Integer -> Session -> IO (Seq UserAccessTokenSanitized)+-- mmGetUserAccessTokens userId page perPage =+-- inGet (printf "/users/%s/tokens?%s" userId (mkQueryString [ sequence ("page", fmap show page) , sequence ("per_page", fmap show perPage) ])) noBody jsonResponse++-- -- | Revoke a user access token and delete any sessions using the token.+-- --+-- --+-- -- /Minimum server version/: 4.1+-- --+-- --+-- -- /Permissions/: Must have @revoke_user_access_token@ permission. For+-- -- non-self requests, must also have the @edit_other_users@ permission.+-- mmRevokeUserAccessToken :: Text -> Session -> IO ()+-- mmRevokeUserAccessToken token =+-- inPost "/users/tokens/revoke" (jsonBody (A.object [ "token" A..= token ])) jsonResponse++-- -- | Get a user access token. Does not include the actual authentication+-- -- token.+-- --+-- --+-- -- /Minimum server version/: 4.1+-- --+-- --+-- -- /Permissions/: Must have @read_user_access_token@ permission. For non-+-- -- self requests, must also have the @edit_other_users@ permission.+-- mmGetUserAccessToken :: TokenId -> Session -> IO UserAccessTokenSanitized+-- mmGetUserAccessToken tokenId =+-- inGet (printf "/users/tokens/%s" tokenId) noBody jsonResponse++-- -- | Update user active or inactive status+-- --+-- -- /Permissions/: User can deactivate itself.+-- --+-- -- User with @manage_system@ permission can activate or deactivate a+-- -- user.+-- mmUpdateUserActiveStatus :: UserId -> Bool -> Session -> IO ()+-- mmUpdateUserActiveStatus userId active =+-- inPut (printf "/users/%s/active" userId) (jsonBody (A.object [ "active" A..= active ])) jsonResponse++-- -- | Get a user object by providing a username. Sensitive information will+-- -- be sanitized out.+-- --+-- -- /Permissions/: Requires an active session but no other permissions.+-- mmGetUserByUsername :: Text -> Session -> IO User+-- mmGetUserByUsername username =+-- inGet (printf "/users/username/%s" username) noBody jsonResponse++-- -- | Get a list of users based on a provided list of user ids.+-- --+-- -- /Permissions/: Requires an active session but no other permissions.+-- mmGetUsersByIds :: (Seq Text) -> Session -> IO (Seq User)+-- mmGetUsersByIds body =+-- inPost "/users/ids" (jsonBody body) jsonResponse++-- -- | Attach a mobile device id to the currently logged in session. This+-- -- will enable push notiofications for a user, if configured by the+-- -- server.+-- --+-- -- /Permissions/: Must be authenticated.+-- mmAttachMobileDevice :: Text -> Session -> IO ()+-- mmAttachMobileDevice deviceId =+-- inPut "/users/sessions/device" (jsonBody (A.object [ "device_id" A..= deviceId ])) jsonResponse++-- -- | Send an email containing a link for resetting the user's password. The+-- -- link will contain a one-use, timed recovery code tied to the user's+-- -- account. Only works for non-SSO users.+-- --+-- -- /Permissions/: No permissions required.+-- mmSendPasswordResetEmail :: Text -> Session -> IO ()+-- mmSendPasswordResetEmail email =+-- inPost "/users/password/reset/send" (jsonBody (A.object [ "email" A..= email ])) jsonResponse++-- -- | Get a user object by providing a user email. Sensitive information+-- -- will be sanitized out.+-- --+-- -- /Permissions/: Requires an active session but no other permissions.+-- mmGetUserByEmail :: Text -> Session -> IO User+-- mmGetUserByEmail email =+-- inGet (printf "/users/email/%s" email) noBody jsonResponse++-- -- | Switch a user's login method from using email to OAuth2\/SAML\/LDAP or+-- -- back to email. When switching to OAuth2\/SAML, account switching is+-- -- not complete until the user follows the returned link and completes+-- -- any steps on the OAuth2\/SAML service provider.+-- --+-- --+-- -- To switch from email to OAuth2\/SAML, specify @current_service@,+-- -- @new_service@, @email@ and @password@.+-- --+-- --+-- -- To switch from OAuth2\/SAML to email, specify @current_service@,+-- -- @new_service@, @email@ and @new_password@.+-- --+-- --+-- -- To switch from email to LDAP\/AD, specify @current_service@,+-- -- @new_service@, @email@, @password@, @ldap_ip@ and @new_password@ (this+-- -- is the user's LDAP password).+-- --+-- --+-- -- To switch from LDAP\/AD to email, specify @current_service@,+-- -- @new_service@, @ldap_ip@, @password@ (this is the user's LDAP+-- -- password), @email@ and @new_password@.+-- --+-- --+-- -- Additionally, specify @mfa_code@ when trying to switch an account on+-- -- LDAP\/AD or email that has MFA activated.+-- --+-- --+-- -- /Permissions/: No current authentication required except when+-- -- switching from OAuth2\/SAML to email.+-- mmSwitchLoginMethod :: XX19 -> Session -> IO Text+-- mmSwitchLoginMethod body =+-- inPost "/users/login/switch" (jsonBody body) jsonResponse++-- -- | Set a user's profile image based on user_id string parameter.+-- --+-- -- /Permissions/: Must be logged in as the user being updated or have the+-- -- @edit_other_users@ permission.+-- mmSetUsersProfileImage :: UserId -> Session -> IO ()+-- mmSetUsersProfileImage userId =+-- inPost (printf "/users/%s/image" userId) noBody jsonResponse++-- -- | Get a user's profile image based on user_id string parameter.+-- --+-- -- /Permissions/: Must be logged in.+-- mmGetUsersProfileImage :: UserId -> Session -> IO ()+-- mmGetUsersProfileImage userId =+-- inGet (printf "/users/%s/image" userId) noBody jsonResponse++-- -- | Activates multi-factor authentication for the user if @activate@ is+-- -- true and a valid @code@ is provided. If activate is false, then @code@+-- -- is not required and multi-factor authentication is disabled for the+-- -- user.+-- --+-- -- /Permissions/: Must be logged in as the user being updated or have the+-- -- @edit_other_users@ permission.+-- mmUpdateUsersMfa :: UserId -> XX22 -> Session -> IO ()+-- mmUpdateUsersMfa userId body =+-- inPut (printf "/users/%s/mfa" userId) (jsonBody body) jsonResponse++-- -- | Verify the email used by a user to sign-up their account with.+-- --+-- -- /Permissions/: No permissions required.+-- mmVerifyUserEmail :: Text -> Session -> IO ()+-- mmVerifyUserEmail token =+-- inPost "/users/email/verify" (jsonBody (A.object [ "token" A..= token ])) jsonResponse++-- -- | Update the password for a user using a one-use, timed recovery code+-- -- tied to the user's account. Only works for non-SSO users.+-- --+-- -- /Permissions/: No permissions required.+-- mmResetPassword :: XX24 -> Session -> IO ()+-- mmResetPassword body =+-- inPost "/users/password/reset" (jsonBody body) jsonResponse++-- -- | Get a list of audit by providing the user GUID.+-- --+-- -- /Permissions/: Must be logged in as the user or have the+-- -- @edit_other_users@ permission.+-- mmGetUsersAudits :: UserId -> Session -> IO (Seq Audit)+-- mmGetUsersAudits userId =+-- inGet (printf "/users/%s/audits" userId) noBody jsonResponse++-- -- | Update a user's password. New password must meet password policy set+-- -- by server configuration.+-- --+-- -- /Permissions/: Must be logged in as the user the password is being+-- -- changed for or have @manage_system@ permission.+-- mmUpdateUsersPassword :: UserId -> XX29 -> Session -> IO ()+-- mmUpdateUsersPassword userId body =+-- inPut (printf "/users/%s/password" userId) (jsonBody body) jsonResponse++-- -- | Update a user by providing the user object. The fields that can be+-- -- updated are defined in the request body, all other provided fields+-- -- will be ignored.+-- --+-- -- /Permissions/: Must be logged in as the user being updated or have the+-- -- @edit_other_users@ permission.+-- mmUpdateUser :: UserId -> XX30 -> Session -> IO User+-- mmUpdateUser userId body =+-- inPut (printf "/users/%s" userId) (jsonBody body) jsonResponse++-- | Get a user a object. Sensitive information will be sanitized out.+--+-- /Permissions/: Requires an active session but no other permissions.+mmGetUser :: UserParam -> Session -> IO User+mmGetUser userId =+ inGet (printf "/users/%s" userId) noBody jsonResponse++-- | Deactivates the user by archiving its user object.+--+-- /Permissions/: Must be logged in as the user being deactivated or have+-- the @edit_other_users@ permission.+mmDeactivateUserAccount :: UserParam -> Session -> IO ()+mmDeactivateUserAccount userId =+ inDelete (printf "/users/%s" userId) noBody jsonResponse++-- | Create a new user on the system.+--+-- /Permissions/: No permission required but user creation can be+-- controlled by server configuration.+mmCreateUser :: UsersCreate -> Session -> IO User+mmCreateUser body =+ inPost "/users" (jsonBody body) jsonResponse+ -- UsersCreate was XX31++data UserQuery = UserQuery+ { userQueryPage :: Maybe Int+ , userQueryPerPage :: Maybe Int+ , userQueryInTeam :: Maybe TeamId+ , userQueryNotInTeam :: Maybe TeamId+ , userQueryInChannel :: Maybe ChannelId+ , userQueryNotInChannel :: Maybe ChannelId+ , userQueryWithoutTeam :: Maybe Bool+ , userQuerySort :: Maybe UserQuerySort+ }++defaultUserQuery :: UserQuery+defaultUserQuery = UserQuery+ { userQueryPage = Nothing+ , userQueryPerPage = Nothing+ , userQueryInTeam = Nothing+ , userQueryNotInTeam = Nothing+ , userQueryInChannel = Nothing+ , userQueryNotInChannel = Nothing+ , userQueryWithoutTeam = Nothing+ , userQuerySort = Nothing+ }++data UserQuerySort+ = UserQuerySortByLastActivity+ | UserQuerySortByCreation++userQueryToQueryString :: UserQuery -> String+userQueryToQueryString UserQuery { .. } =+ mkQueryString [ sequence ("page", fmap show userQueryPage)+ , sequence ("per_page", fmap show userQueryPerPage)+ , sequence ("in_team", fmap (T.unpack . idString) userQueryInTeam)+ , sequence ("not_in_team", fmap (T.unpack . idString) userQueryNotInTeam)+ , sequence ("in_channel", fmap (T.unpack . idString) userQueryInChannel)+ , sequence ("not_in_channel", fmap (T.unpack . idString) userQueryNotInChannel)+ , sequence ( "without_team"+ , case userQueryWithoutTeam of+ Nothing -> Nothing+ Just True -> Just "true"+ Just False -> Just "false"+ )+ , sequence ( "sort"+ , case userQuerySort of+ Nothing -> Nothing+ Just UserQuerySortByLastActivity -> Just "last_activity_at"+ Just UserQuerySortByCreation -> Just "create_at"+ )+ ]++-- | Get a page of a list of users. Based on query string parameters,+-- select users from a team, channel, or select users not in a specific+-- channel.+--+--+-- Since server version 4.0, some basic sorting is available using the+-- @sort@ query parameter. Sorting is currently only supported when+-- selecting users on a team.+--+-- /Permissions/: Requires an active session and (if specified)+-- membership to the channel or team being selected from.+mmGetUsers+ :: UserQuery+ -> Session+ -> IO (Seq User)+mmGetUsers userQuery =+ inGet (printf "/users?%s" (userQueryToQueryString userQuery)) noBody jsonResponse++-- -- | Generates an multi-factor authentication secret for a user and returns+-- -- it as a string and as base64 encoded QR code image.+-- --+-- -- /Permissions/: Must be logged in as the user or have the+-- -- @edit_other_users@ permission.+-- mmGenerateMfaSecret :: UserId -> Session -> IO XX37+-- mmGenerateMfaSecret userId =+-- inPost (printf "/users/%s/mfa/generate" userId) noBody jsonResponse++-- -- | Partially update a user by providing only the fields you want to+-- -- update. Omitted fields will not be updated. The fields that can be+-- -- updated are defined in the request body, all other provided fields+-- -- will be ignored.+-- --+-- -- /Permissions/: Must be logged in as the user being updated or have the+-- -- @edit_other_users@ permission.+-- mmPatchUser :: UserId -> XX38 -> Session -> IO User+-- mmPatchUser userId body =+-- inPut (printf "/users/%s/patch" userId) (jsonBody body) jsonResponse++-- -- | Get a list of users for the purpose of autocompleting based on the+-- -- provided search term. Specify a combination of @team_id@ and+-- -- @channel_id@ to filter results further.+-- --+-- -- /Permissions/: Requires an active session and @view_team@ and+-- -- @read_channel@ on any teams or channels used to filter the results+-- -- further.+-- mmAutocompleteUsers :: TeamId -> ChannelId -> Text -> Session -> IO UserAutocomplete+-- mmAutocompleteUsers teamId channelId name =+-- inGet (printf "/users/autocomplete?%s" (mkQueryString [ Just ("team_id", T.unpack (idString teamId)) , Just ("channel_id", T.unpack (idString channelId)) , Just ("name", T.unpack name) ])) noBody jsonResponse++++-- * Webhooks++-- -- | Update an outgoing webhook given the hook id.+-- --+-- -- /Permissions/: @manage_webhooks@ for system or @manage_webhooks@ for+-- -- the specific team or @manage_webhooks@ for the channel.+-- mmUpdateAnOutgoingWebhook :: HookId -> XX12 -> Session -> IO OutgoingWebhook+-- mmUpdateAnOutgoingWebhook hookId body =+-- inPut (printf "/hooks/outgoing/%s" hookId) (jsonBody body) jsonResponse++-- -- | Get an outgoing webhook given the hook id.+-- --+-- -- /Permissions/: @manage_webhooks@ for system or @manage_webhooks@ for+-- -- the specific team or @manage_webhooks@ for the channel.+-- mmGetAnOutgoingWebhook :: HookId -> Session -> IO OutgoingWebhook+-- mmGetAnOutgoingWebhook hookId =+-- inGet (printf "/hooks/outgoing/%s" hookId) noBody jsonResponse++-- -- | Delete an outgoing webhook given the hook id.+-- --+-- -- /Permissions/: @manage_webhooks@ for system or @manage_webhooks@ for+-- -- the specific team or @manage_webhooks@ for the channel.+-- mmDeleteAnOutgoingWebhook :: HookId -> Session -> IO ()+-- mmDeleteAnOutgoingWebhook hookId =+-- inDelete (printf "/hooks/outgoing/%s" hookId) noBody jsonResponse++-- -- | Regenerate the token for the outgoing webhook.+-- --+-- -- /Permissions/: @manage_webhooks@ for system or @manage_webhooks@ for+-- -- the specific team or @manage_webhooks@ for the channel.+-- mmRegenerateTokenForOutgoingWebhook :: HookId -> Session -> IO ()+-- mmRegenerateTokenForOutgoingWebhook hookId =+-- inPost (printf "/hooks/outgoing/%s/regen_token" hookId) noBody jsonResponse++-- -- | Create an incoming webhook for a channel.+-- --+-- -- /Permissions/: @manage_webhooks@ for the channel the webhook is in.+-- mmCreateAnIncomingWebhook :: XX25 -> Session -> IO IncomingWebhook+-- mmCreateAnIncomingWebhook body =+-- inPost "/hooks/incoming" (jsonBody body) jsonResponse++-- -- | Get a page of a list of incoming webhooks. Optionally filter for a+-- -- specific team using query parameters.+-- --+-- -- /Permissions/: @manage_webhooks@ for the system or @manage_webhooks@+-- -- for the specific team.+-- mmListIncomingWebhooks :: Maybe Integer -> Maybe Integer -> TeamId -> Session -> IO (Seq IncomingWebhook)+-- mmListIncomingWebhooks page perPage teamId =+-- inGet (printf "/hooks/incoming?%s" (mkQueryString [ sequence ("page", fmap show page) , sequence ("per_page", fmap show perPage) , Just ("team_id", T.unpack (idString teamId)) ])) noBody jsonResponse++-- -- | Create an outgoing webhook for a team.+-- --+-- -- /Permissions/: @manage_webhooks@ for the team the webhook is in.+-- mmCreateAnOutgoingWebhook :: XX33 -> Session -> IO OutgoingWebhook+-- mmCreateAnOutgoingWebhook body =+-- inPost "/hooks/outgoing" (jsonBody body) jsonResponse++-- -- | Get a page of a list of outgoing webhooks. Optionally filter for a+-- -- specific team or channel using query parameters.+-- --+-- -- /Permissions/: @manage_webhooks@ for the system or @manage_webhooks@+-- -- for the specific team\/channel.+-- mmListOutgoingWebhooks :: Maybe Integer -> Maybe Integer -> TeamId -> ChannelId -> Session -> IO (Seq OutgoingWebhook)+-- mmListOutgoingWebhooks page perPage teamId channelId =+-- inGet (printf "/hooks/outgoing?%s" (mkQueryString [ sequence ("page", fmap show page) , sequence ("per_page", fmap show perPage) , Just ("team_id", T.unpack (idString teamId)) , Just ("channel_id", T.unpack (idString channelId)) ])) noBody jsonResponse++-- -- | Update an incoming webhook given the hook id.+-- --+-- -- /Permissions/: @manage_webhooks@ for system or @manage_webhooks@ for+-- -- the specific team or @manage_webhooks@ for the channel.+-- mmUpdateAnIncomingWebhook :: HookId -> XX35 -> Session -> IO IncomingWebhook+-- mmUpdateAnIncomingWebhook hookId body =+-- inPut (printf "/hooks/incoming/%s" hookId) (jsonBody body) jsonResponse++-- -- | Get an incoming webhook given the hook id.+-- --+-- -- /Permissions/: @manage_webhooks@ for system or @manage_webhooks@ for+-- -- the specific team or @manage_webhooks@ for the channel.+-- mmGetAnIncomingWebhook :: HookId -> Session -> IO IncomingWebhook+-- mmGetAnIncomingWebhook hookId =+-- inGet (printf "/hooks/incoming/%s" hookId) noBody jsonResponse++-- data AppError = AppError+-- { appErrorStatusCode :: Integer+-- , appErrorMessage :: Text+-- , appErrorId :: Text+-- , appErrorRequestId :: Text+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON AppError where+-- parseJSON = A.withObject "appError" $ \v -> do+-- appErrorStatusCode <- v A..: "status_code"+-- appErrorMessage <- v A..: "message"+-- appErrorId <- v A..: "id"+-- appErrorRequestId <- v A..: "request_id"+-- return AppError { .. }++-- instance A.ToJSON AppError where+-- toJSON AppError { .. } = A.object+-- [ "status_code" A..= appErrorStatusCode+-- , "message" A..= appErrorMessage+-- , "id" A..= appErrorId+-- , "request_id" A..= appErrorRequestId+-- ]++-- ** User Statuses++mmGetUserStatus :: UserParam -> Session -> IO T.Text+mmGetUserStatus userId =+ inGet (printf "/users/%s/status" userId) noBody jsonResponse++getUserStatusesByIds :: Seq UserId -> Session -> IO (HM.HashMap UserId T.Text)+getUserStatusesByIds body =+ inPost (printf "/users/%s/status/ids") (jsonBody body) jsonResponse++-- updateUserStatus :: UserParam -> Session -> IO ()+-- updateUserStatus =+-- inPut++-- --++-- data Article = Article+-- { articlePublishedTime :: Text+-- , articleTags :: (Seq Text)+-- , articleSection :: Text+-- , articleAuthors :: (Seq XX4)+-- , articleExpirationTime :: Text+-- , articleModifiedTime :: Text+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON Article where+-- parseJSON = A.withObject "article" $ \v -> do+-- articlePublishedTime <- v A..: "published_time"+-- articleTags <- v A..: "tags"+-- articleSection <- v A..: "section"+-- articleAuthors <- v A..: "authors"+-- articleExpirationTime <- v A..: "expiration_time"+-- articleModifiedTime <- v A..: "modified_time"+-- return Article { .. }++-- instance A.ToJSON Article where+-- toJSON Article { .. } = A.object+-- [ "published_time" A..= articlePublishedTime+-- , "tags" A..= articleTags+-- , "section" A..= articleSection+-- , "authors" A..= articleAuthors+-- , "expiration_time" A..= articleExpirationTime+-- , "modified_time" A..= articleModifiedTime+-- ]++-- --++-- data Audit = Audit+-- { auditUserId :: Text+-- , auditAction :: Text+-- , auditExtraInfo :: Text+-- , auditIpAddress :: Text+-- , auditCreateAt :: UnknownType+-- , auditSessionId :: Text+-- , auditId :: Text+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON Audit where+-- parseJSON = A.withObject "audit" $ \v -> do+-- auditUserId <- v A..: "user_id"+-- auditAction <- v A..: "action"+-- auditExtraInfo <- v A..: "extra_info"+-- auditIpAddress <- v A..: "ip_address"+-- auditCreateAt <- v A..: "create_at"+-- auditSessionId <- v A..: "session_id"+-- auditId <- v A..: "id"+-- return Audit { .. }++-- instance A.ToJSON Audit where+-- toJSON Audit { .. } = A.object+-- [ "user_id" A..= auditUserId+-- , "action" A..= auditAction+-- , "extra_info" A..= auditExtraInfo+-- , "ip_address" A..= auditIpAddress+-- , "create_at" A..= auditCreateAt+-- , "session_id" A..= auditSessionId+-- , "id" A..= auditId+-- ]++-- --++-- data Book = Book+-- { bookReleaseDate :: Text+-- , bookTags :: (Seq Text)+-- , bookIsbn :: Text+-- , bookAuthors :: (Seq XX2)+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON Book where+-- parseJSON = A.withObject "book" $ \v -> do+-- bookReleaseDate <- v A..: "release_date"+-- bookTags <- v A..: "tags"+-- bookIsbn <- v A..: "isbn"+-- bookAuthors <- v A..: "authors"+-- return Book { .. }++-- instance A.ToJSON Book where+-- toJSON Book { .. } = A.object+-- [ "release_date" A..= bookReleaseDate+-- , "tags" A..= bookTags+-- , "isbn" A..= bookIsbn+-- , "authors" A..= bookAuthors+-- ]++-- --++-- --++-- data ClusterInfo = ClusterInfo+-- { clusterInfoLastPing :: Integer+-- , clusterInfoVersion :: Text+-- -- ^ The server version the node is on+-- , clusterInfoInternodeUrl :: Text+-- -- ^ The URL used to communicate with those node from other nodes+-- , clusterInfoConfigHash :: Text+-- -- ^ The hash of the configuartion file the node is using+-- , clusterInfoHostname :: Text+-- -- ^ The hostname for this node+-- , clusterInfoIsAlive :: UnknownType+-- -- ^ Whether or not the node is alive and well+-- , clusterInfoId :: Text+-- -- ^ The unique ID for the node+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON ClusterInfo where+-- parseJSON = A.withObject "clusterInfo" $ \v -> do+-- clusterInfoLastPing <- v A..: "last_ping"+-- clusterInfoVersion <- v A..: "version"+-- clusterInfoInternodeUrl <- v A..: "internode_url"+-- clusterInfoConfigHash <- v A..: "config_hash"+-- clusterInfoHostname <- v A..: "hostname"+-- clusterInfoIsAlive <- v A..: "is_alive"+-- clusterInfoId <- v A..: "id"+-- return ClusterInfo { .. }++-- instance A.ToJSON ClusterInfo where+-- toJSON ClusterInfo { .. } = A.object+-- [ "last_ping" A..= clusterInfoLastPing+-- , "version" A..= clusterInfoVersion+-- , "internode_url" A..= clusterInfoInternodeUrl+-- , "config_hash" A..= clusterInfoConfigHash+-- , "hostname" A..= clusterInfoHostname+-- , "is_alive" A..= clusterInfoIsAlive+-- , "id" A..= clusterInfoId+-- ]++-- --++-- data ClusterSettings = ClusterSettings+-- { clusterSettingsInternodeurls :: (Seq Text)+-- , clusterSettingsEnable :: UnknownType+-- , clusterSettingsInternodelistenaddress :: Text+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON ClusterSettings where+-- parseJSON = A.withObject "clusterSettings" $ \v -> do+-- clusterSettingsInternodeurls <- v A..: "InterNodeUrls"+-- clusterSettingsEnable <- v A..: "Enable"+-- clusterSettingsInternodelistenaddress <- v A..: "InterNodeListenAddress"+-- return ClusterSettings { .. }++-- instance A.ToJSON ClusterSettings where+-- toJSON ClusterSettings { .. } = A.object+-- [ "InterNodeUrls" A..= clusterSettingsInternodeurls+-- , "Enable" A..= clusterSettingsEnable+-- , "InterNodeListenAddress" A..= clusterSettingsInternodelistenaddress+-- ]++-- --++-- data Compliance = Compliance+-- { complianceStatus :: Text+-- , complianceCount :: UnknownType+-- , complianceUserId :: Text+-- , complianceId :: Text+-- , complianceCreateAt :: UnknownType+-- , complianceEndAt :: UnknownType+-- , complianceKeywords :: Text+-- , complianceStartAt :: UnknownType+-- , complianceType :: Text+-- , complianceEmails :: Text+-- , complianceDesc :: Text+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON Compliance where+-- parseJSON = A.withObject "compliance" $ \v -> do+-- complianceStatus <- v A..: "status"+-- complianceCount <- v A..: "count"+-- complianceUserId <- v A..: "user_id"+-- complianceId <- v A..: "id"+-- complianceCreateAt <- v A..: "create_at"+-- complianceEndAt <- v A..: "end_at"+-- complianceKeywords <- v A..: "keywords"+-- complianceStartAt <- v A..: "start_at"+-- complianceType <- v A..: "type"+-- complianceEmails <- v A..: "emails"+-- complianceDesc <- v A..: "desc"+-- return Compliance { .. }++-- instance A.ToJSON Compliance where+-- toJSON Compliance { .. } = A.object+-- [ "status" A..= complianceStatus+-- , "count" A..= complianceCount+-- , "user_id" A..= complianceUserId+-- , "id" A..= complianceId+-- , "create_at" A..= complianceCreateAt+-- , "end_at" A..= complianceEndAt+-- , "keywords" A..= complianceKeywords+-- , "start_at" A..= complianceStartAt+-- , "type" A..= complianceType+-- , "emails" A..= complianceEmails+-- , "desc" A..= complianceDesc+-- ]++-- --++-- --++-- --++-- data Emoji = Emoji+-- { emojiCreatorId :: Text+-- , emojiName :: Text+-- -- ^ The name of the emoji+-- , emojiDeleteAt :: UnknownType+-- -- ^ The time at which the emoji was deleted.+-- , emojiUpdateAt :: UnknownType+-- -- ^ The time at which the emoji was updated.+-- , emojiCreateAt :: UnknownType+-- -- ^ The time at which the emoji was made+-- , emojiId :: Text+-- -- ^ The ID of the emoji+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON Emoji where+-- parseJSON = A.withObject "emoji" $ \v -> do+-- emojiCreatorId <- v A..: "creator_id"+-- emojiName <- v A..: "name"+-- emojiDeleteAt <- v A..: "delete_at"+-- emojiUpdateAt <- v A..: "update_at"+-- emojiCreateAt <- v A..: "create_at"+-- emojiId <- v A..: "id"+-- return Emoji { .. }++-- instance A.ToJSON Emoji where+-- toJSON Emoji { .. } = A.object+-- [ "creator_id" A..= emojiCreatorId+-- , "name" A..= emojiName+-- , "delete_at" A..= emojiDeleteAt+-- , "update_at" A..= emojiUpdateAt+-- , "create_at" A..= emojiCreateAt+-- , "id" A..= emojiId+-- ]++-- --++-- data FileSettings = FileSettings+-- { fileSettingsInitialfont :: Text+-- , fileSettingsThumbnailwidth :: UnknownType+-- , fileSettingsAmazons3accesskeyid :: Text+-- , fileSettingsAmazons3region :: Text+-- , fileSettingsPreviewwidth :: UnknownType+-- , fileSettingsAmazons3endpoint :: Text+-- , fileSettingsDirectory :: Text+-- , fileSettingsThumbnailheight :: UnknownType+-- , fileSettingsAmazons3bucket :: Text+-- , fileSettingsAmazons3secretaccesskey :: Text+-- , fileSettingsAmazons3ssl :: UnknownType+-- , fileSettingsPreviewheight :: UnknownType+-- , fileSettingsEnablepubliclink :: UnknownType+-- , fileSettingsMaxfilesize :: UnknownType+-- , fileSettingsProfilewidth :: UnknownType+-- , fileSettingsProfileheight :: UnknownType+-- , fileSettingsPubliclinksalt :: Text+-- , fileSettingsDrivername :: Text+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON FileSettings where+-- parseJSON = A.withObject "fileSettings" $ \v -> do+-- fileSettingsInitialfont <- v A..: "InitialFont"+-- fileSettingsThumbnailwidth <- v A..: "ThumbnailWidth"+-- fileSettingsAmazons3accesskeyid <- v A..: "AmazonS3AccessKeyId"+-- fileSettingsAmazons3region <- v A..: "AmazonS3Region"+-- fileSettingsPreviewwidth <- v A..: "PreviewWidth"+-- fileSettingsAmazons3endpoint <- v A..: "AmazonS3Endpoint"+-- fileSettingsDirectory <- v A..: "Directory"+-- fileSettingsThumbnailheight <- v A..: "ThumbnailHeight"+-- fileSettingsAmazons3bucket <- v A..: "AmazonS3Bucket"+-- fileSettingsAmazons3secretaccesskey <- v A..: "AmazonS3SecretAccessKey"+-- fileSettingsAmazons3ssl <- v A..: "AmazonS3SSL"+-- fileSettingsPreviewheight <- v A..: "PreviewHeight"+-- fileSettingsEnablepubliclink <- v A..: "EnablePublicLink"+-- fileSettingsMaxfilesize <- v A..: "MaxFileSize"+-- fileSettingsProfilewidth <- v A..: "ProfileWidth"+-- fileSettingsProfileheight <- v A..: "ProfileHeight"+-- fileSettingsPubliclinksalt <- v A..: "PublicLinkSalt"+-- fileSettingsDrivername <- v A..: "DriverName"+-- return FileSettings { .. }++-- instance A.ToJSON FileSettings where+-- toJSON FileSettings { .. } = A.object+-- [ "InitialFont" A..= fileSettingsInitialfont+-- , "ThumbnailWidth" A..= fileSettingsThumbnailwidth+-- , "AmazonS3AccessKeyId" A..= fileSettingsAmazons3accesskeyid+-- , "AmazonS3Region" A..= fileSettingsAmazons3region+-- , "PreviewWidth" A..= fileSettingsPreviewwidth+-- , "AmazonS3Endpoint" A..= fileSettingsAmazons3endpoint+-- , "Directory" A..= fileSettingsDirectory+-- , "ThumbnailHeight" A..= fileSettingsThumbnailheight+-- , "AmazonS3Bucket" A..= fileSettingsAmazons3bucket+-- , "AmazonS3SecretAccessKey" A..= fileSettingsAmazons3secretaccesskey+-- , "AmazonS3SSL" A..= fileSettingsAmazons3ssl+-- , "PreviewHeight" A..= fileSettingsPreviewheight+-- , "EnablePublicLink" A..= fileSettingsEnablepubliclink+-- , "MaxFileSize" A..= fileSettingsMaxfilesize+-- , "ProfileWidth" A..= fileSettingsProfilewidth+-- , "ProfileHeight" A..= fileSettingsProfileheight+-- , "PublicLinkSalt" A..= fileSettingsPubliclinksalt+-- , "DriverName" A..= fileSettingsDrivername+-- ]++-- --++-- data GitLabSettings = GitLabSettings+-- { gitLabSettingsSecret :: Text+-- , gitLabSettingsEnable :: UnknownType+-- , gitLabSettingsScope :: Text+-- , gitLabSettingsUserapiendpoint :: Text+-- , gitLabSettingsTokenendpoint :: Text+-- , gitLabSettingsAuthendpoint :: Text+-- , gitLabSettingsId :: Text+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON GitLabSettings where+-- parseJSON = A.withObject "gitLabSettings" $ \v -> do+-- gitLabSettingsSecret <- v A..: "Secret"+-- gitLabSettingsEnable <- v A..: "Enable"+-- gitLabSettingsScope <- v A..: "Scope"+-- gitLabSettingsUserapiendpoint <- v A..: "UserApiEndpoint"+-- gitLabSettingsTokenendpoint <- v A..: "TokenEndpoint"+-- gitLabSettingsAuthendpoint <- v A..: "AuthEndpoint"+-- gitLabSettingsId <- v A..: "Id"+-- return GitLabSettings { .. }++-- instance A.ToJSON GitLabSettings where+-- toJSON GitLabSettings { .. } = A.object+-- [ "Secret" A..= gitLabSettingsSecret+-- , "Enable" A..= gitLabSettingsEnable+-- , "Scope" A..= gitLabSettingsScope+-- , "UserApiEndpoint" A..= gitLabSettingsUserapiendpoint+-- , "TokenEndpoint" A..= gitLabSettingsTokenendpoint+-- , "AuthEndpoint" A..= gitLabSettingsAuthendpoint+-- , "Id" A..= gitLabSettingsId+-- ]++-- --++-- data GoogleSettings = GoogleSettings+-- { googleSettingsSecret :: Text+-- , googleSettingsEnable :: UnknownType+-- , googleSettingsScope :: Text+-- , googleSettingsUserapiendpoint :: Text+-- , googleSettingsTokenendpoint :: Text+-- , googleSettingsAuthendpoint :: Text+-- , googleSettingsId :: Text+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON GoogleSettings where+-- parseJSON = A.withObject "googleSettings" $ \v -> do+-- googleSettingsSecret <- v A..: "Secret"+-- googleSettingsEnable <- v A..: "Enable"+-- googleSettingsScope <- v A..: "Scope"+-- googleSettingsUserapiendpoint <- v A..: "UserApiEndpoint"+-- googleSettingsTokenendpoint <- v A..: "TokenEndpoint"+-- googleSettingsAuthendpoint <- v A..: "AuthEndpoint"+-- googleSettingsId <- v A..: "Id"+-- return GoogleSettings { .. }++-- instance A.ToJSON GoogleSettings where+-- toJSON GoogleSettings { .. } = A.object+-- [ "Secret" A..= googleSettingsSecret+-- , "Enable" A..= googleSettingsEnable+-- , "Scope" A..= googleSettingsScope+-- , "UserApiEndpoint" A..= googleSettingsUserapiendpoint+-- , "TokenEndpoint" A..= googleSettingsTokenendpoint+-- , "AuthEndpoint" A..= googleSettingsAuthendpoint+-- , "Id" A..= googleSettingsId+-- ]++-- --++-- data IncomingWebhook = IncomingWebhook+-- { incomingWebhookChannelId :: Text+-- , incomingWebhookDisplayName :: Text+-- -- ^ The display name for this incoming webhook+-- , incomingWebhookDescription :: Text+-- -- ^ The description for this incoming webhook+-- , incomingWebhookDeleteAt :: UnknownType+-- , incomingWebhookUpdateAt :: UnknownType+-- , incomingWebhookCreateAt :: UnknownType+-- , incomingWebhookId :: Text+-- -- ^ The unique identifier for this incoming webhook+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON IncomingWebhook where+-- parseJSON = A.withObject "incomingWebhook" $ \v -> do+-- incomingWebhookChannelId <- v A..: "channel_id"+-- incomingWebhookDisplayName <- v A..: "display_name"+-- incomingWebhookDescription <- v A..: "description"+-- incomingWebhookDeleteAt <- v A..: "delete_at"+-- incomingWebhookUpdateAt <- v A..: "update_at"+-- incomingWebhookCreateAt <- v A..: "create_at"+-- incomingWebhookId <- v A..: "id"+-- return IncomingWebhook { .. }++-- instance A.ToJSON IncomingWebhook where+-- toJSON IncomingWebhook { .. } = A.object+-- [ "channel_id" A..= incomingWebhookChannelId+-- , "display_name" A..= incomingWebhookDisplayName+-- , "description" A..= incomingWebhookDescription+-- , "delete_at" A..= incomingWebhookDeleteAt+-- , "update_at" A..= incomingWebhookUpdateAt+-- , "create_at" A..= incomingWebhookCreateAt+-- , "id" A..= incomingWebhookId+-- ]++-- --++-- data Job = Job+-- { jobStatus :: Text+-- , jobStartAt :: UnknownType+-- -- ^ The time at which the job was started+-- , jobType :: Text+-- -- ^ The type of job+-- , jobCreateAt :: UnknownType+-- -- ^ The time at which the job was created+-- , jobId :: Text+-- -- ^ The unique id of the job+-- , jobProgress :: UnknownType+-- -- ^ The progress (as a percentage) of the job+-- , jobData :: UnknownType+-- -- ^ A freeform data field containing additional information about the job+-- , jobLastActivityAt :: UnknownType+-- -- ^ The last time at which the job had activity+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON Job where+-- parseJSON = A.withObject "job" $ \v -> do+-- jobStatus <- v A..: "status"+-- jobStartAt <- v A..: "start_at"+-- jobType <- v A..: "type"+-- jobCreateAt <- v A..: "create_at"+-- jobId <- v A..: "id"+-- jobProgress <- v A..: "progress"+-- jobData <- v A..: "data"+-- jobLastActivityAt <- v A..: "last_activity_at"+-- return Job { .. }++-- instance A.ToJSON Job where+-- toJSON Job { .. } = A.object+-- [ "status" A..= jobStatus+-- , "start_at" A..= jobStartAt+-- , "type" A..= jobType+-- , "create_at" A..= jobCreateAt+-- , "id" A..= jobId+-- , "progress" A..= jobProgress+-- , "data" A..= jobData+-- , "last_activity_at" A..= jobLastActivityAt+-- ]++-- --++-- data LdapSettings = LdapSettings+-- { ldapSettingsLastnameattribute :: Text+-- , ldapSettingsIdattribute :: Text+-- , ldapSettingsSyncintervalminutes :: UnknownType+-- , ldapSettingsLoginfieldname :: Text+-- , ldapSettingsLdapserver :: Text+-- , ldapSettingsLdapport :: UnknownType+-- , ldapSettingsUsernameattribute :: Text+-- , ldapSettingsMaxpagesize :: UnknownType+-- , ldapSettingsEnable :: UnknownType+-- , ldapSettingsUserfilter :: Text+-- , ldapSettingsBindpassword :: Text+-- , ldapSettingsSkipcertificateverification :: UnknownType+-- , ldapSettingsQuerytimeout :: UnknownType+-- , ldapSettingsBasedn :: Text+-- , ldapSettingsPositionattribute :: Text+-- , ldapSettingsEmailattribute :: Text+-- , ldapSettingsConnectionsecurity :: Text+-- , ldapSettingsBindusername :: Text+-- , ldapSettingsFirstnameattribute :: Text+-- , ldapSettingsNicknameattribute :: Text+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON LdapSettings where+-- parseJSON = A.withObject "ldapSettings" $ \v -> do+-- ldapSettingsLastnameattribute <- v A..: "LastNameAttribute"+-- ldapSettingsIdattribute <- v A..: "IdAttribute"+-- ldapSettingsSyncintervalminutes <- v A..: "SyncIntervalMinutes"+-- ldapSettingsLoginfieldname <- v A..: "LoginFieldName"+-- ldapSettingsLdapserver <- v A..: "LdapServer"+-- ldapSettingsLdapport <- v A..: "LdapPort"+-- ldapSettingsUsernameattribute <- v A..: "UsernameAttribute"+-- ldapSettingsMaxpagesize <- v A..: "MaxPageSize"+-- ldapSettingsEnable <- v A..: "Enable"+-- ldapSettingsUserfilter <- v A..: "UserFilter"+-- ldapSettingsBindpassword <- v A..: "BindPassword"+-- ldapSettingsSkipcertificateverification <- v A..: "SkipCertificateVerification"+-- ldapSettingsQuerytimeout <- v A..: "QueryTimeout"+-- ldapSettingsBasedn <- v A..: "BaseDN"+-- ldapSettingsPositionattribute <- v A..: "PositionAttribute"+-- ldapSettingsEmailattribute <- v A..: "EmailAttribute"+-- ldapSettingsConnectionsecurity <- v A..: "ConnectionSecurity"+-- ldapSettingsBindusername <- v A..: "BindUsername"+-- ldapSettingsFirstnameattribute <- v A..: "FirstNameAttribute"+-- ldapSettingsNicknameattribute <- v A..: "NicknameAttribute"+-- return LdapSettings { .. }++-- instance A.ToJSON LdapSettings where+-- toJSON LdapSettings { .. } = A.object+-- [ "LastNameAttribute" A..= ldapSettingsLastnameattribute+-- , "IdAttribute" A..= ldapSettingsIdattribute+-- , "SyncIntervalMinutes" A..= ldapSettingsSyncintervalminutes+-- , "LoginFieldName" A..= ldapSettingsLoginfieldname+-- , "LdapServer" A..= ldapSettingsLdapserver+-- , "LdapPort" A..= ldapSettingsLdapport+-- , "UsernameAttribute" A..= ldapSettingsUsernameattribute+-- , "MaxPageSize" A..= ldapSettingsMaxpagesize+-- , "Enable" A..= ldapSettingsEnable+-- , "UserFilter" A..= ldapSettingsUserfilter+-- , "BindPassword" A..= ldapSettingsBindpassword+-- , "SkipCertificateVerification" A..= ldapSettingsSkipcertificateverification+-- , "QueryTimeout" A..= ldapSettingsQuerytimeout+-- , "BaseDN" A..= ldapSettingsBasedn+-- , "PositionAttribute" A..= ldapSettingsPositionattribute+-- , "EmailAttribute" A..= ldapSettingsEmailattribute+-- , "ConnectionSecurity" A..= ldapSettingsConnectionsecurity+-- , "BindUsername" A..= ldapSettingsBindusername+-- , "FirstNameAttribute" A..= ldapSettingsFirstnameattribute+-- , "NicknameAttribute" A..= ldapSettingsNicknameattribute+-- ]++-- --++-- data LocalizationSettings = LocalizationSettings+-- { localizationSettingsDefaultclientlocale :: Text+-- , localizationSettingsAvailablelocales :: Text+-- , localizationSettingsDefaultserverlocale :: Text+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON LocalizationSettings where+-- parseJSON = A.withObject "localizationSettings" $ \v -> do+-- localizationSettingsDefaultclientlocale <- v A..: "DefaultClientLocale"+-- localizationSettingsAvailablelocales <- v A..: "AvailableLocales"+-- localizationSettingsDefaultserverlocale <- v A..: "DefaultServerLocale"+-- return LocalizationSettings { .. }++-- instance A.ToJSON LocalizationSettings where+-- toJSON LocalizationSettings { .. } = A.object+-- [ "DefaultClientLocale" A..= localizationSettingsDefaultclientlocale+-- , "AvailableLocales" A..= localizationSettingsAvailablelocales+-- , "DefaultServerLocale" A..= localizationSettingsDefaultserverlocale+-- ]++-- --++-- --++-- --++-- data OAuthApp = OAuthApp+-- { oAuthAppDescription :: Text+-- , oAuthAppIconUrl :: Text+-- -- ^ A URL to an icon to display with the application+-- , oAuthAppUpdateAt :: UnknownType+-- -- ^ The last time of update for the application+-- , oAuthAppCreateAt :: UnknownType+-- -- ^ The time of registration for the application+-- , oAuthAppIsTrusted :: UnknownType+-- -- ^ Set this to `true` to skip asking users for permission+-- , oAuthAppClientSecret :: Text+-- -- ^ The client secret of the application+-- , oAuthAppCallbackUrls :: (Seq Text)+-- -- ^ A list of callback URLs for the appliation+-- , oAuthAppHomepage :: Text+-- -- ^ A link to the website of the application+-- , oAuthAppId :: Text+-- -- ^ The client id of the application+-- , oAuthAppName :: Text+-- -- ^ The name of the client application+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON OAuthApp where+-- parseJSON = A.withObject "oAuthApp" $ \v -> do+-- oAuthAppDescription <- v A..: "description"+-- oAuthAppIconUrl <- v A..: "icon_url"+-- oAuthAppUpdateAt <- v A..: "update_at"+-- oAuthAppCreateAt <- v A..: "create_at"+-- oAuthAppIsTrusted <- v A..: "is_trusted"+-- oAuthAppClientSecret <- v A..: "client_secret"+-- oAuthAppCallbackUrls <- v A..: "callback_urls"+-- oAuthAppHomepage <- v A..: "homepage"+-- oAuthAppId <- v A..: "id"+-- oAuthAppName <- v A..: "name"+-- return OAuthApp { .. }++-- instance A.ToJSON OAuthApp where+-- toJSON OAuthApp { .. } = A.object+-- [ "description" A..= oAuthAppDescription+-- , "icon_url" A..= oAuthAppIconUrl+-- , "update_at" A..= oAuthAppUpdateAt+-- , "create_at" A..= oAuthAppCreateAt+-- , "is_trusted" A..= oAuthAppIsTrusted+-- , "client_secret" A..= oAuthAppClientSecret+-- , "callback_urls" A..= oAuthAppCallbackUrls+-- , "homepage" A..= oAuthAppHomepage+-- , "id" A..= oAuthAppId+-- , "name" A..= oAuthAppName+-- ]++-- --++-- data Office365Settings = Office365Settings+-- { office365SettingsSecret :: Text+-- , office365SettingsEnable :: UnknownType+-- , office365SettingsScope :: Text+-- , office365SettingsUserapiendpoint :: Text+-- , office365SettingsTokenendpoint :: Text+-- , office365SettingsAuthendpoint :: Text+-- , office365SettingsId :: Text+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON Office365Settings where+-- parseJSON = A.withObject "office365Settings" $ \v -> do+-- office365SettingsSecret <- v A..: "Secret"+-- office365SettingsEnable <- v A..: "Enable"+-- office365SettingsScope <- v A..: "Scope"+-- office365SettingsUserapiendpoint <- v A..: "UserApiEndpoint"+-- office365SettingsTokenendpoint <- v A..: "TokenEndpoint"+-- office365SettingsAuthendpoint <- v A..: "AuthEndpoint"+-- office365SettingsId <- v A..: "Id"+-- return Office365Settings { .. }++-- instance A.ToJSON Office365Settings where+-- toJSON Office365Settings { .. } = A.object+-- [ "Secret" A..= office365SettingsSecret+-- , "Enable" A..= office365SettingsEnable+-- , "Scope" A..= office365SettingsScope+-- , "UserApiEndpoint" A..= office365SettingsUserapiendpoint+-- , "TokenEndpoint" A..= office365SettingsTokenendpoint+-- , "AuthEndpoint" A..= office365SettingsAuthendpoint+-- , "Id" A..= office365SettingsId+-- ]++-- --++-- data OpenGraph = OpenGraph+-- { openGraphProfile :: UnknownObject+-- , openGraphSiteName :: Text+-- , openGraphDescription :: Text+-- , openGraphVideos :: (Seq XX1)+-- , openGraphTitle :: Text+-- , openGraphUrl :: Text+-- , openGraphLocalesAlternate :: (Seq Text)+-- , openGraphLocale :: Text+-- , openGraphBook :: Book+-- -- ^ Book object used in OpenGraph metadata of a webpage, if type is book+-- , openGraphImages :: (Seq XX3)+-- , openGraphArticle :: Article+-- -- ^ Article object used in OpenGraph metadata of a webpage, if type is article+-- , openGraphAudios :: (Seq XX5)+-- , openGraphType :: Text+-- , openGraphDeterminer :: Text+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON OpenGraph where+-- parseJSON = A.withObject "openGraph" $ \v -> do+-- openGraphProfile <- v A..: "profile"+-- openGraphSiteName <- v A..: "site_name"+-- openGraphDescription <- v A..: "description"+-- openGraphVideos <- v A..: "videos"+-- openGraphTitle <- v A..: "title"+-- openGraphUrl <- v A..: "url"+-- openGraphLocalesAlternate <- v A..: "locales_alternate"+-- openGraphLocale <- v A..: "locale"+-- openGraphBook <- v A..: "book"+-- openGraphImages <- v A..: "images"+-- openGraphArticle <- v A..: "article"+-- openGraphAudios <- v A..: "audios"+-- openGraphType <- v A..: "type"+-- openGraphDeterminer <- v A..: "determiner"+-- return OpenGraph { .. }++-- instance A.ToJSON OpenGraph where+-- toJSON OpenGraph { .. } = A.object+-- [ "profile" A..= openGraphProfile+-- , "site_name" A..= openGraphSiteName+-- , "description" A..= openGraphDescription+-- , "videos" A..= openGraphVideos+-- , "title" A..= openGraphTitle+-- , "url" A..= openGraphUrl+-- , "locales_alternate" A..= openGraphLocalesAlternate+-- , "locale" A..= openGraphLocale+-- , "book" A..= openGraphBook+-- , "images" A..= openGraphImages+-- , "article" A..= openGraphArticle+-- , "audios" A..= openGraphAudios+-- , "type" A..= openGraphType+-- , "determiner" A..= openGraphDeterminer+-- ]++-- --++-- data OutgoingWebhook = OutgoingWebhook+-- { outgoingWebhookTriggerWhen :: Integer+-- , outgoingWebhookDisplayName :: Text+-- -- ^ The display name for this outgoing webhook+-- , outgoingWebhookDescription :: Text+-- -- ^ The description for this outgoing webhook+-- , outgoingWebhookDeleteAt :: UnknownType+-- , outgoingWebhookUpdateAt :: UnknownType+-- , outgoingWebhookCreateAt :: UnknownType+-- , outgoingWebhookChannelId :: Text+-- -- ^ The ID of a public channel that the webhook watchs+-- , outgoingWebhookCreatorId :: Text+-- -- ^ The Id of the user who created the webhook+-- , outgoingWebhookContentType :: Text+-- -- ^ The format to POST the data in, either `application/json` or `application/x-www-form-urlencoded`+-- , outgoingWebhookTriggerWords :: (Seq Text)+-- -- ^ List of words for the webhook to trigger on+-- , outgoingWebhookTeamId :: Text+-- -- ^ The ID of the team that the webhook watchs+-- , outgoingWebhookCallbackUrls :: (Seq Text)+-- -- ^ The URLs to POST the payloads to when the webhook is triggered+-- , outgoingWebhookId :: Text+-- -- ^ The unique identifier for this outgoing webhook+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON OutgoingWebhook where+-- parseJSON = A.withObject "outgoingWebhook" $ \v -> do+-- outgoingWebhookTriggerWhen <- v A..: "trigger_when"+-- outgoingWebhookDisplayName <- v A..: "display_name"+-- outgoingWebhookDescription <- v A..: "description"+-- outgoingWebhookDeleteAt <- v A..: "delete_at"+-- outgoingWebhookUpdateAt <- v A..: "update_at"+-- outgoingWebhookCreateAt <- v A..: "create_at"+-- outgoingWebhookChannelId <- v A..: "channel_id"+-- outgoingWebhookCreatorId <- v A..: "creator_id"+-- outgoingWebhookContentType <- v A..: "content_type"+-- outgoingWebhookTriggerWords <- v A..: "trigger_words"+-- outgoingWebhookTeamId <- v A..: "team_id"+-- outgoingWebhookCallbackUrls <- v A..: "callback_urls"+-- outgoingWebhookId <- v A..: "id"+-- return OutgoingWebhook { .. }++-- instance A.ToJSON OutgoingWebhook where+-- toJSON OutgoingWebhook { .. } = A.object+-- [ "trigger_when" A..= outgoingWebhookTriggerWhen+-- , "display_name" A..= outgoingWebhookDisplayName+-- , "description" A..= outgoingWebhookDescription+-- , "delete_at" A..= outgoingWebhookDeleteAt+-- , "update_at" A..= outgoingWebhookUpdateAt+-- , "create_at" A..= outgoingWebhookCreateAt+-- , "channel_id" A..= outgoingWebhookChannelId+-- , "creator_id" A..= outgoingWebhookCreatorId+-- , "content_type" A..= outgoingWebhookContentType+-- , "trigger_words" A..= outgoingWebhookTriggerWords+-- , "team_id" A..= outgoingWebhookTeamId+-- , "callback_urls" A..= outgoingWebhookCallbackUrls+-- , "id" A..= outgoingWebhookId+-- ]++-- --++-- --++-- data SamlCertificateStatus = SamlCertificateStatus+-- { samlCertificateStatusIdpCertificateFile :: Bool+-- , samlCertificateStatusPrivateKeyFile :: UnknownType+-- -- ^ Status is good when `true`+-- , samlCertificateStatusPublicCertificateFile :: UnknownType+-- -- ^ Status is good when `true`+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON SamlCertificateStatus where+-- parseJSON = A.withObject "samlCertificateStatus" $ \v -> do+-- samlCertificateStatusIdpCertificateFile <- v A..: "idp_certificate_file"+-- samlCertificateStatusPrivateKeyFile <- v A..: "private_key_file"+-- samlCertificateStatusPublicCertificateFile <- v A..: "public_certificate_file"+-- return SamlCertificateStatus { .. }++-- instance A.ToJSON SamlCertificateStatus where+-- toJSON SamlCertificateStatus { .. } = A.object+-- [ "idp_certificate_file" A..= samlCertificateStatusIdpCertificateFile+-- , "private_key_file" A..= samlCertificateStatusPrivateKeyFile+-- , "public_certificate_file" A..= samlCertificateStatusPublicCertificateFile+-- ]++-- --++-- data SamlSettings = SamlSettings+-- { samlSettingsLoginbuttontext :: Text+-- , samlSettingsLastnameattribute :: Text+-- , samlSettingsEncrypt :: UnknownType+-- , samlSettingsIdpurl :: Text+-- , samlSettingsVerify :: UnknownType+-- , samlSettingsAssertionconsumerserviceurl :: Text+-- , samlSettingsUsernameattribute :: Text+-- , samlSettingsLocaleattribute :: Text+-- , samlSettingsFirstnameattribute :: Text+-- , samlSettingsEnable :: UnknownType+-- , samlSettingsNicknameattribute :: Text+-- , samlSettingsPositionattribute :: Text+-- , samlSettingsIdpdescriptorurl :: Text+-- , samlSettingsPrivatekeyfile :: Text+-- , samlSettingsIdpcertificatefile :: Text+-- , samlSettingsEmailattribute :: Text+-- , samlSettingsPubliccertificatefile :: Text+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON SamlSettings where+-- parseJSON = A.withObject "samlSettings" $ \v -> do+-- samlSettingsLoginbuttontext <- v A..: "LoginButtonText"+-- samlSettingsLastnameattribute <- v A..: "LastNameAttribute"+-- samlSettingsEncrypt <- v A..: "Encrypt"+-- samlSettingsIdpurl <- v A..: "IdpUrl"+-- samlSettingsVerify <- v A..: "Verify"+-- samlSettingsAssertionconsumerserviceurl <- v A..: "AssertionConsumerServiceURL"+-- samlSettingsUsernameattribute <- v A..: "UsernameAttribute"+-- samlSettingsLocaleattribute <- v A..: "LocaleAttribute"+-- samlSettingsFirstnameattribute <- v A..: "FirstNameAttribute"+-- samlSettingsEnable <- v A..: "Enable"+-- samlSettingsNicknameattribute <- v A..: "NicknameAttribute"+-- samlSettingsPositionattribute <- v A..: "PositionAttribute"+-- samlSettingsIdpdescriptorurl <- v A..: "IdpDescriptorUrl"+-- samlSettingsPrivatekeyfile <- v A..: "PrivateKeyFile"+-- samlSettingsIdpcertificatefile <- v A..: "IdpCertificateFile"+-- samlSettingsEmailattribute <- v A..: "EmailAttribute"+-- samlSettingsPubliccertificatefile <- v A..: "PublicCertificateFile"+-- return SamlSettings { .. }++-- instance A.ToJSON SamlSettings where+-- toJSON SamlSettings { .. } = A.object+-- [ "LoginButtonText" A..= samlSettingsLoginbuttontext+-- , "LastNameAttribute" A..= samlSettingsLastnameattribute+-- , "Encrypt" A..= samlSettingsEncrypt+-- , "IdpUrl" A..= samlSettingsIdpurl+-- , "Verify" A..= samlSettingsVerify+-- , "AssertionConsumerServiceURL" A..= samlSettingsAssertionconsumerserviceurl+-- , "UsernameAttribute" A..= samlSettingsUsernameattribute+-- , "LocaleAttribute" A..= samlSettingsLocaleattribute+-- , "FirstNameAttribute" A..= samlSettingsFirstnameattribute+-- , "Enable" A..= samlSettingsEnable+-- , "NicknameAttribute" A..= samlSettingsNicknameattribute+-- , "PositionAttribute" A..= samlSettingsPositionattribute+-- , "IdpDescriptorUrl" A..= samlSettingsIdpdescriptorurl+-- , "PrivateKeyFile" A..= samlSettingsPrivatekeyfile+-- , "IdpCertificateFile" A..= samlSettingsIdpcertificatefile+-- , "EmailAttribute" A..= samlSettingsEmailattribute+-- , "PublicCertificateFile" A..= samlSettingsPubliccertificatefile+-- ]++-- --++-- data ServiceSettings = ServiceSettings+-- { serviceSettingsEnableposticonoverride :: Bool+-- , serviceSettingsSegmentdeveloperkey :: Text+-- , serviceSettingsEnablepostusernameoverride :: UnknownType+-- , serviceSettingsForward80to443 :: UnknownType+-- , serviceSettingsEnableincomingwebhooks :: UnknownType+-- , serviceSettingsSessionlengthmobileindays :: UnknownType+-- , serviceSettingsUseletsencrypt :: UnknownType+-- , serviceSettingsRestrictcustomemojicreation :: Text+-- , serviceSettingsReadtimeout :: UnknownType+-- , serviceSettingsEnableoutgoingwebhooks :: UnknownType+-- , serviceSettingsTlscertfile :: Text+-- , serviceSettingsEnableonlyadminintegrations :: UnknownType+-- , serviceSettingsEnableinsecureoutgoingconnections :: UnknownType+-- , serviceSettingsEnableoauthserviceprovider :: UnknownType+-- , serviceSettingsEnablecustomemoji :: UnknownType+-- , serviceSettingsEnabletesting :: UnknownType+-- , serviceSettingsSessioncacheinminutes :: UnknownType+-- , serviceSettingsSessionlengthwebindays :: UnknownType+-- , serviceSettingsWebservermode :: Text+-- , serviceSettingsEnablesecurityfixalert :: UnknownType+-- , serviceSettingsEnablemultifactorauthentication :: UnknownType+-- , serviceSettingsEnabledeveloper :: UnknownType+-- , serviceSettingsSiteurl :: Text+-- , serviceSettingsTlskeyfile :: Text+-- , serviceSettingsListenaddress :: Text+-- , serviceSettingsGoogledeveloperkey :: Text+-- , serviceSettingsEnforcemultifactorauthentication :: UnknownType+-- , serviceSettingsLetsencryptcertificatecachefile :: Text+-- , serviceSettingsWebsocketport :: UnknownType+-- , serviceSettingsWebsocketsecureport :: UnknownType+-- , serviceSettingsAllowcorsfrom :: Text+-- , serviceSettingsSessionlengthssoindays :: UnknownType+-- , serviceSettingsEnablecommands :: UnknownType+-- , serviceSettingsConnectionsecurity :: Text+-- , serviceSettingsWritetimeout :: UnknownType+-- , serviceSettingsMaximumloginattempts :: UnknownType+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON ServiceSettings where+-- parseJSON = A.withObject "serviceSettings" $ \v -> do+-- serviceSettingsEnableposticonoverride <- v A..: "EnablePostIconOverride"+-- serviceSettingsSegmentdeveloperkey <- v A..: "SegmentDeveloperKey"+-- serviceSettingsEnablepostusernameoverride <- v A..: "EnablePostUsernameOverride"+-- serviceSettingsForward80to443 <- v A..: "Forward80To443"+-- serviceSettingsEnableincomingwebhooks <- v A..: "EnableIncomingWebhooks"+-- serviceSettingsSessionlengthmobileindays <- v A..: "SessionLengthMobileInDays"+-- serviceSettingsUseletsencrypt <- v A..: "UseLetsEncrypt"+-- serviceSettingsRestrictcustomemojicreation <- v A..: "RestrictCustomEmojiCreation"+-- serviceSettingsReadtimeout <- v A..: "ReadTimeout"+-- serviceSettingsEnableoutgoingwebhooks <- v A..: "EnableOutgoingWebhooks"+-- serviceSettingsTlscertfile <- v A..: "TLSCertFile"+-- serviceSettingsEnableonlyadminintegrations <- v A..: "EnableOnlyAdminIntegrations"+-- serviceSettingsEnableinsecureoutgoingconnections <- v A..: "EnableInsecureOutgoingConnections"+-- serviceSettingsEnableoauthserviceprovider <- v A..: "EnableOAuthServiceProvider"+-- serviceSettingsEnablecustomemoji <- v A..: "EnableCustomEmoji"+-- serviceSettingsEnabletesting <- v A..: "EnableTesting"+-- serviceSettingsSessioncacheinminutes <- v A..: "SessionCacheInMinutes"+-- serviceSettingsSessionlengthwebindays <- v A..: "SessionLengthWebInDays"+-- serviceSettingsWebservermode <- v A..: "WebserverMode"+-- serviceSettingsEnablesecurityfixalert <- v A..: "EnableSecurityFixAlert"+-- serviceSettingsEnablemultifactorauthentication <- v A..: "EnableMultifactorAuthentication"+-- serviceSettingsEnabledeveloper <- v A..: "EnableDeveloper"+-- serviceSettingsSiteurl <- v A..: "SiteURL"+-- serviceSettingsTlskeyfile <- v A..: "TLSKeyFile"+-- serviceSettingsListenaddress <- v A..: "ListenAddress"+-- serviceSettingsGoogledeveloperkey <- v A..: "GoogleDeveloperKey"+-- serviceSettingsEnforcemultifactorauthentication <- v A..: "EnforceMultifactorAuthentication"+-- serviceSettingsLetsencryptcertificatecachefile <- v A..: "LetsEncryptCertificateCacheFile"+-- serviceSettingsWebsocketport <- v A..: "WebsocketPort"+-- serviceSettingsWebsocketsecureport <- v A..: "WebsocketSecurePort"+-- serviceSettingsAllowcorsfrom <- v A..: "AllowCorsFrom"+-- serviceSettingsSessionlengthssoindays <- v A..: "SessionLengthSSOInDays"+-- serviceSettingsEnablecommands <- v A..: "EnableCommands"+-- serviceSettingsConnectionsecurity <- v A..: "ConnectionSecurity"+-- serviceSettingsWritetimeout <- v A..: "WriteTimeout"+-- serviceSettingsMaximumloginattempts <- v A..: "MaximumLoginAttempts"+-- return ServiceSettings { .. }++-- instance A.ToJSON ServiceSettings where+-- toJSON ServiceSettings { .. } = A.object+-- [ "EnablePostIconOverride" A..= serviceSettingsEnableposticonoverride+-- , "SegmentDeveloperKey" A..= serviceSettingsSegmentdeveloperkey+-- , "EnablePostUsernameOverride" A..= serviceSettingsEnablepostusernameoverride+-- , "Forward80To443" A..= serviceSettingsForward80to443+-- , "EnableIncomingWebhooks" A..= serviceSettingsEnableincomingwebhooks+-- , "SessionLengthMobileInDays" A..= serviceSettingsSessionlengthmobileindays+-- , "UseLetsEncrypt" A..= serviceSettingsUseletsencrypt+-- , "RestrictCustomEmojiCreation" A..= serviceSettingsRestrictcustomemojicreation+-- , "ReadTimeout" A..= serviceSettingsReadtimeout+-- , "EnableOutgoingWebhooks" A..= serviceSettingsEnableoutgoingwebhooks+-- , "TLSCertFile" A..= serviceSettingsTlscertfile+-- , "EnableOnlyAdminIntegrations" A..= serviceSettingsEnableonlyadminintegrations+-- , "EnableInsecureOutgoingConnections" A..= serviceSettingsEnableinsecureoutgoingconnections+-- , "EnableOAuthServiceProvider" A..= serviceSettingsEnableoauthserviceprovider+-- , "EnableCustomEmoji" A..= serviceSettingsEnablecustomemoji+-- , "EnableTesting" A..= serviceSettingsEnabletesting+-- , "SessionCacheInMinutes" A..= serviceSettingsSessioncacheinminutes+-- , "SessionLengthWebInDays" A..= serviceSettingsSessionlengthwebindays+-- , "WebserverMode" A..= serviceSettingsWebservermode+-- , "EnableSecurityFixAlert" A..= serviceSettingsEnablesecurityfixalert+-- , "EnableMultifactorAuthentication" A..= serviceSettingsEnablemultifactorauthentication+-- , "EnableDeveloper" A..= serviceSettingsEnabledeveloper+-- , "SiteURL" A..= serviceSettingsSiteurl+-- , "TLSKeyFile" A..= serviceSettingsTlskeyfile+-- , "ListenAddress" A..= serviceSettingsListenaddress+-- , "GoogleDeveloperKey" A..= serviceSettingsGoogledeveloperkey+-- , "EnforceMultifactorAuthentication" A..= serviceSettingsEnforcemultifactorauthentication+-- , "LetsEncryptCertificateCacheFile" A..= serviceSettingsLetsencryptcertificatecachefile+-- , "WebsocketPort" A..= serviceSettingsWebsocketport+-- , "WebsocketSecurePort" A..= serviceSettingsWebsocketsecureport+-- , "AllowCorsFrom" A..= serviceSettingsAllowcorsfrom+-- , "SessionLengthSSOInDays" A..= serviceSettingsSessionlengthssoindays+-- , "EnableCommands" A..= serviceSettingsEnablecommands+-- , "ConnectionSecurity" A..= serviceSettingsConnectionsecurity+-- , "WriteTimeout" A..= serviceSettingsWritetimeout+-- , "MaximumLoginAttempts" A..= serviceSettingsMaximumloginattempts+-- ]++-- --++-- data SlackAttachment = SlackAttachment+-- { slackAttachmentTitlelink :: Text+-- , slackAttachmentFooter :: Text+-- , slackAttachmentFields :: (Seq SlackAttachmentField)+-- , slackAttachmentImageurl :: Text+-- , slackAttachmentAuthorname :: Text+-- , slackAttachmentThumburl :: Text+-- , slackAttachmentTitle :: Text+-- , slackAttachmentFallback :: Text+-- , slackAttachmentColor :: Text+-- , slackAttachmentText :: Text+-- , slackAttachmentAuthorlink :: Text+-- , slackAttachmentAuthoricon :: Text+-- , slackAttachmentTimestamp :: Text+-- -- ^ The timestamp of the slack attahment, either type of string or integer+-- , slackAttachmentPretext :: Text+-- , slackAttachmentId :: Text+-- , slackAttachmentFootericon :: Text+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON SlackAttachment where+-- parseJSON = A.withObject "slackAttachment" $ \v -> do+-- slackAttachmentTitlelink <- v A..: "TitleLink"+-- slackAttachmentFooter <- v A..: "Footer"+-- slackAttachmentFields <- v A..: "Fields"+-- slackAttachmentImageurl <- v A..: "ImageURL"+-- slackAttachmentAuthorname <- v A..: "AuthorName"+-- slackAttachmentThumburl <- v A..: "ThumbURL"+-- slackAttachmentTitle <- v A..: "Title"+-- slackAttachmentFallback <- v A..: "Fallback"+-- slackAttachmentColor <- v A..: "Color"+-- slackAttachmentText <- v A..: "Text"+-- slackAttachmentAuthorlink <- v A..: "AuthorLink"+-- slackAttachmentAuthoricon <- v A..: "AuthorIcon"+-- slackAttachmentTimestamp <- v A..: "Timestamp"+-- slackAttachmentPretext <- v A..: "Pretext"+-- slackAttachmentId <- v A..: "Id"+-- slackAttachmentFootericon <- v A..: "FooterIcon"+-- return SlackAttachment { .. }++-- instance A.ToJSON SlackAttachment where+-- toJSON SlackAttachment { .. } = A.object+-- [ "TitleLink" A..= slackAttachmentTitlelink+-- , "Footer" A..= slackAttachmentFooter+-- , "Fields" A..= slackAttachmentFields+-- , "ImageURL" A..= slackAttachmentImageurl+-- , "AuthorName" A..= slackAttachmentAuthorname+-- , "ThumbURL" A..= slackAttachmentThumburl+-- , "Title" A..= slackAttachmentTitle+-- , "Fallback" A..= slackAttachmentFallback+-- , "Color" A..= slackAttachmentColor+-- , "Text" A..= slackAttachmentText+-- , "AuthorLink" A..= slackAttachmentAuthorlink+-- , "AuthorIcon" A..= slackAttachmentAuthoricon+-- , "Timestamp" A..= slackAttachmentTimestamp+-- , "Pretext" A..= slackAttachmentPretext+-- , "Id" A..= slackAttachmentId+-- , "FooterIcon" A..= slackAttachmentFootericon+-- ]++-- --++-- data SlackAttachmentField = SlackAttachmentField+-- { slackAttachmentFieldShort :: Bool+-- , slackAttachmentFieldValue :: Text+-- -- ^ The value of the attachment, set as string but capable with golang interface+-- , slackAttachmentFieldTitle :: Text+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON SlackAttachmentField where+-- parseJSON = A.withObject "slackAttachmentField" $ \v -> do+-- slackAttachmentFieldShort <- v A..: "Short"+-- slackAttachmentFieldValue <- v A..: "Value"+-- slackAttachmentFieldTitle <- v A..: "Title"+-- return SlackAttachmentField { .. }++-- instance A.ToJSON SlackAttachmentField where+-- toJSON SlackAttachmentField { .. } = A.object+-- [ "Short" A..= slackAttachmentFieldShort+-- , "Value" A..= slackAttachmentFieldValue+-- , "Title" A..= slackAttachmentFieldTitle+-- ]++-- --++-- data Status = Status+-- { statusStatus :: Text+-- , statusActiveChannel :: Text+-- , statusManual :: UnknownType+-- , statusLastActivityAt :: UnknownType+-- , statusUserId :: Text+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON Status where+-- parseJSON = A.withObject "status" $ \v -> do+-- statusStatus <- v A..: "status"+-- statusActiveChannel <- v A..: "active_channel"+-- statusManual <- v A..: "manual"+-- statusLastActivityAt <- v A..: "last_activity_at"+-- statusUserId <- v A..: "user_id"+-- return Status { .. }++-- instance A.ToJSON Status where+-- toJSON Status { .. } = A.object+-- [ "status" A..= statusStatus+-- , "active_channel" A..= statusActiveChannel+-- , "manual" A..= statusManual+-- , "last_activity_at" A..= statusLastActivityAt+-- , "user_id" A..= statusUserId+-- ]++-- --++-- newtype StatusOK = StatusOK+-- { statusOKStatus :: Text+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON StatusOK where+-- parseJSON = A.withObject "statusOK" $ \v -> do+-- statusOKStatus <- v A..: "status"+-- return StatusOK { .. }++-- instance A.ToJSON StatusOK where+-- toJSON StatusOK { .. } = A.object+-- [ "status" A..= statusOKStatus+-- ]++-- --++-- --++-- newtype TeamExists = TeamExists+-- { teamExistsExists :: Bool+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON TeamExists where+-- parseJSON = A.withObject "teamExists" $ \v -> do+-- teamExistsExists <- v A..: "exists"+-- return TeamExists { .. }++-- instance A.ToJSON TeamExists where+-- toJSON TeamExists { .. } = A.object+-- [ "exists" A..= teamExistsExists+-- ]++-- --++-- newtype TeamMap = TeamMap+-- { teamMapTeamId :: Team+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON TeamMap where+-- parseJSON = A.withObject "teamMap" $ \v -> do+-- teamMapTeamId <- v A..: "team_id"+-- return TeamMap { .. }++-- instance A.ToJSON TeamMap where+-- toJSON TeamMap { .. } = A.object+-- [ "team_id" A..= teamMapTeamId+-- ]++-- --++-- --++-- data TeamStats = TeamStats+-- { teamStatsTeamId :: Text+-- , teamStatsActiveMemberCount :: UnknownType+-- , teamStatsTotalMemberCount :: UnknownType+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON TeamStats where+-- parseJSON = A.withObject "teamStats" $ \v -> do+-- teamStatsTeamId <- v A..: "team_id"+-- teamStatsActiveMemberCount <- v A..: "active_member_count"+-- teamStatsTotalMemberCount <- v A..: "total_member_count"+-- return TeamStats { .. }++-- instance A.ToJSON TeamStats where+-- toJSON TeamStats { .. } = A.object+-- [ "team_id" A..= teamStatsTeamId+-- , "active_member_count" A..= teamStatsActiveMemberCount+-- , "total_member_count" A..= teamStatsTotalMemberCount+-- ]++-- --++-- data TeamUnread = TeamUnread+-- { teamUnreadTeamId :: Text+-- , teamUnreadMsgCount :: UnknownType+-- , teamUnreadMentionCount :: UnknownType+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON TeamUnread where+-- parseJSON = A.withObject "teamUnread" $ \v -> do+-- teamUnreadTeamId <- v A..: "team_id"+-- teamUnreadMsgCount <- v A..: "msg_count"+-- teamUnreadMentionCount <- v A..: "mention_count"+-- return TeamUnread { .. }++-- instance A.ToJSON TeamUnread where+-- toJSON TeamUnread { .. } = A.object+-- [ "team_id" A..= teamUnreadTeamId+-- , "msg_count" A..= teamUnreadMsgCount+-- , "mention_count" A..= teamUnreadMentionCount+-- ]++-- --++-- data UserAccessToken = UserAccessToken+-- { userAccessTokenToken :: Text+-- , userAccessTokenUserId :: Text+-- -- ^ The user the token authenticates for+-- , userAccessTokenId :: Text+-- -- ^ Unique identifier for the token+-- , userAccessTokenDescription :: Text+-- -- ^ A description of the token usage+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON UserAccessToken where+-- parseJSON = A.withObject "userAccessToken" $ \v -> do+-- userAccessTokenToken <- v A..: "token"+-- userAccessTokenUserId <- v A..: "user_id"+-- userAccessTokenId <- v A..: "id"+-- userAccessTokenDescription <- v A..: "description"+-- return UserAccessToken { .. }++-- instance A.ToJSON UserAccessToken where+-- toJSON UserAccessToken { .. } = A.object+-- [ "token" A..= userAccessTokenToken+-- , "user_id" A..= userAccessTokenUserId+-- , "id" A..= userAccessTokenId+-- , "description" A..= userAccessTokenDescription+-- ]++-- --++-- data UserAccessTokenSanitized = UserAccessTokenSanitized+-- { userAccessTokenSanitizedUserId :: Text+-- , userAccessTokenSanitizedId :: Text+-- -- ^ Unique identifier for the token+-- , userAccessTokenSanitizedDescription :: Text+-- -- ^ A description of the token usage+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON UserAccessTokenSanitized where+-- parseJSON = A.withObject "userAccessTokenSanitized" $ \v -> do+-- userAccessTokenSanitizedUserId <- v A..: "user_id"+-- userAccessTokenSanitizedId <- v A..: "id"+-- userAccessTokenSanitizedDescription <- v A..: "description"+-- return UserAccessTokenSanitized { .. }++-- instance A.ToJSON UserAccessTokenSanitized where+-- toJSON UserAccessTokenSanitized { .. } = A.object+-- [ "user_id" A..= userAccessTokenSanitizedUserId+-- , "id" A..= userAccessTokenSanitizedId+-- , "description" A..= userAccessTokenSanitizedDescription+-- ]++-- --++-- data UserAutocomplete = UserAutocomplete+-- { userAutocompleteUsers :: (Seq User)+-- , userAutocompleteOutOfChannel :: (Seq User)+-- -- ^ A special case list of users returned when autocompleting in a specific channel. Omitted when empty or not relevant+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON UserAutocomplete where+-- parseJSON = A.withObject "userAutocomplete" $ \v -> do+-- userAutocompleteUsers <- v A..: "users"+-- userAutocompleteOutOfChannel <- v A..: "out_of_channel"+-- return UserAutocomplete { .. }++-- instance A.ToJSON UserAutocomplete where+-- toJSON UserAutocomplete { .. } = A.object+-- [ "users" A..= userAutocompleteUsers+-- , "out_of_channel" A..= userAutocompleteOutOfChannel+-- ]++-- --++-- data UserAutocompleteInChannel = UserAutocompleteInChannel+-- { userAutocompleteInChannelInChannel :: (Seq User)+-- , userAutocompleteInChannelOutOfChannel :: (Seq User)+-- -- ^ A list of user objects not in the channel+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON UserAutocompleteInChannel where+-- parseJSON = A.withObject "userAutocompleteInChannel" $ \v -> do+-- userAutocompleteInChannelInChannel <- v A..: "in_channel"+-- userAutocompleteInChannelOutOfChannel <- v A..: "out_of_channel"+-- return UserAutocompleteInChannel { .. }++-- instance A.ToJSON UserAutocompleteInChannel where+-- toJSON UserAutocompleteInChannel { .. } = A.object+-- [ "in_channel" A..= userAutocompleteInChannelInChannel+-- , "out_of_channel" A..= userAutocompleteInChannelOutOfChannel+-- ]++-- --++-- newtype UserAutocompleteInTeam = UserAutocompleteInTeam+-- { userAutocompleteInTeamInTeam :: (Seq User)+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON UserAutocompleteInTeam where+-- parseJSON = A.withObject "userAutocompleteInTeam" $ \v -> do+-- userAutocompleteInTeamInTeam <- v A..: "in_team"+-- return UserAutocompleteInTeam { .. }++-- instance A.ToJSON UserAutocompleteInTeam where+-- toJSON UserAutocompleteInTeam { .. } = A.object+-- [ "in_team" A..= userAutocompleteInTeamInTeam+-- ]++-- --++-- --++-- data XX1 = XX1+-- { xx1Url :: Text+-- , xx1Width :: UnknownType+-- , xx1SecureUrl :: Text+-- , xx1Type :: Text+-- , xx1Height :: UnknownType+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX1 where+-- parseJSON = A.withObject "xx1" $ \v -> do+-- xx1Url <- v A..: "url"+-- xx1Width <- v A..: "width"+-- xx1SecureUrl <- v A..: "secure_url"+-- xx1Type <- v A..: "type"+-- xx1Height <- v A..: "height"+-- return XX1 { .. }++-- instance A.ToJSON XX1 where+-- toJSON XX1 { .. } = A.object+-- [ "url" A..= xx1Url+-- , "width" A..= xx1Width+-- , "secure_url" A..= xx1SecureUrl+-- , "type" A..= xx1Type+-- , "height" A..= xx1Height+-- ]++-- --++-- data XX10 = XX10+-- { xx10IsOrSearch :: Bool+-- , xx10Terms :: Text+-- -- ^ The search terms as inputed by the user.+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX10 where+-- parseJSON = A.withObject "xx10" $ \v -> do+-- xx10IsOrSearch <- v A..: "is_or_search"+-- xx10Terms <- v A..: "terms"+-- return XX10 { .. }++-- instance A.ToJSON XX10 where+-- toJSON XX10 { .. } = A.object+-- [ "is_or_search" A..= xx10IsOrSearch+-- , "terms" A..= xx10Terms+-- ]++-- --++-- --++-- data XX12 = XX12+-- { xx12HookId :: Text+-- , xx12ChannelId :: Text+-- -- ^ The ID of a public channel or private group that receives the webhook payloads.+-- , xx12DisplayName :: Text+-- -- ^ The display name for this incoming webhook+-- , xx12Description :: Text+-- -- ^ The description for this incoming webhook+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX12 where+-- parseJSON = A.withObject "xx12" $ \v -> do+-- xx12HookId <- v A..: "hook_id"+-- xx12ChannelId <- v A..: "channel_id"+-- xx12DisplayName <- v A..: "display_name"+-- xx12Description <- v A..: "description"+-- return XX12 { .. }++-- instance A.ToJSON XX12 where+-- toJSON XX12 { .. } = A.object+-- [ "hook_id" A..= xx12HookId+-- , "channel_id" A..= xx12ChannelId+-- , "display_name" A..= xx12DisplayName+-- , "description" A..= xx12Description+-- ]++-- --++-- data XX13 = XX13+-- { xx13Name :: Text+-- , xx13IconUrl :: Text+-- -- ^ A URL to an icon to display with the application+-- , xx13CallbackUrls :: (Seq Text)+-- -- ^ A list of callback URLs for the appliation+-- , xx13Homepage :: Text+-- -- ^ A link to the website of the application+-- , xx13IsTrusted :: UnknownType+-- -- ^ Set this to `true` to skip asking users for permission+-- , xx13Description :: Text+-- -- ^ A short description of the application+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX13 where+-- parseJSON = A.withObject "xx13" $ \v -> do+-- xx13Name <- v A..: "name"+-- xx13IconUrl <- v A..: "icon_url"+-- xx13CallbackUrls <- v A..: "callback_urls"+-- xx13Homepage <- v A..: "homepage"+-- xx13IsTrusted <- v A..: "is_trusted"+-- xx13Description <- v A..: "description"+-- return XX13 { .. }++-- instance A.ToJSON XX13 where+-- toJSON XX13 { .. } = A.object+-- [ "name" A..= xx13Name+-- , "icon_url" A..= xx13IconUrl+-- , "callback_urls" A..= xx13CallbackUrls+-- , "homepage" A..= xx13Homepage+-- , "is_trusted" A..= xx13IsTrusted+-- , "description" A..= xx13Description+-- ]++-- --++-- --++-- data XX15 = XX15+-- { xx15ClientIds :: (Seq Text)+-- , xx15FileInfos :: (Seq FileInfo)+-- -- ^ A list of file metadata that has been stored in the database+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX15 where+-- parseJSON = A.withObject "xx15" $ \v -> do+-- xx15ClientIds <- v A..: "client_ids"+-- xx15FileInfos <- v A..: "file_infos"+-- return XX15 { .. }++-- instance A.ToJSON XX15 where+-- toJSON XX15 { .. } = A.object+-- [ "client_ids" A..= xx15ClientIds+-- , "file_infos" A..= xx15FileInfos+-- ]++-- --++-- --++-- data XX17 = XX17+-- { xx17MarkUnread :: Text+-- , xx17Desktop :: Text+-- -- ^ Controls when to send desktop notifications. The possible options are `default`, `all`, `mention`, `none`+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX17 where+-- parseJSON = A.withObject "xx17" $ \v -> do+-- xx17MarkUnread <- v A..: "mark_unread"+-- xx17Desktop <- v A..: "desktop"+-- return XX17 { .. }++-- instance A.ToJSON XX17 where+-- toJSON XX17 { .. } = A.object+-- [ "mark_unread" A..= xx17MarkUnread+-- , "desktop" A..= xx17Desktop+-- ]++-- --++-- --++-- data XX19 = XX19+-- { xx19LdapId :: Text+-- , xx19CurrentService :: Text+-- -- ^ The service the user currently uses to login+-- , xx19NewService :: Text+-- -- ^ The service the user will use to login+-- , xx19Password :: Text+-- -- ^ The password used with the current service+-- , xx19Email :: Text+-- -- ^ The email of the user+-- , xx19MfaCode :: Text+-- -- ^ The MFA code of the current service+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX19 where+-- parseJSON = A.withObject "xx19" $ \v -> do+-- xx19LdapId <- v A..: "ldap_id"+-- xx19CurrentService <- v A..: "current_service"+-- xx19NewService <- v A..: "new_service"+-- xx19Password <- v A..: "password"+-- xx19Email <- v A..: "email"+-- xx19MfaCode <- v A..: "mfa_code"+-- return XX19 { .. }++-- instance A.ToJSON XX19 where+-- toJSON XX19 { .. } = A.object+-- [ "ldap_id" A..= xx19LdapId+-- , "current_service" A..= xx19CurrentService+-- , "new_service" A..= xx19NewService+-- , "password" A..= xx19Password+-- , "email" A..= xx19Email+-- , "mfa_code" A..= xx19MfaCode+-- ]++-- --++-- data XX2 = XX2+-- { xx2Username :: Text+-- , xx2Gender :: Text+-- , xx2FirstName :: Text+-- , xx2LastName :: Text+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX2 where+-- parseJSON = A.withObject "xx2" $ \v -> do+-- xx2Username <- v A..: "username"+-- xx2Gender <- v A..: "gender"+-- xx2FirstName <- v A..: "first_name"+-- xx2LastName <- v A..: "last_name"+-- return XX2 { .. }++-- instance A.ToJSON XX2 where+-- toJSON XX2 { .. } = A.object+-- [ "username" A..= xx2Username+-- , "gender" A..= xx2Gender+-- , "first_name" A..= xx2FirstName+-- , "last_name" A..= xx2LastName+-- ]++-- --++-- data XX20 = XX20+-- { xx20Type :: Text+-- , xx20Data :: UnknownType+-- -- ^ An object containing any additional data required for this job type+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX20 where+-- parseJSON = A.withObject "xx20" $ \v -> do+-- xx20Type <- v A..: "type"+-- xx20Data <- v A..: "data"+-- return XX20 { .. }++-- instance A.ToJSON XX20 where+-- toJSON XX20 { .. } = A.object+-- [ "type" A..= xx20Type+-- , "data" A..= xx20Data+-- ]++--++-- --++-- data XX22 = XX22+-- { xx22Code :: Text+-- , xx22Activate :: UnknownType+-- -- ^ Use `true` to activate, `false` to deactivate+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX22 where+-- parseJSON = A.withObject "xx22" $ \v -> do+-- xx22Code <- v A..: "code"+-- xx22Activate <- v A..: "activate"+-- return XX22 { .. }++-- instance A.ToJSON XX22 where+-- toJSON XX22 { .. } = A.object+-- [ "code" A..= xx22Code+-- , "activate" A..= xx22Activate+-- ]++-- --++-- data XX23 = XX23+-- { xx23DisplayName :: Text+-- , xx23CompanyName :: Text+-- , xx23InviteId :: Text+-- , xx23Description :: Text+-- , xx23AllowOpenInvite :: UnknownType+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX23 where+-- parseJSON = A.withObject "xx23" $ \v -> do+-- xx23DisplayName <- v A..: "display_name"+-- xx23CompanyName <- v A..: "company_name"+-- xx23InviteId <- v A..: "invite_id"+-- xx23Description <- v A..: "description"+-- xx23AllowOpenInvite <- v A..: "allow_open_invite"+-- return XX23 { .. }++-- instance A.ToJSON XX23 where+-- toJSON XX23 { .. } = A.object+-- [ "display_name" A..= xx23DisplayName+-- , "company_name" A..= xx23CompanyName+-- , "invite_id" A..= xx23InviteId+-- , "description" A..= xx23Description+-- , "allow_open_invite" A..= xx23AllowOpenInvite+-- ]++-- --++-- data XX24 = XX24+-- { xx24NewPassword :: Text+-- , xx24Code :: Text+-- -- ^ The recovery code+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX24 where+-- parseJSON = A.withObject "xx24" $ \v -> do+-- xx24NewPassword <- v A..: "new_password"+-- xx24Code <- v A..: "code"+-- return XX24 { .. }++-- instance A.ToJSON XX24 where+-- toJSON XX24 { .. } = A.object+-- [ "new_password" A..= xx24NewPassword+-- , "code" A..= xx24Code+-- ]++-- --++-- data XX25 = XX25+-- { xx25ChannelId :: Text+-- , xx25DisplayName :: Text+-- -- ^ The display name for this incoming webhook+-- , xx25Description :: Text+-- -- ^ The description for this incoming webhook+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX25 where+-- parseJSON = A.withObject "xx25" $ \v -> do+-- xx25ChannelId <- v A..: "channel_id"+-- xx25DisplayName <- v A..: "display_name"+-- xx25Description <- v A..: "description"+-- return XX25 { .. }++-- instance A.ToJSON XX25 where+-- toJSON XX25 { .. } = A.object+-- [ "channel_id" A..= xx25ChannelId+-- , "display_name" A..= xx25DisplayName+-- , "description" A..= xx25Description+-- ]++-- --++-- data XX26 = XX26+-- { xx26Message :: Text+-- , xx26Level :: Text+-- -- ^ The error level, e.g. ERROR or INFO+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX26 where+-- parseJSON = A.withObject "xx26" $ \v -> do+-- xx26Message <- v A..: "message"+-- xx26Level <- v A..: "level"+-- return XX26 { .. }++-- instance A.ToJSON XX26 where+-- toJSON XX26 { .. } = A.object+-- [ "message" A..= xx26Message+-- , "level" A..= xx26Level+-- ]++-- --++-- data XX27 = XX27+-- { xx27IsPinned :: Bool+-- , xx27Message :: Text+-- -- ^ The message text of the post+-- , xx27HasReactions :: UnknownType+-- -- ^ Set to `true` if the post has reactions to it+-- , xx27FileIds :: (Seq UnknownType)+-- -- ^ The list of files attached to this post+-- , xx27Props :: Text+-- -- ^ A general JSON property bag to attach to the post+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX27 where+-- parseJSON = A.withObject "xx27" $ \v -> do+-- xx27IsPinned <- v A..: "is_pinned"+-- xx27Message <- v A..: "message"+-- xx27HasReactions <- v A..: "has_reactions"+-- xx27FileIds <- v A..: "file_ids"+-- xx27Props <- v A..: "props"+-- return XX27 { .. }++-- instance A.ToJSON XX27 where+-- toJSON XX27 { .. } = A.object+-- [ "is_pinned" A..= xx27IsPinned+-- , "message" A..= xx27Message+-- , "has_reactions" A..= xx27HasReactions+-- , "file_ids" A..= xx27FileIds+-- , "props" A..= xx27Props+-- ]++-- --++-- data XX28 = XX28+-- { xx28Header :: Text+-- , xx28DisplayName :: Text+-- -- ^ The non-unique UI name for the channel+-- , xx28Name :: Text+-- -- ^ The unique handle for the channel, will be present in the channel URL+-- , xx28Type :: Text+-- -- ^ 'O' for a public channel, 'P' for a private channel+-- , xx28Id :: Text+-- -- ^ The channel's id, not updatable+-- , xx28Purpose :: Text+-- -- ^ A short description of the purpose of the channel+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX28 where+-- parseJSON = A.withObject "xx28" $ \v -> do+-- xx28Header <- v A..: "header"+-- xx28DisplayName <- v A..: "display_name"+-- xx28Name <- v A..: "name"+-- xx28Type <- v A..: "type"+-- xx28Id <- v A..: "id"+-- xx28Purpose <- v A..: "purpose"+-- return XX28 { .. }++-- instance A.ToJSON XX28 where+-- toJSON XX28 { .. } = A.object+-- [ "header" A..= xx28Header+-- , "display_name" A..= xx28DisplayName+-- , "name" A..= xx28Name+-- , "type" A..= xx28Type+-- , "id" A..= xx28Id+-- , "purpose" A..= xx28Purpose+-- ]++-- --++-- data XX29 = XX29+-- { xx29CurrentPassword :: Text+-- , xx29NewPassword :: Text+-- -- ^ The new password for the user+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX29 where+-- parseJSON = A.withObject "xx29" $ \v -> do+-- xx29CurrentPassword <- v A..: "current_password"+-- xx29NewPassword <- v A..: "new_password"+-- return XX29 { .. }++-- instance A.ToJSON XX29 where+-- toJSON XX29 { .. } = A.object+-- [ "current_password" A..= xx29CurrentPassword+-- , "new_password" A..= xx29NewPassword+-- ]++-- --++-- data XX3 = XX3+-- { xx3Url :: Text+-- , xx3Width :: UnknownType+-- , xx3SecureUrl :: Text+-- , xx3Type :: Text+-- , xx3Height :: UnknownType+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX3 where+-- parseJSON = A.withObject "xx3" $ \v -> do+-- xx3Url <- v A..: "url"+-- xx3Width <- v A..: "width"+-- xx3SecureUrl <- v A..: "secure_url"+-- xx3Type <- v A..: "type"+-- xx3Height <- v A..: "height"+-- return XX3 { .. }++-- instance A.ToJSON XX3 where+-- toJSON XX3 { .. } = A.object+-- [ "url" A..= xx3Url+-- , "width" A..= xx3Width+-- , "secure_url" A..= xx3SecureUrl+-- , "type" A..= xx3Type+-- , "height" A..= xx3Height+-- ]++-- --++-- data XX30 = XX30+-- { xx30Username :: Text+-- , xx30FirstName :: Text+-- , xx30LastName :: Text+-- , xx30NotifyProps :: UnknownType+-- , xx30Locale :: Text+-- , xx30Id :: Text+-- , xx30Props :: UnknownType+-- , xx30Position :: Text+-- , xx30Nickname :: Text+-- , xx30Email :: Text+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX30 where+-- parseJSON = A.withObject "xx30" $ \v -> do+-- xx30Username <- v A..: "username"+-- xx30FirstName <- v A..: "first_name"+-- xx30LastName <- v A..: "last_name"+-- xx30NotifyProps <- v A..: "notify_props"+-- xx30Locale <- v A..: "locale"+-- xx30Id <- v A..: "id"+-- xx30Props <- v A..: "props"+-- xx30Position <- v A..: "position"+-- xx30Nickname <- v A..: "nickname"+-- xx30Email <- v A..: "email"+-- return XX30 { .. }++-- instance A.ToJSON XX30 where+-- toJSON XX30 { .. } = A.object+-- [ "username" A..= xx30Username+-- , "first_name" A..= xx30FirstName+-- , "last_name" A..= xx30LastName+-- , "notify_props" A..= xx30NotifyProps+-- , "locale" A..= xx30Locale+-- , "id" A..= xx30Id+-- , "props" A..= xx30Props+-- , "position" A..= xx30Position+-- , "nickname" A..= xx30Nickname+-- , "email" A..= xx30Email+-- ]++-- --++-- data XX31 = XX31+-- { xx31Username :: Text+-- , xx31FirstName :: Text+-- , xx31LastName :: Text+-- , xx31Locale :: Text+-- , xx31Props :: UnknownType+-- , xx31Password :: Text+-- , xx31Nickname :: Text+-- , xx31Email :: Text+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX31 where+-- parseJSON = A.withObject "xx31" $ \v -> do+-- xx31Username <- v A..: "username"+-- xx31FirstName <- v A..: "first_name"+-- xx31LastName <- v A..: "last_name"+-- xx31Locale <- v A..: "locale"+-- xx31Props <- v A..: "props"+-- xx31Password <- v A..: "password"+-- xx31Nickname <- v A..: "nickname"+-- xx31Email <- v A..: "email"+-- return XX31 { .. }++-- instance A.ToJSON XX31 where+-- toJSON XX31 { .. } = A.object+-- [ "username" A..= xx31Username+-- , "first_name" A..= xx31FirstName+-- , "last_name" A..= xx31LastName+-- , "locale" A..= xx31Locale+-- , "props" A..= xx31Props+-- , "password" A..= xx31Password+-- , "nickname" A..= xx31Nickname+-- , "email" A..= xx31Email+-- ]++-- --++-- data XX32 = XX32+-- { xx32Url :: Text+-- , xx32TeamId :: Text+-- -- ^ Team ID to where the command should be created+-- , xx32Trigger :: Text+-- -- ^ Activation word to trigger the command+-- , xx32Method :: Text+-- -- ^ `'P'` for post request, `'G'` for get request+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX32 where+-- parseJSON = A.withObject "xx32" $ \v -> do+-- xx32Url <- v A..: "url"+-- xx32TeamId <- v A..: "team_id"+-- xx32Trigger <- v A..: "trigger"+-- xx32Method <- v A..: "method"+-- return XX32 { .. }++-- instance A.ToJSON XX32 where+-- toJSON XX32 { .. } = A.object+-- [ "url" A..= xx32Url+-- , "team_id" A..= xx32TeamId+-- , "trigger" A..= xx32Trigger+-- , "method" A..= xx32Method+-- ]++-- --++-- data XX33 = XX33+-- { xx33TriggerWhen :: Integer+-- , xx33DisplayName :: Text+-- -- ^ The display name for this outgoing webhook+-- , xx33Description :: Text+-- -- ^ The description for this outgoing webhook+-- , xx33ChannelId :: Text+-- -- ^ The ID of a public channel that the webhook watchs+-- , xx33TeamId :: Text+-- -- ^ The ID of the team that the webhook watchs+-- , xx33ContentType :: Text+-- -- ^ The format to POST the data in, either `application/json` or `application/x-www-form-urlencoded`+-- , xx33TriggerWords :: (Seq Text)+-- -- ^ List of words for the webhook to trigger on+-- , xx33CallbackUrls :: (Seq Text)+-- -- ^ The URLs to POST the payloads to when the webhook is triggered+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX33 where+-- parseJSON = A.withObject "xx33" $ \v -> do+-- xx33TriggerWhen <- v A..: "trigger_when"+-- xx33DisplayName <- v A..: "display_name"+-- xx33Description <- v A..: "description"+-- xx33ChannelId <- v A..: "channel_id"+-- xx33TeamId <- v A..: "team_id"+-- xx33ContentType <- v A..: "content_type"+-- xx33TriggerWords <- v A..: "trigger_words"+-- xx33CallbackUrls <- v A..: "callback_urls"+-- return XX33 { .. }++-- instance A.ToJSON XX33 where+-- toJSON XX33 { .. } = A.object+-- [ "trigger_when" A..= xx33TriggerWhen+-- , "display_name" A..= xx33DisplayName+-- , "description" A..= xx33Description+-- , "channel_id" A..= xx33ChannelId+-- , "team_id" A..= xx33TeamId+-- , "content_type" A..= xx33ContentType+-- , "trigger_words" A..= xx33TriggerWords+-- , "callback_urls" A..= xx33CallbackUrls+-- ]++-- --++-- data XX34 = XX34+-- { xx34DisplayName :: Text+-- , xx34Description :: Text+-- , xx34Name :: Text+-- , xx34Id :: Text+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX34 where+-- parseJSON = A.withObject "xx34" $ \v -> do+-- xx34DisplayName <- v A..: "display_name"+-- xx34Description <- v A..: "description"+-- xx34Name <- v A..: "name"+-- xx34Id <- v A..: "id"+-- return XX34 { .. }++-- instance A.ToJSON XX34 where+-- toJSON XX34 { .. } = A.object+-- [ "display_name" A..= xx34DisplayName+-- , "description" A..= xx34Description+-- , "name" A..= xx34Name+-- , "id" A..= xx34Id+-- ]++-- --++-- data XX35 = XX35+-- { xx35HookId :: Text+-- , xx35ChannelId :: Text+-- -- ^ The ID of a public channel or private group that receives the webhook payloads.+-- , xx35DisplayName :: Text+-- -- ^ The display name for this incoming webhook+-- , xx35Description :: Text+-- -- ^ The description for this incoming webhook+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX35 where+-- parseJSON = A.withObject "xx35" $ \v -> do+-- xx35HookId <- v A..: "hook_id"+-- xx35ChannelId <- v A..: "channel_id"+-- xx35DisplayName <- v A..: "display_name"+-- xx35Description <- v A..: "description"+-- return XX35 { .. }++-- instance A.ToJSON XX35 where+-- toJSON XX35 { .. } = A.object+-- [ "hook_id" A..= xx35HookId+-- , "channel_id" A..= xx35ChannelId+-- , "display_name" A..= xx35DisplayName+-- , "description" A..= xx35Description+-- ]++-- --++-- data XX36 = XX36+-- { xx36DisplayName :: Text+-- , xx36AllowedDomains :: Text+-- , xx36CompanyName :: Text+-- , xx36AllowOpenInvite :: Text+-- , xx36InviteId :: Text+-- , xx36Description :: Text+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX36 where+-- parseJSON = A.withObject "xx36" $ \v -> do+-- xx36DisplayName <- v A..: "display_name"+-- xx36AllowedDomains <- v A..: "allowed_domains"+-- xx36CompanyName <- v A..: "company_name"+-- xx36AllowOpenInvite <- v A..: "allow_open_invite"+-- xx36InviteId <- v A..: "invite_id"+-- xx36Description <- v A..: "description"+-- return XX36 { .. }++-- instance A.ToJSON XX36 where+-- toJSON XX36 { .. } = A.object+-- [ "display_name" A..= xx36DisplayName+-- , "allowed_domains" A..= xx36AllowedDomains+-- , "company_name" A..= xx36CompanyName+-- , "allow_open_invite" A..= xx36AllowOpenInvite+-- , "invite_id" A..= xx36InviteId+-- , "description" A..= xx36Description+-- ]++-- --++-- data XX37 = XX37+-- { xx37Secret :: Text+-- , xx37QrCode :: Text+-- -- ^ A base64 encoded QR code image+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX37 where+-- parseJSON = A.withObject "xx37" $ \v -> do+-- xx37Secret <- v A..: "secret"+-- xx37QrCode <- v A..: "qr_code"+-- return XX37 { .. }++-- instance A.ToJSON XX37 where+-- toJSON XX37 { .. } = A.object+-- [ "secret" A..= xx37Secret+-- , "qr_code" A..= xx37QrCode+-- ]++-- --++-- data XX38 = XX38+-- { xx38Username :: Text+-- , xx38FirstName :: Text+-- , xx38LastName :: Text+-- , xx38NotifyProps :: UnknownType+-- , xx38Locale :: Text+-- , xx38Props :: UnknownType+-- , xx38Position :: Text+-- , xx38Nickname :: Text+-- , xx38Email :: Text+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX38 where+-- parseJSON = A.withObject "xx38" $ \v -> do+-- xx38Username <- v A..: "username"+-- xx38FirstName <- v A..: "first_name"+-- xx38LastName <- v A..: "last_name"+-- xx38NotifyProps <- v A..: "notify_props"+-- xx38Locale <- v A..: "locale"+-- xx38Props <- v A..: "props"+-- xx38Position <- v A..: "position"+-- xx38Nickname <- v A..: "nickname"+-- xx38Email <- v A..: "email"+-- return XX38 { .. }++-- instance A.ToJSON XX38 where+-- toJSON XX38 { .. } = A.object+-- [ "username" A..= xx38Username+-- , "first_name" A..= xx38FirstName+-- , "last_name" A..= xx38LastName+-- , "notify_props" A..= xx38NotifyProps+-- , "locale" A..= xx38Locale+-- , "props" A..= xx38Props+-- , "position" A..= xx38Position+-- , "nickname" A..= xx38Nickname+-- , "email" A..= xx38Email+-- ]++-- --++-- data XX4 = XX4+-- { xx4Username :: Text+-- , xx4Gender :: Text+-- , xx4FirstName :: Text+-- , xx4LastName :: Text+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX4 where+-- parseJSON = A.withObject "xx4" $ \v -> do+-- xx4Username <- v A..: "username"+-- xx4Gender <- v A..: "gender"+-- xx4FirstName <- v A..: "first_name"+-- xx4LastName <- v A..: "last_name"+-- return XX4 { .. }++-- instance A.ToJSON XX4 where+-- toJSON XX4 { .. } = A.object+-- [ "username" A..= xx4Username+-- , "gender" A..= xx4Gender+-- , "first_name" A..= xx4FirstName+-- , "last_name" A..= xx4LastName+-- ]++-- --++-- data XX5 = XX5+-- { xx5Url :: Text+-- , xx5SecureUrl :: Text+-- , xx5Type :: Text+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX5 where+-- parseJSON = A.withObject "xx5" $ \v -> do+-- xx5Url <- v A..: "url"+-- xx5SecureUrl <- v A..: "secure_url"+-- xx5Type <- v A..: "type"+-- return XX5 { .. }++-- instance A.ToJSON XX5 where+-- toJSON XX5 { .. } = A.object+-- [ "url" A..= xx5Url+-- , "secure_url" A..= xx5SecureUrl+-- , "type" A..= xx5Type+-- ]++-- --++-- --++-- data XX8 = XX8+-- { xx8Token :: Text+-- , xx8TurnUsername :: Text+-- -- ^ The username to use with the TURN server+-- , xx8TurnUri :: Text+-- -- ^ The URI to the TURN server+-- , xx8StunUri :: Text+-- -- ^ The URI to the STUN server+-- , xx8GatewayUrl :: Text+-- -- ^ The URL to the gateway server+-- , xx8TurnPassword :: Text+-- -- ^ The password to use with the TURN server+-- } deriving (Read, Show, Eq)++-- instance A.FromJSON XX8 where+-- parseJSON = A.withObject "xx8" $ \v -> do+-- xx8Token <- v A..: "token"+-- xx8TurnUsername <- v A..: "turn_username"+-- xx8TurnUri <- v A..: "turn_uri"+-- xx8StunUri <- v A..: "stun_uri"+-- xx8GatewayUrl <- v A..: "gateway_url"+-- xx8TurnPassword <- v A..: "turn_password"+-- return XX8 { .. }++-- instance A.ToJSON XX8 where+-- toJSON XX8 { .. } = A.object+-- [ "token" A..= xx8Token+-- , "turn_username" A..= xx8TurnUsername+-- , "turn_uri" A..= xx8TurnUri+-- , "stun_uri" A..= xx8StunUri+-- , "gateway_url" A..= xx8GatewayUrl+-- , "turn_password" A..= xx8TurnPassword+-- ]+++-- * Helpers++-- | Add a post to a user's flagged post list. This is a convenience+-- wrapper for the 'mmSaveUsersPreferences' function.+--+-- /Permissions/: Must be logged in as the user being updated or have the+-- @edit_other_users@ permission.+mmFlagPost :: UserId -> PostId -> Session -> IO ()+mmFlagPost uId pId =+ let body = FlaggedPost+ { flaggedPostUserId = uId+ , flaggedPostId = pId+ , flaggedPostStatus = True+ }+ in inPut (printf "/users/%s/preferences" uId) (jsonBody [body]) noResponse++-- | Remove a post from a user's flagged post list. This is a convenience+-- wrapper for the 'mmSaveUsersPreferences' function.+--+-- /Permissions/: Must be logged in as the user being updated or have the+-- @edit_other_users@ permission.+mmUnflagPost :: UserId -> PostId -> Session -> IO ()+mmUnflagPost uId pId =+ let body = FlaggedPost+ { flaggedPostUserId = uId+ , flaggedPostId = pId+ , flaggedPostStatus = False+ }+ in inPut (printf "/users/%s/preferences" uId) (jsonBody [body]) noResponse
src/Network/Mattermost/Exceptions.hs view
@@ -1,4 +1,6 @@ {-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE OverloadedStrings #-} module Network.Mattermost.Exceptions ( -- Exception Types LoginFailureException(..)@@ -7,10 +9,12 @@ , JSONDecodeException(..) , HeaderNotFoundException(..) , HTTPResponseException(..)+, MattermostError(..) , ConnectionException(..) , MattermostServerError(..) ) where +import qualified Data.Aeson as A import qualified Data.Text as T import Data.Typeable ( Typeable ) import Control.Exception ( Exception(..) )@@ -56,6 +60,25 @@ instance Exception HeaderNotFoundException --++data MattermostError = MattermostError+ { mattermostErrorId :: T.Text+ , mattermostErrorMessage :: T.Text+ , mattermostErrorRequestId :: T.Text+ , mattermostErrorStatusCode :: Int+ , mattermostErrorIsOAuth :: Bool+ } deriving (Show, Typeable)++instance Exception MattermostError++instance A.FromJSON MattermostError where+ parseJSON = A.withObject "MattermostError" $ \o -> do+ mattermostErrorId <- o A..: "id"+ mattermostErrorMessage <- o A..: "message"+ mattermostErrorRequestId <- o A..: "request_id"+ mattermostErrorStatusCode <- o A..: "status_code"+ mattermostErrorIsOAuth <- o A..:? "is_oauth" A..!= False+ return MattermostError { .. } data MattermostServerError = MattermostServerError T.Text deriving (Show, Typeable)
src/Network/Mattermost/Types.hs view
@@ -5,10 +5,14 @@ {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE MultiParamTypeClasses #-} -module Network.Mattermost.Types where+module Network.Mattermost.Types+ ( module Network.Mattermost.Types+ , module Network.Mattermost.Types.Base+ )+ where import Control.Applicative-import Text.Printf ( printf )+import Text.Printf ( PrintfArg(..), printf ) import Data.Hashable ( Hashable ) import qualified Data.Aeson as A import Data.Aeson ( (.:), (.=), (.:?), (.!=) )@@ -26,7 +30,7 @@ import qualified Data.Sequence as S import Data.Text (Text) import qualified Data.Text as T-import Data.Time.Clock ( UTCTime, getCurrentTime )+import Data.Time.Clock ( getCurrentTime ) import Data.Time.Clock.POSIX ( posixSecondsToUTCTime , utcTimeToPOSIXSeconds ) import Network.Connection (ConnectionContext, initConnectionContext)@@ -189,12 +193,15 @@ toId = unTI fromId = TI +instance PrintfArg TeamId where+ formatArg = formatArg . idString+ data Team = Team { teamId :: TeamId- , teamCreateAt :: UTCTime- , teamUpdateAt :: UTCTime- , teamDeleteAt :: UTCTime+ , teamCreateAt :: ServerTime+ , teamUpdateAt :: ServerTime+ , teamDeleteAt :: ServerTime , teamDisplayName :: Text , teamName :: Text , teamEmail :: Text@@ -212,9 +219,9 @@ instance A.FromJSON Team where parseJSON = A.withObject "Team" $ \v -> do teamId <- v .: "id"- teamCreateAt <- millisecondsToUTCTime <$> v .: "create_at"- teamUpdateAt <- millisecondsToUTCTime <$> v .: "update_at"- teamDeleteAt <- millisecondsToUTCTime <$> v .: "delete_at"+ teamCreateAt <- timeFromServer <$> v .: "create_at"+ teamUpdateAt <- timeFromServer <$> v .: "update_at"+ teamDeleteAt <- timeFromServer <$> v .: "delete_at" teamDisplayName <- v .: "display_name" teamName <- v .: "name" teamEmail <- v .: "email"@@ -238,6 +245,12 @@ teamMemberRoles <- v .: "roles" return TeamMember { .. } +instance A.ToJSON TeamMember where+ toJSON TeamMember { .. } = A.object+ [ "user_id" .= teamMemberUserId+ , "team_id" .= teamMemberTeamId+ , "roles" .= teamMemberRoles+ ] -- data WithDefault a@@ -245,6 +258,10 @@ | Default deriving (Read, Show, Eq, Ord) +instance A.ToJSON t => A.ToJSON (WithDefault t) where+ toJSON Default = A.String "default"+ toJSON (IsValue x) = A.toJSON x+ instance A.FromJSON t => A.FromJSON (WithDefault t) where parseJSON (A.String "default") = return Default parseJSON t = IsValue <$> A.parseJSON t@@ -259,6 +276,11 @@ | NotifyOptionNone deriving (Read, Show, Eq, Ord) +instance A.ToJSON NotifyOption where+ toJSON NotifyOptionAll = A.String "all"+ toJSON NotifyOptionMention = A.String "mention"+ toJSON NotifyOptionNone = A.String "none"+ instance A.FromJSON NotifyOption where parseJSON (A.String "all") = return NotifyOptionAll parseJSON (A.String "mention") = return NotifyOptionMention@@ -310,6 +332,10 @@ "false" -> return (BoolString False) _ -> fail "Expected \"true\" or \"false\"" +instance A.ToJSON BoolString where+ toJSON (BoolString True) = A.String "true"+ toJSON (BoolString False) = A.String "false"+ instance A.FromJSON UserNotifyProps where parseJSON = A.withObject "UserNotifyProps" $ \v -> do userNotifyPropsMentionKeys <- T.split (==',') <$>@@ -322,6 +348,17 @@ userNotifyPropsFirstName <- fromBoolString <$> (v .:? "first_name" .!= BoolString False) return UserNotifyProps { .. } +instance A.ToJSON UserNotifyProps where+ toJSON UserNotifyProps { .. } = A.object+ [ "mention_keys" .= T.intercalate "," userNotifyPropsMentionKeys+ , "push" .= userNotifyPropsPush+ , "desktop" .= userNotifyPropsDesktop+ , "email" .= BoolString userNotifyPropsEmail+ , "desktop_sound" .= BoolString userNotifyPropsDesktopSound+ , "channel" .= BoolString userNotifyPropsChannel+ , "first_name" .= BoolString userNotifyPropsFirstName+ ]+ instance A.FromJSON ChannelNotifyProps where parseJSON = A.withObject "ChannelNotifyProps" $ \v -> do channelNotifyPropsEmail <- fmap fromBoolString <$>@@ -331,6 +368,14 @@ channelNotifyPropsMarkUnread <- v .:? "mark_unread" .!= IsValue NotifyOptionAll return ChannelNotifyProps { .. } +instance A.ToJSON ChannelNotifyProps where+ toJSON ChannelNotifyProps { .. } = A.object+ [ "email" .= fmap BoolString channelNotifyPropsEmail+ , "push" .= channelNotifyPropsPush+ , "desktop" .= channelNotifyPropsDesktop+ , "mark_unread" .= channelNotifyPropsMarkUnread+ ]+ -- newtype ChannelId = CI { unCI :: Id }@@ -340,21 +385,24 @@ toId = unCI fromId = CI +instance PrintfArg ChannelId where+ formatArg = formatArg . idString+ data Channel = Channel { channelId :: ChannelId- , channelCreateAt :: UTCTime- , channelUpdateAt :: UTCTime- , channelDeleteAt :: UTCTime+ , channelCreateAt :: ServerTime+ , channelUpdateAt :: ServerTime+ , channelDeleteAt :: ServerTime , channelTeamId :: Maybe TeamId , channelType :: Type , channelDisplayName :: Text , channelName :: Text , channelHeader :: Text , channelPurpose :: Text- , channelLastPostAt :: UTCTime+ , channelLastPostAt :: ServerTime , channelTotalMsgCount :: Int- , channelExtraUpdateAt :: UTCTime+ , channelExtraUpdateAt :: ServerTime , channelCreatorId :: Maybe UserId } deriving (Read, Show, Eq, Ord) @@ -364,18 +412,18 @@ instance A.FromJSON Channel where parseJSON = A.withObject "Channel" $ \v -> do channelId <- v .: "id"- channelCreateAt <- millisecondsToUTCTime <$> v .: "create_at"- channelUpdateAt <- millisecondsToUTCTime <$> v .: "update_at"- channelDeleteAt <- millisecondsToUTCTime <$> v .: "delete_at"+ channelCreateAt <- timeFromServer <$> v .: "create_at"+ channelUpdateAt <- timeFromServer <$> v .: "update_at"+ channelDeleteAt <- timeFromServer <$> v .: "delete_at" channelTeamId <- maybeFail (v .: "team_id") channelType <- v .: "type" channelDisplayName <- v .: "display_name" channelName <- v .: "name" channelHeader <- v .: "header" channelPurpose <- v .: "purpose"- channelLastPostAt <- millisecondsToUTCTime <$> v .: "last_post_at"+ channelLastPostAt <- timeFromServer <$> v .: "last_post_at" channelTotalMsgCount <- v .: "total_msg_count"- channelExtraUpdateAt <- millisecondsToUTCTime <$> v .: "extra_update_at"+ channelExtraUpdateAt <- timeFromServer <$> v .: "extra_update_at" channelCreatorId <- maybeFail (v .: "creator_id") return Channel { .. } @@ -398,11 +446,11 @@ { channelDataChannelId :: ChannelId , channelDataUserId :: UserId , channelDataRoles :: Text- , channelDataLastViewedAt :: UTCTime+ , channelDataLastViewedAt :: ServerTime , channelDataMsgCount :: Int , channelDataMentionCount :: Int , channelDataNotifyProps :: ChannelNotifyProps- , channelDataLastUpdateAt :: UTCTime+ , channelDataLastUpdateAt :: ServerTime } deriving (Read, Show, Eq) instance A.FromJSON ChannelData where@@ -410,11 +458,11 @@ channelDataChannelId <- o .: "channel_id" channelDataUserId <- o .: "user_id" channelDataRoles <- o .: "roles"- channelDataLastViewedAt <- millisecondsToUTCTime <$> o .: "last_viewed_at"+ channelDataLastViewedAt <- timeFromServer <$> o .: "last_viewed_at" channelDataMsgCount <- o .: "msg_count" channelDataMentionCount <- o .: "mention_count" channelDataNotifyProps <- o .: "notify_props"- channelDataLastUpdateAt <- millisecondsToUTCTime <$> o .: "last_update_at"+ channelDataLastUpdateAt <- timeFromServer <$> o .: "last_update_at" return ChannelData { .. } data ChannelWithData = ChannelWithData Channel ChannelData@@ -434,6 +482,7 @@ , minChannelPurpose :: Maybe Text , minChannelHeader :: Maybe Text , minChannelType :: Type+ , minChannelTeamId :: TeamId } deriving (Read, Eq, Show) instance A.ToJSON MinChannel where@@ -441,6 +490,7 @@ [ "name" .= minChannelName , "display_name" .= minChannelDisplayName , "type" .= minChannelType+ , "team_id" .= minChannelTeamId ] ++ [ "purpose" .= p | Just p <- [minChannelPurpose] ] ++ [ "header" .= h | Just h <- [minChannelHeader] ]@@ -453,6 +503,21 @@ toId = unUI fromId = UI +instance PrintfArg UserId where+ formatArg = formatArg . idString++data UserParam+ = UserById UserId+ | UserMe+ deriving (Read, Show, Eq, Ord)++instance PrintfArg UserParam where+ formatArg = formatArg . userParamString++userParamString :: UserParam -> Text+userParamString (UserById uid) = idString uid+userParamString UserMe = "me"+ -- -- Note: there's lots of other stuff in an initial_load response but@@ -477,9 +542,9 @@ data User = User { userId :: UserId- , userCreateAt :: UTCTime- , userUpdateAt :: UTCTime- , userDeleteAt :: UTCTime+ , userCreateAt :: ServerTime+ , userUpdateAt :: ServerTime+ , userDeleteAt :: ServerTime , userUsername :: Text , userAuthData :: Text , userAuthService :: Text@@ -490,17 +555,17 @@ , userLastName :: Text , userRoles :: Text , userNotifyProps :: UserNotifyProps- , userLastPasswordUpdate :: Maybe UTCTime- , userLastPictureUpdate :: Maybe UTCTime+ , userLastPasswordUpdate :: Maybe ServerTime+ , userLastPictureUpdate :: Maybe ServerTime , userLocale :: Text } deriving (Read, Show, Eq) instance A.FromJSON User where parseJSON = A.withObject "User" $ \o -> do userId <- o .: "id"- userCreateAt <- millisecondsToUTCTime <$> o .: "create_at"- userUpdateAt <- millisecondsToUTCTime <$> o .: "update_at"- userDeleteAt <- millisecondsToUTCTime <$> o .: "delete_at"+ userCreateAt <- timeFromServer <$> o .: "create_at"+ userUpdateAt <- timeFromServer <$> o .: "update_at"+ userDeleteAt <- timeFromServer <$> o .: "delete_at" userUsername <- o .: "username" userAuthData <- o .: "auth_data" userAuthService <- o .: "auth_service"@@ -511,9 +576,9 @@ userLastName <- o .: "last_name" userRoles <- o .: "roles" userNotifyProps <- o .:? "notify_props" .!= emptyUserNotifyProps- userLastPasswordUpdate <- (millisecondsToUTCTime <$>) <$>+ userLastPasswordUpdate <- (timeFromServer <$>) <$> (o .:? "last_password_update")- userLastPictureUpdate <- (millisecondsToUTCTime <$>) <$> (o .:? "last_picture_update")+ userLastPictureUpdate <- (timeFromServer <$>) <$> (o .:? "last_picture_update") userLocale <- o .: "locale" return User { .. } @@ -613,6 +678,9 @@ toId = unPI fromId = PI +instance PrintfArg PostId where+ formatArg = formatArg . idString+ newtype FileId = FI { unFI :: Id } deriving (Read, Show, Eq, Ord, Hashable, ToJSON, ToJSONKey, FromJSONKey, FromJSON) @@ -620,6 +688,9 @@ toId = unFI fromId = FI +instance PrintfArg FileId where+ formatArg = formatArg . idString+ urlForFile :: FileId -> Text urlForFile fId = "/api/v3/files/" <> idString fId <> "/get"@@ -673,11 +744,12 @@ , postId :: PostId , postType :: PostType , postMessage :: Text- , postDeleteAt :: Maybe UTCTime+ , postDeleteAt :: Maybe ServerTime , postHashtags :: Text- , postUpdateAt :: UTCTime+ , postUpdateAt :: ServerTime+ , postEditAt :: ServerTime , postUserId :: Maybe UserId- , postCreateAt :: UTCTime+ , postCreateAt :: ServerTime , postParentId :: Maybe PostId , postChannelId :: ChannelId , postHasReactions :: Bool@@ -696,11 +768,12 @@ postId <- v .: "id" postType <- v .: "type" postMessage <- v .: "message"- postDeleteAt <- (millisecondsToUTCTime <$>) <$> v .:? "delete_at"+ postDeleteAt <- (timeFromServer <$>) <$> v .:? "delete_at" postHashtags <- v .: "hashtags"- postUpdateAt <- millisecondsToUTCTime <$> v .: "update_at"+ postUpdateAt <- timeFromServer <$> v .: "update_at"+ postEditAt <- timeFromServer <$> v .: "edit_at" postUserId <- maybeFail (v .: "user_id")- postCreateAt <- millisecondsToUTCTime <$> v .: "create_at"+ postCreateAt <- timeFromServer <$> v .: "create_at" postParentId <- maybeFail (v .: "parent_id") postChannelId <- v .: "channel_id" postHasReactions <- (v .: "has_reactions") <|> (return False)@@ -716,11 +789,11 @@ , "id" .= postId , "type" .= postType , "message" .= postMessage- , "delete_at" .= (utcTimeToMilliseconds <$> postDeleteAt)+ , "delete_at" .= (timeToServer <$> postDeleteAt) , "hashtags" .= postHashtags- , "update_at" .= utcTimeToMilliseconds postUpdateAt+ , "update_at" .= timeToServer postUpdateAt , "user_id" .= postUserId- , "create_at" .= utcTimeToMilliseconds postCreateAt+ , "create_at" .= timeToServer postCreateAt , "parent_id" .= postParentId , "channel_id" .= postChannelId , "has_reactions" .= postHasReactions@@ -729,7 +802,7 @@ data PendingPost = PendingPost { pendingPostChannelId :: ChannelId- , pendingPostCreateAt :: Maybe UTCTime+ , pendingPostCreateAt :: Maybe ServerTime , pendingPostFilenames :: Seq FilePath , pendingPostMessage :: Text , pendingPostId :: PendingPostId@@ -741,7 +814,7 @@ instance A.ToJSON PendingPost where toJSON post = A.object [ "channel_id" .= pendingPostChannelId post- , "create_at" .= maybe 0 utcTimeToMilliseconds (pendingPostCreateAt post)+ , "create_at" .= maybe 0 timeToServer (pendingPostCreateAt post) , "filenames" .= pendingPostFilenames post , "message" .= pendingPostMessage post , "pending_post_id" .= pendingPostId post@@ -762,8 +835,10 @@ mkPendingPost :: Text -> UserId -> ChannelId -> IO PendingPost mkPendingPost msg userid channelid = do+ -- locally generating a ServerTime: ok because it's just used for an+ -- initial string ID for this post and not an actual time value. now <- getCurrentTime- let ms = utcTimeToMilliseconds now :: Int+ let ms = timeToServer (ServerTime now) :: Int pid = T.pack $ printf "%s:%d" (idString userid) ms return PendingPost { pendingPostId = PPI (Id pid)@@ -781,9 +856,9 @@ { fileInfoId :: FileId , fileInfoUserId :: UserId , fileInfoPostId :: Maybe PostId- , fileInfoCreateAt :: UTCTime- , fileInfoUpdateAt :: UTCTime- , fileInfoDeleteAt :: UTCTime+ , fileInfoCreateAt :: ServerTime+ , fileInfoUpdateAt :: ServerTime+ , fileInfoDeleteAt :: ServerTime , fileInfoName :: Text , fileInfoExtension :: Text , fileInfoSize :: Int@@ -793,14 +868,17 @@ , fileInfoHasPreview :: Bool } deriving (Read, Show, Eq) +instance ToJSON FileInfo where+ toJSON = error "file info"+ instance FromJSON FileInfo where parseJSON = A.withObject "file_info" $ \o -> do fileInfoId <- o .: "id" fileInfoUserId <- o .: "user_id" fileInfoPostId <- o .: "post_id"- fileInfoCreateAt <- millisecondsToUTCTime <$> o .: "create_at"- fileInfoUpdateAt <- millisecondsToUTCTime <$> o .: "update_at"- fileInfoDeleteAt <- millisecondsToUTCTime <$> o .: "delete_at"+ fileInfoCreateAt <- timeFromServer <$> o .: "create_at"+ fileInfoUpdateAt <- timeFromServer <$> o .: "update_at"+ fileInfoDeleteAt <- timeFromServer <$> o .: "delete_at" fileInfoName <- o .: "name" fileInfoExtension <- o .: "extension" fileInfoSize <- o .: "size"@@ -826,12 +904,16 @@ -- -millisecondsToUTCTime :: Integer -> UTCTime-millisecondsToUTCTime ms = posixSecondsToUTCTime (fromRational (ms%1000))+-- The JSON specification of times exchanged with the server are in+-- integer milliSeconds; convert to and from the local ServerTime+-- internal value. -utcTimeToMilliseconds :: UTCTime -> Int-utcTimeToMilliseconds utc = truncate ((utcTimeToPOSIXSeconds utc)*1000)+timeFromServer :: Integer -> ServerTime+timeFromServer ms = ServerTime $ posixSecondsToUTCTime (fromRational (ms%1000)) +timeToServer :: ServerTime -> Int+timeToServer time = truncate ((utcTimeToPOSIXSeconds $ withServerTime time)*1000)+ -- data MinCommand@@ -840,6 +922,7 @@ , minComCommand :: Text , minComParentId :: Maybe PostId , minComRootId :: Maybe PostId+ , minComTeamId :: TeamId } deriving (Read, Show, Eq) instance A.ToJSON MinCommand where@@ -848,6 +931,7 @@ , "command" .= minComCommand , "parent_id" .= minComParentId , "root_id" .= minComRootId+ , "team_id" .= minComTeamId ] --@@ -856,9 +940,9 @@ = Command { commandId :: CommandId , commandToken :: Token- , commandCreateAt :: UTCTime- , commandUpdateAt :: UTCTime- , commandDeleteAt :: UTCTime+ , commandCreateAt :: ServerTime+ , commandUpdateAt :: ServerTime+ , commandDeleteAt :: ServerTime , commandCreatorId :: UserId , commandTeamId :: TeamId , commandTrigger :: Text@@ -883,6 +967,9 @@ instance HasId Command CommandId where getId = commandId +instance PrintfArg CommandId where+ formatArg = formatArg . idString+ data CommandResponseType = CommandResponseInChannel | CommandResponseEphemeral@@ -954,7 +1041,7 @@ { reactionUserId :: UserId , reactionPostId :: PostId , reactionEmojiName :: Text- , reactionCreateAt :: UTCTime+ , reactionCreateAt :: ServerTime } deriving (Read, Show, Eq) instance A.FromJSON Reaction where@@ -962,7 +1049,7 @@ reactionUserId <- v .: "user_id" reactionPostId <- v .: "post_id" reactionEmojiName <- v .: "emoji_name"- reactionCreateAt <- millisecondsToUTCTime <$> v .: "create_at"+ reactionCreateAt <- timeFromServer <$> v .: "create_at" return Reaction { .. } instance A.ToJSON Reaction where@@ -970,7 +1057,7 @@ [ "user_id" .= reactionUserId , "post_id" .= reactionPostId , "emoji_name" .= reactionEmojiName- , "create_at" .= utcTimeToMilliseconds reactionCreateAt+ , "create_at" .= timeToServer reactionCreateAt ] -- * Preferences@@ -1111,3 +1198,388 @@ , preferenceValue = PreferenceValue (if status then "true" else "false") , preferenceUserId = userId }++--++newtype HookId = HI { unHI :: Id }+ deriving (Read, Show, Eq, Ord, Hashable, ToJSON, ToJSONKey, FromJSONKey, FromJSON)++instance IsId HookId where+ toId = unHI+ fromId = HI++instance PrintfArg HookId where+ formatArg = formatArg . idString++--++newtype InviteId = II { unII :: Id }+ deriving (Read, Show, Eq, Ord, Hashable, ToJSON, ToJSONKey, FromJSONKey, FromJSON)++instance IsId InviteId where+ toId = unII+ fromId = II++instance PrintfArg InviteId where+ formatArg = formatArg . idString++--++newtype TokenId = TkI { unTkI :: Id }+ deriving (Read, Show, Eq, Ord, Hashable, ToJSON, ToJSONKey, FromJSONKey, FromJSON)++instance IsId TokenId where+ toId = unTkI+ fromId = TkI++instance PrintfArg TokenId where+ formatArg = formatArg . idString++--++newtype AppId = AI { unAI :: Id }+ deriving (Read, Show, Eq, Ord, Hashable, ToJSON, ToJSONKey, FromJSONKey, FromJSON)++instance IsId AppId where+ toId = unAI+ fromId = AI++instance PrintfArg AppId where+ formatArg = formatArg . idString++--++newtype JobId = JI { unJI :: Id }+ deriving (Read, Show, Eq, Ord, Hashable, ToJSON, ToJSONKey, FromJSONKey, FromJSON)++instance IsId JobId where+ toId = unJI+ fromId = JI++instance PrintfArg JobId where+ formatArg = formatArg . idString++--++newtype EmojiId = EI { unEI :: Id }+ deriving (Read, Show, Eq, Ord, Hashable, ToJSON, ToJSONKey, FromJSONKey, FromJSON)++instance IsId EmojiId where+ toId = unEI+ fromId = EI++instance PrintfArg EmojiId where+ formatArg = formatArg . idString++--++newtype ReportId = RI { unRI :: Id }+ deriving (Read, Show, Eq, Ord, Hashable, ToJSON, ToJSONKey, FromJSONKey, FromJSON)++instance IsId ReportId where+ toId = unRI+ fromId = RI++instance PrintfArg ReportId where+ formatArg = formatArg . idString++-- FIXMES++instance A.ToJSON User where toJSON = error "to user"+instance A.ToJSON Team where toJSON = error "to team"+instance A.FromJSON Command where parseJSON = error "from command"+instance A.ToJSON Command where toJSON = error "to command"+++-- --++data MinChannelMember = MinChannelMember+ { minChannelMemberUserId :: UserId+ , minChannelMemberChannelId :: ChannelId+ } deriving (Read, Show, Eq)++instance A.FromJSON MinChannelMember where+ parseJSON = A.withObject "channelMember" $ \v -> do+ minChannelMemberUserId <- v A..: "user_id"+ minChannelMemberChannelId <- v A..: "channel_id"+ return MinChannelMember { .. }++instance A.ToJSON MinChannelMember where+ toJSON MinChannelMember { .. } = A.object+ [ "user_id" A..= minChannelMemberUserId+ , "channel_id" A..= minChannelMemberChannelId+ ]++data ChannelMember = ChannelMember+ { channelMemberMsgCount :: Integer+ , channelMemberUserId :: UserId+ , channelMemberRoles :: Text+ , channelMemberMentionCount :: Int+ , channelMemberLastViewedAt :: ServerTime+ , channelMemberChannelId :: ChannelId+ , channelMemberLastUpdateAt :: ServerTime+ , channelMemberNotifyProps :: ChannelNotifyProps+ } deriving (Read, Show, Eq)++instance A.FromJSON ChannelMember where+ parseJSON = A.withObject "channelMember" $ \v -> do+ channelMemberMsgCount <- v A..: "msg_count"+ channelMemberUserId <- v A..: "user_id"+ channelMemberRoles <- v A..: "roles"+ channelMemberMentionCount <- v A..: "mention_count"+ channelMemberLastViewedAt <- timeFromServer <$> v A..: "last_viewed_at"+ channelMemberChannelId <- v A..: "channel_id"+ channelMemberLastUpdateAt <- timeFromServer <$> v A..: "last_update_at"+ channelMemberNotifyProps <- v A..: "notify_props"+ return ChannelMember { .. }++instance A.ToJSON ChannelMember where+ toJSON ChannelMember { .. } = A.object+ [ "msg_count" A..= channelMemberMsgCount+ , "user_id" A..= channelMemberUserId+ , "roles" A..= channelMemberRoles+ , "mention_count" A..= channelMemberMentionCount+ , "last_viewed_at" A..= timeToServer channelMemberLastViewedAt+ , "channel_id" A..= channelMemberChannelId+ , "last_update_at" A..= timeToServer channelMemberLastUpdateAt+ , "notify_props" A..= channelMemberNotifyProps+ ]+++data Status = Status+ { statusUserId :: UserId+ , statusStatus :: T.Text+ , statusManual :: Bool+ , statusLastActivityAt :: ServerTime+ }++instance A.FromJSON Status where+ parseJSON = A.withObject "Status" $ \o -> do+ statusUserId <- o A..: "user_id"+ statusStatus <- o A..: "status"+ statusManual <- o A..: "manual"+ statusLastActivityAt <- timeFromServer <$> o A..: "last_activity_at"+ return Status { .. }++instance A.ToJSON Status where+ toJSON Status { .. } = A.object+ [ "user_id" A..= statusUserId+ , "status" A..= statusStatus+ , "manual" A..= statusManual+ , "last_activity_at" A..= timeToServer statusLastActivityAt+ ]+++data UserSearch = UserSearch+ { userSearchTerm :: Text+ , userSearchAllowInactive :: Bool+ -- ^ When `true`, include deactivated users in the results+ , userSearchWithoutTeam :: Bool+ -- ^ Set this to `true` if you would like to search for users that are not on a team. This option takes precendence over `team_id`, `in_channel_id`, and `not_in_channel_id`.+ , userSearchInChannelId :: Text+ -- ^ If provided, only search users in this channel+ , userSearchNotInTeamId :: Text+ -- ^ If provided, only search users not on this team+ , userSearchNotInChannelId :: Text+ -- ^ If provided, only search users not in this channel. Must specifiy `team_id` when using this option+ , userSearchTeamId :: Text+ -- ^ If provided, only search users on this team+ } deriving (Read, Show, Eq)++instance A.FromJSON UserSearch where+ parseJSON = A.withObject "userSearch" $ \v -> do+ userSearchTerm <- v A..: "term"+ userSearchAllowInactive <- v A..: "allow_inactive"+ userSearchWithoutTeam <- v A..: "without_team"+ userSearchInChannelId <- v A..: "in_channel_id"+ userSearchNotInTeamId <- v A..: "not_in_team_id"+ userSearchNotInChannelId <- v A..: "not_in_channel_id"+ userSearchTeamId <- v A..: "team_id"+ return UserSearch { .. }++instance A.ToJSON UserSearch where+ toJSON UserSearch { .. } = A.object+ [ "term" A..= userSearchTerm+ , "allow_inactive" A..= userSearchAllowInactive+ , "without_team" A..= userSearchWithoutTeam+ , "in_channel_id" A..= userSearchInChannelId+ , "not_in_team_id" A..= userSearchNotInTeamId+ , "not_in_channel_id" A..= userSearchNotInChannelId+ , "team_id" A..= userSearchTeamId+ ]++-- --++data RawPost = RawPost+ { rawPostChannelId :: ChannelId+ , rawPostMessage :: Text+ -- ^ The message contents, can be formatted with Markdown+ , rawPostFileIds :: Seq FileId+ -- ^ A list of file IDs to associate with the post+ , rawPostRootId :: Maybe PostId+ -- ^ The post ID to comment on+ } deriving (Read, Show, Eq)++instance A.FromJSON RawPost where+ parseJSON = A.withObject "rawPost" $ \v -> do+ rawPostChannelId <- v A..: "channel_id"+ rawPostMessage <- v A..: "message"+ rawPostFileIds <- v A..: "file_ids"+ rawPostRootId <- v A..:? "root_id"+ return RawPost { .. }++instance A.ToJSON RawPost where+ toJSON RawPost { .. } = A.object+ ( "channel_id" A..= rawPostChannelId+ : "message" A..= rawPostMessage+ : "file_ids" A..= rawPostFileIds+ : case rawPostRootId of+ Nothing -> []+ Just rId -> [("root_id" A..= rId)]+ )++rawPost :: Text -> ChannelId -> RawPost+rawPost message channelId = RawPost+ { rawPostChannelId = channelId+ , rawPostMessage = message+ , rawPostFileIds = mempty+ , rawPostRootId = Nothing+ }+++data PostUpdate = PostUpdate+ { postUpdateIsPinned :: Maybe Bool+ , postUpdateMessage :: Text+ -- ^ The message text of the post+ , postUpdateHasReactions :: Maybe Bool+ -- ^ Set to `true` if the post has reactions to it+ , postUpdateFileIds :: Maybe (Seq FileId)+ -- ^ The list of files attached to this post+ , postUpdateProps :: Maybe Text+ -- ^ A general JSON property bag to attach to the post+ } deriving (Read, Show, Eq)++instance A.FromJSON PostUpdate where+ parseJSON = A.withObject "postUpdate" $ \v -> do+ postUpdateIsPinned <- v A..:? "is_pinned" A..!= Nothing+ postUpdateMessage <- v A..: "message"+ postUpdateHasReactions <- v A..:? "has_reactions" A..!= Nothing+ postUpdateFileIds <- v A..:? "file_ids" A..!= Nothing+ postUpdateProps <- v A..:? "props" A..!= Nothing+ return PostUpdate { .. }++instance A.ToJSON PostUpdate where+ toJSON PostUpdate { .. } = A.object $+ [ "is_pinned" A..= p | Just p <- [postUpdateIsPinned] ] +++ [ "message" A..= postUpdateMessage ] +++ [ "has_reactions" A..= p | Just p <- [postUpdateHasReactions] ] +++ [ "file_ids" A..= p | Just p <- [postUpdateFileIds] ] +++ [ "props" A..= p | Just p <- [postUpdateProps] ]++postUpdate :: Text -> PostUpdate+postUpdate message = PostUpdate+ { postUpdateIsPinned = Nothing+ , postUpdateMessage = message+ , postUpdateHasReactions = Nothing+ , postUpdateFileIds = Nothing+ , postUpdateProps = Nothing+ }+++data ChannelPatch = ChannelPatch+ { channelPatchHeader :: Maybe Text+ , channelPatchDisplayName :: Maybe Text+ -- ^ The non-unique UI name for the channel+ , channelPatchName :: Maybe Text+ -- ^ The unique handle for the channel, will be present in the channel URL+ , channelPatchPurpose :: Maybe Text+ -- ^ A short description of the purpose of the channel+ } deriving (Read, Show, Eq)++instance A.FromJSON ChannelPatch where+ parseJSON = A.withObject "channelPatch" $ \v -> do+ channelPatchHeader <- v A..:? "header"+ channelPatchDisplayName <- v A..:? "display_name"+ channelPatchName <- v A..:? "name"+ channelPatchPurpose <- v A..:? "purpose"+ return ChannelPatch { .. }++instance A.ToJSON ChannelPatch where+ toJSON ChannelPatch { .. } = A.object $+ [ "header" A..= x | Just x <- [ channelPatchHeader] ] +++ [ "display_name" A..= x | Just x <- [channelPatchDisplayName] ] +++ [ "name" A..= x | Just x <- [channelPatchName] ] +++ [ "purpose" A..= x | Just x <- [channelPatchPurpose] ]++defaultChannelPatch :: ChannelPatch+defaultChannelPatch = ChannelPatch+ { channelPatchHeader = Nothing+ , channelPatchDisplayName = Nothing+ , channelPatchName = Nothing+ , channelPatchPurpose = Nothing+ }+++data InitialTeamData = InitialTeamData+ { initialTeamDataDisplayName :: Text+ , initialTeamDataType :: Text+ -- ^ `'O'` for open, `'I'` for invite only+ , initialTeamDataName :: Text+ -- ^ Unique handler for a team, will be present in the team URL+ } deriving (Read, Show, Eq)++instance A.FromJSON InitialTeamData where+ parseJSON = A.withObject "initialTeamData" $ \v -> do+ initialTeamDataDisplayName <- v A..: "display_name"+ initialTeamDataType <- v A..: "type"+ initialTeamDataName <- v A..: "name"+ return InitialTeamData { .. }++instance A.ToJSON InitialTeamData where+ toJSON InitialTeamData { .. } = A.object+ [ "display_name" A..= initialTeamDataDisplayName+ , "type" A..= initialTeamDataType+ , "name" A..= initialTeamDataName+ ]++data ChannelStats = ChannelStats+ { channelStatsChannelId :: Text+ , channelStatsMemberCount :: Int+ } deriving (Read, Show, Eq)++instance A.FromJSON ChannelStats where+ parseJSON = A.withObject "channelStats" $ \v -> do+ channelStatsChannelId <- v A..: "channel_id"+ channelStatsMemberCount <- v A..: "member_count"+ return ChannelStats { .. }++instance A.ToJSON ChannelStats where+ toJSON ChannelStats { .. } = A.object+ [ "channel_id" A..= channelStatsChannelId+ , "member_count" A..= channelStatsMemberCount+ ]++-- --++data ChannelUnread = ChannelUnread+ { channelUnreadChannelId :: Text+ , channelUnreadTeamId :: Text+ , channelUnreadMsgCount :: Int+ , channelUnreadMentionCount :: Int+ } deriving (Read, Show, Eq)++instance A.FromJSON ChannelUnread where+ parseJSON = A.withObject "channelUnread" $ \v -> do+ channelUnreadChannelId <- v A..: "channel_id"+ channelUnreadTeamId <- v A..: "team_id"+ channelUnreadMsgCount <- v A..: "msg_count"+ channelUnreadMentionCount <- v A..: "mention_count"+ return ChannelUnread { .. }++instance A.ToJSON ChannelUnread where+ toJSON ChannelUnread { .. } = A.object+ [ "channel_id" A..= channelUnreadChannelId+ , "team_id" A..= channelUnreadTeamId+ , "msg_count" A..= channelUnreadMsgCount+ , "mention_count" A..= channelUnreadMentionCount+ ]
src/Network/Mattermost/Types/Base.hs view
@@ -7,6 +7,7 @@ import qualified Data.Aeson as A import Data.Text (Text)+import Data.Time.Clock ( UTCTime ) import Network.HTTP.Base (RequestMethod) type Hostname = Text@@ -33,3 +34,11 @@ | WebSocketPing | WebSocketPong deriving (Eq, Show)+++-- | The time as provided by the Server. This is a wrapper designed+-- to warn against naive comparisons to local times: the server's time+-- and local times are not necessarily synchronized.++newtype ServerTime = ServerTime { withServerTime :: UTCTime }+ deriving (Eq, Ord, Read, Show)
+ src/Network/Mattermost/Types/Config.hs view
@@ -0,0 +1,666 @@+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE OverloadedStrings #-}++module Network.Mattermost.Types.Config where++import qualified Data.Aeson as A+import Data.Text (Text)+import qualified Data.Text as T++data ServerConfig = ServerConfig+ {+ -- { configSqlsettings :: UnknownObject+ -- , configPrivacysettings :: PrivacySettings+ configLogsettings :: LogSettings+ , configCompliancesettings :: ComplianceSettings+ , configEmailsettings :: EmailSettings+ -- , configFilesettings :: FileSettings+ -- , configGitlabsettings :: GitLabSettings+ , configNativeappsettings :: NativeAppSettings+ -- , configLdapsettings :: LdapSettings+ -- , configServicesettings :: ServiceSettings+ -- , configOffice365settings :: Office365Settings+ -- , configGooglesettings :: GoogleSettings+ , configPasswordsettings :: PasswordSettings+ , configTeamsettings :: TeamSettings+ -- , configSamlsettings :: SamlSettings+ -- , configClustersettings :: ClusterSettings+ -- , configRatelimitsettings :: RateLimitSettings+ -- , configLocalizationsettings :: LocalizationSettings+ , configSupportsettings :: SupportSettings+ -- , configAnalyticssettings :: Integer+ , configMetricssettings :: MetricsSettings+ , configWebrtcsettings :: WebrtcSettings+ } deriving (Read, Show, Eq)++instance A.FromJSON ServerConfig where+ parseJSON = A.withObject "config" $ \v -> do+ -- configSqlsettings <- v A..: "SqlSettings"+ -- configPrivacysettings <- v A..: "PrivacySettings"+ configLogsettings <- v A..: "LogSettings"+ configCompliancesettings <- v A..: "ComplianceSettings"+ configEmailsettings <- v A..: "EmailSettings"+ -- configFilesettings <- v A..: "FileSettings"+ -- configGitlabsettings <- v A..: "GitLabSettings"+ configNativeappsettings <- v A..: "NativeAppSettings"+ -- configLdapsettings <- v A..: "LdapSettings"+ -- configServicesettings <- v A..: "ServiceSettings"+ -- configOffice365settings <- v A..: "Office365Settings"+ -- configGooglesettings <- v A..: "GoogleSettings"+ configPasswordsettings <- v A..: "PasswordSettings"+ configTeamsettings <- v A..: "TeamSettings"+ -- configSamlsettings <- v A..: "SamlSettings"+ -- configClustersettings <- v A..: "ClusterSettings"+ -- configRatelimitsettings <- v A..: "RateLimitSettings"+ -- configLocalizationsettings <- v A..: "LocalizationSettings"+ configSupportsettings <- v A..: "SupportSettings"+ -- configAnalyticssettings <- v A..: "AnalyticsSettings"+ configMetricssettings <- v A..: "MetricsSettings"+ configWebrtcsettings <- v A..: "WebrtcSettings"+ return ServerConfig { .. }++instance A.ToJSON ServerConfig where+ toJSON ServerConfig { .. } = A.object+ [ "EmailSettings" A..= configEmailsettings+ , "WebrtcSettings" A..= configWebrtcsettings+ , "PasswordSettings" A..= configPasswordsettings+ , "LogSettings" A..= configLogsettings+ , "NativeAppSettings" A..= configNativeappsettings+ , "MetricsSettings" A..= configMetricssettings+ , "ComplianceSettings" A..= configCompliancesettings+ -- , "SqlSettings" A..= configSqlsettings+ -- , "PrivacySettings" A..= configPrivacysettings+ -- , "EmailSettings" A..= configEmailsettings+ -- , "FileSettings" A..= configFilesettings+ -- , "GitLabSettings" A..= configGitlabsettings+ -- , "LdapSettings" A..= configLdapsettings+ -- , "ServiceSettings" A..= configServicesettings+ -- , "Office365Settings" A..= configOffice365settings+ -- , "GoogleSettings" A..= configGooglesettings+ -- , "TeamSettings" A..= configTeamsettings+ -- , "SamlSettings" A..= configSamlsettings+ -- , "ClusterSettings" A..= configClustersettings+ -- , "RateLimitSettings" A..= configRatelimitsettings+ -- , "LocalizationSettings" A..= configLocalizationsettings+ , "SupportSettings" A..= configSupportsettings+ -- , "AnalyticsSettings" A..= configAnalyticssettings+ , "WebrtcSettings" A..= configWebrtcsettings+ ]++-- --++data EmailSettings = EmailSettings+ { emailSettingsSendemailnotifications :: Bool+ , emailSettingsPasswordresetsalt :: Maybe T.Text+ , emailSettingsEnablesignupwithemail :: Bool+ , emailSettingsSmtpusername ::T.Text+ , emailSettingsEmailbatchinginterval :: Int+ , emailSettingsFeedbackname ::T.Text+ , emailSettingsRequireemailverification :: Bool+ , emailSettingsSmtpserver ::T.Text+ , emailSettingsSmtppassword ::T.Text+ , emailSettingsEnablesigninwithemail :: Bool+ , emailSettingsPushnotificationcontents ::T.Text+ , emailSettingsPushnotificationserver ::T.Text+ , emailSettingsEnableemailbatching :: Bool+ , emailSettingsEmailbatchingbuffersize :: Int+ , emailSettingsConnectionsecurity ::T.Text+ , emailSettingsSmtpport ::T.Text+ , emailSettingsFeedbackemail ::T.Text+ , emailSettingsSendpushnotifications :: Bool+ , emailSettingsFeedbackorganization ::T.Text+ , emailSettingsInvitesalt ::T.Text+ , emailSettingsEnablesigninwithusername :: Bool+ } deriving (Read, Show, Eq)++instance A.FromJSON EmailSettings where+ parseJSON = A.withObject "emailSettings" $ \v -> do+ emailSettingsSendemailnotifications <- v A..: "SendEmailNotifications"+ emailSettingsPasswordresetsalt <- v A..:? "PasswordResetSalt"+ emailSettingsEnablesignupwithemail <- v A..: "EnableSignUpWithEmail"+ emailSettingsSmtpusername <- v A..: "SMTPUsername"+ emailSettingsEmailbatchinginterval <- v A..: "EmailBatchingInterval"+ emailSettingsFeedbackname <- v A..: "FeedbackName"+ emailSettingsRequireemailverification <- v A..: "RequireEmailVerification"+ emailSettingsSmtpserver <- v A..: "SMTPServer"+ emailSettingsSmtppassword <- v A..: "SMTPPassword"+ emailSettingsEnablesigninwithemail <- v A..: "EnableSignInWithEmail"+ emailSettingsPushnotificationcontents <- v A..: "PushNotificationContents"+ emailSettingsPushnotificationserver <- v A..: "PushNotificationServer"+ emailSettingsEnableemailbatching <- v A..: "EnableEmailBatching"+ emailSettingsEmailbatchingbuffersize <- v A..: "EmailBatchingBufferSize"+ emailSettingsConnectionsecurity <- v A..: "ConnectionSecurity"+ emailSettingsSmtpport <- v A..: "SMTPPort"+ emailSettingsFeedbackemail <- v A..: "FeedbackEmail"+ emailSettingsSendpushnotifications <- v A..: "SendPushNotifications"+ emailSettingsFeedbackorganization <- v A..: "FeedbackOrganization"+ emailSettingsInvitesalt <- v A..: "InviteSalt"+ emailSettingsEnablesigninwithusername <- v A..: "EnableSignInWithUsername"+ return EmailSettings { .. }++instance A.ToJSON EmailSettings where+ toJSON EmailSettings { .. } = A.object $+ [ "SendEmailNotifications" A..= emailSettingsSendemailnotifications+ , "EnableSignUpWithEmail" A..= emailSettingsEnablesignupwithemail+ , "SMTPUsername" A..= emailSettingsSmtpusername+ , "EmailBatchingInterval" A..= emailSettingsEmailbatchinginterval+ , "FeedbackName" A..= emailSettingsFeedbackname+ , "RequireEmailVerification" A..= emailSettingsRequireemailverification+ , "SMTPServer" A..= emailSettingsSmtpserver+ , "SMTPPassword" A..= emailSettingsSmtppassword+ , "EnableSignInWithEmail" A..= emailSettingsEnablesigninwithemail+ , "PushNotificationContents" A..= emailSettingsPushnotificationcontents+ , "PushNotificationServer" A..= emailSettingsPushnotificationserver+ , "EnableEmailBatching" A..= emailSettingsEnableemailbatching+ , "EmailBatchingBufferSize" A..= emailSettingsEmailbatchingbuffersize+ , "ConnectionSecurity" A..= emailSettingsConnectionsecurity+ , "SMTPPort" A..= emailSettingsSmtpport+ , "FeedbackEmail" A..= emailSettingsFeedbackemail+ , "SendPushNotifications" A..= emailSettingsSendpushnotifications+ , "FeedbackOrganization" A..= emailSettingsFeedbackorganization+ , "InviteSalt" A..= emailSettingsInvitesalt+ , "EnableSignInWithUsername" A..= emailSettingsEnablesigninwithusername+ ] +++ [ "PasswordResetSalt" A..= x | Just x <- [emailSettingsPasswordresetsalt] ]++data ClientConfig = ClientConfig+ { clientConfigVersion :: T.Text+ , clientConfigBuildNumber :: T.Text+ , clientConfigBuildDate :: T.Text+ , clientConfigBuildHash :: T.Text+ , clientConfigBuildHashEnterprise :: T.Text+ , clientConfigBuildEnterpriseReady :: T.Text++ , clientConfigSiteURL :: T.Text+ , clientConfigSiteName :: T.Text+ , clientConfigEnableTeamCreation :: T.Text+ , clientConfigEnableUserCreation :: T.Text+ , clientConfigEnableOpenServer :: T.Text+ , clientConfigRestrictDirectMessage :: T.Text+ , clientConfigRestrictTeamInvite :: T.Text+ , clientConfigRestrictPublicChannelCreation :: T.Text+ , clientConfigRestrictPrivateChannelCreation :: T.Text+ , clientConfigRestrictPublicChannelManagement :: T.Text+ , clientConfigRestrictPrivateChannelManagement :: T.Text+ , clientConfigRestrictPublicChannelDeletion :: T.Text+ , clientConfigRestrictPrivateChannelDeletion :: T.Text+ , clientConfigRestrictPrivateChannelManageMembers :: T.Text+ , clientConfigTeammateNameDisplay :: T.Text++ , clientConfigEnableOAuthServiceProvider :: T.Text+ , clientConfigGoogleDeveloperKey :: T.Text+ , clientConfigEnableIncomingWebhooks :: T.Text+ , clientConfigEnableOutgoingWebhooks :: T.Text+ , clientConfigEnableCommands :: T.Text+ , clientConfigEnableOnlyAdminIntegrations :: T.Text+ , clientConfigEnablePostUsernameOverride :: T.Text+ , clientConfigEnablePostIconOverride :: T.Text+ , clientConfigEnableLinkPreviews :: T.Text+ , clientConfigEnableTesting :: T.Text+ , clientConfigEnableDeveloper :: T.Text+ , clientConfigEnableDiagnostics :: T.Text+ , clientConfigRestrictPostDelete :: T.Text+ , clientConfigAllowEditPost :: T.Text+ , clientConfigPostEditTimeLimit :: T.Text++ , clientConfigSendEmailNotifications :: T.Text+ , clientConfigSendPushNotifications :: T.Text+ , clientConfigEnableSignUpWithEmail :: T.Text+ , clientConfigEnableSignInWithEmail :: T.Text+ , clientConfigEnableSignInWithUsername :: T.Text+ , clientConfigRequireEmailVerification :: T.Text+ , clientConfigEnableEmailBatching :: T.Text++ , clientConfigEnableSignUpWithGitLab :: T.Text++ , clientConfigShowEmailAddress :: T.Text++ , clientConfigTermsOfServiceLink :: T.Text+ , clientConfigPrivacyPolicyLink :: T.Text+ , clientConfigAboutLink :: T.Text+ , clientConfigHelpLink :: T.Text+ , clientConfigReportAProblemLink :: T.Text+ , clientConfigAdministratorsGuideLink :: Maybe T.Text+ , clientConfigTroubleshootingForumLink :: Maybe T.Text+ , clientConfigCommercialSupportLink :: Maybe T.Text+ , clientConfigSupportEmail :: T.Text++ , clientConfigEnableFileAttachments :: T.Text+ , clientConfigEnablePublicLink :: T.Text++ , clientConfigWebsocketPort :: T.Text+ , clientConfigWebsocketSecurePort :: T.Text++ , clientConfigDefaultClientLocale :: T.Text+ , clientConfigAvailableLocales :: T.Text+ , clientConfigSQLDriverName :: T.Text++ , clientConfigEnableCustomEmoji :: T.Text+ , clientConfigEnableEmojiPicker :: T.Text+ , clientConfigRestrictCustomEmojiCreation :: T.Text+ , clientConfigMaxFileSize :: T.Text++ , clientConfigAppDownloadLink :: T.Text+ , clientConfigAndroidAppDownloadLink :: T.Text+ , clientConfigIosAppDownloadLink :: T.Text++ , clientConfigEnableWebrtc :: T.Text++ , clientConfigMaxNotificationsPerChannel :: T.Text+ , clientConfigTimeBetweenUserTypingUpdatesMilliseconds :: T.Text+ , clientConfigEnableUserTypingMessages :: T.Text+ , clientConfigEnableChannelViewedMessages :: T.Text++ , clientConfigDiagnosticId :: T.Text+ , clientConfigDiagnosticsEnabled :: T.Text+ } deriving (Read, Show, Eq)+++instance A.FromJSON ClientConfig where+ parseJSON = A.withObject "ClientConfig" $ \o -> do+ clientConfigVersion <- o A..: "Version"+ clientConfigBuildNumber <- o A..: "BuildNumber"+ clientConfigBuildDate <- o A..: "BuildDate"+ clientConfigBuildHash <- o A..: "BuildHash"+ clientConfigBuildHashEnterprise <- o A..: "BuildHashEnterprise"+ clientConfigBuildEnterpriseReady <- o A..: "BuildEnterpriseReady"++ clientConfigSiteURL <- o A..: "SiteURL"+ clientConfigSiteName <- o A..: "SiteName"+ clientConfigEnableTeamCreation <- o A..: "EnableTeamCreation"+ clientConfigEnableUserCreation <- o A..: "EnableUserCreation"+ clientConfigEnableOpenServer <- o A..: "EnableOpenServer"+ clientConfigRestrictDirectMessage <- o A..: "RestrictDirectMessage"+ clientConfigRestrictTeamInvite <- o A..: "RestrictTeamInvite"+ clientConfigRestrictPublicChannelCreation <- o A..: "RestrictPublicChannelCreation"+ clientConfigRestrictPrivateChannelCreation <- o A..: "RestrictPrivateChannelCreation"+ clientConfigRestrictPublicChannelManagement <- o A..: "RestrictPublicChannelManagement"+ clientConfigRestrictPrivateChannelManagement <- o A..: "RestrictPrivateChannelManagement"+ clientConfigRestrictPublicChannelDeletion <- o A..: "RestrictPublicChannelDeletion"+ clientConfigRestrictPrivateChannelDeletion <- o A..: "RestrictPrivateChannelDeletion"+ clientConfigRestrictPrivateChannelManageMembers <- o A..: "RestrictPrivateChannelManageMembers"+ clientConfigTeammateNameDisplay <- o A..: "TeammateNameDisplay"++ clientConfigEnableOAuthServiceProvider <- o A..: "EnableOAuthServiceProvider"+ clientConfigGoogleDeveloperKey <- o A..: "GoogleDeveloperKey"+ clientConfigEnableIncomingWebhooks <- o A..: "EnableIncomingWebhooks"+ clientConfigEnableOutgoingWebhooks <- o A..: "EnableOutgoingWebhooks"+ clientConfigEnableCommands <- o A..: "EnableCommands"+ clientConfigEnableOnlyAdminIntegrations <- o A..: "EnableOnlyAdminIntegrations"+ clientConfigEnablePostUsernameOverride <- o A..: "EnablePostUsernameOverride"+ clientConfigEnablePostIconOverride <- o A..: "EnablePostIconOverride"+ clientConfigEnableLinkPreviews <- o A..: "EnableLinkPreviews"+ clientConfigEnableTesting <- o A..: "EnableTesting"+ clientConfigEnableDeveloper <- o A..: "EnableDeveloper"+ clientConfigEnableDiagnostics <- o A..: "EnableDiagnostics"+ clientConfigRestrictPostDelete <- o A..: "RestrictPostDelete"+ clientConfigAllowEditPost <- o A..: "AllowEditPost"+ clientConfigPostEditTimeLimit <- o A..: "PostEditTimeLimit"++ clientConfigSendEmailNotifications <- o A..: "SendEmailNotifications"+ clientConfigSendPushNotifications <- o A..: "SendPushNotifications"+ clientConfigEnableSignUpWithEmail <- o A..: "EnableSignUpWithEmail"+ clientConfigEnableSignInWithEmail <- o A..: "EnableSignInWithEmail"+ clientConfigEnableSignInWithUsername <- o A..: "EnableSignInWithUsername"+ clientConfigRequireEmailVerification <- o A..: "RequireEmailVerification"+ clientConfigEnableEmailBatching <- o A..: "EnableEmailBatching"++ clientConfigEnableSignUpWithGitLab <- o A..: "EnableSignUpWithGitLab"++ clientConfigShowEmailAddress <- o A..: "ShowEmailAddress"++ clientConfigTermsOfServiceLink <- o A..: "TermsOfServiceLink"+ clientConfigPrivacyPolicyLink <- o A..: "PrivacyPolicyLink"+ clientConfigAboutLink <- o A..: "AboutLink"+ clientConfigHelpLink <- o A..: "HelpLink"+ clientConfigReportAProblemLink <- o A..: "ReportAProblemLink"+ clientConfigAdministratorsGuideLink <- o A..:? "AdministratorsGuideLink"+ clientConfigTroubleshootingForumLink <- o A..:? "TroubleshootingForumLink"+ clientConfigCommercialSupportLink <- o A..:? "CommercialSupportLink"+ clientConfigSupportEmail <- o A..: "SupportEmail"++ clientConfigEnableFileAttachments <- o A..: "EnableFileAttachments"+ clientConfigEnablePublicLink <- o A..: "EnablePublicLink"++ clientConfigWebsocketPort <- o A..: "WebsocketPort"+ clientConfigWebsocketSecurePort <- o A..: "WebsocketSecurePort"++ clientConfigDefaultClientLocale <- o A..: "DefaultClientLocale"+ clientConfigAvailableLocales <- o A..: "AvailableLocales"+ clientConfigSQLDriverName <- o A..: "SQLDriverName"++ clientConfigEnableCustomEmoji <- o A..: "EnableCustomEmoji"+ clientConfigEnableEmojiPicker <- o A..: "EnableEmojiPicker"+ clientConfigRestrictCustomEmojiCreation <- o A..: "RestrictCustomEmojiCreation"+ clientConfigMaxFileSize <- o A..: "MaxFileSize"++ clientConfigAppDownloadLink <- o A..: "AppDownloadLink"+ clientConfigAndroidAppDownloadLink <- o A..: "AndroidAppDownloadLink"+ clientConfigIosAppDownloadLink <- o A..: "IosAppDownloadLink"++ clientConfigEnableWebrtc <- o A..: "EnableWebrtc"++ clientConfigMaxNotificationsPerChannel <- o A..: "MaxNotificationsPerChannel"+ clientConfigTimeBetweenUserTypingUpdatesMilliseconds <- o A..: "TimeBetweenUserTypingUpdatesMilliseconds"+ clientConfigEnableUserTypingMessages <- o A..: "EnableUserTypingMessages"+ clientConfigEnableChannelViewedMessages <- o A..: "EnableChannelViewedMessages"++ clientConfigDiagnosticId <- o A..: "DiagnosticId"+ clientConfigDiagnosticsEnabled <- o A..: "DiagnosticsEnabled"+ return ClientConfig { .. }+++data TeamSettings = TeamSettings+ { teamSettingsRestrictpublicchanneldeletion :: Text+ , teamSettingsRestrictcreationtodomains :: Text+ , teamSettingsMaxusersperteam :: Int+ , teamSettingsCustomdescriptiontext :: Text+ , teamSettingsEnableopenserver :: Bool+ , teamSettingsEnableusercreation :: Bool+ , teamSettingsCustombrandtext :: Text+ , teamSettingsRestrictprivatechanneldeletion :: Text+ , teamSettingsMaxchannelsperteam :: Int+ , teamSettingsRestrictteaminvite :: Text+ , teamSettingsEnableteamcreation :: Bool+ , teamSettingsSitename :: Text+ , teamSettingsRestrictpublicchannelmanagement :: Text+ , teamSettingsMaxnotificationsperchannel :: Int+ , teamSettingsRestrictdirectmessage :: Text+ , teamSettingsUserstatusawaytimeout :: Int+ , teamSettingsEnablecustombrand :: Bool+ , teamSettingsRestrictprivatechannelmanagement :: Text+ , teamSettingsRestrictprivatechannelcreation :: Text+ , teamSettingsRestrictpublicchannelcreation :: Text+ } deriving (Read, Show, Eq)++instance A.FromJSON TeamSettings where+ parseJSON = A.withObject "teamSettings" $ \v -> do+ teamSettingsRestrictpublicchanneldeletion <- v A..: "RestrictPublicChannelDeletion"+ teamSettingsRestrictcreationtodomains <- v A..: "RestrictCreationToDomains"+ teamSettingsMaxusersperteam <- v A..: "MaxUsersPerTeam"+ teamSettingsCustomdescriptiontext <- v A..: "CustomDescriptionText"+ teamSettingsEnableopenserver <- v A..: "EnableOpenServer"+ teamSettingsEnableusercreation <- v A..: "EnableUserCreation"+ teamSettingsCustombrandtext <- v A..: "CustomBrandText"+ teamSettingsRestrictprivatechanneldeletion <- v A..: "RestrictPrivateChannelDeletion"+ teamSettingsMaxchannelsperteam <- v A..: "MaxChannelsPerTeam"+ teamSettingsRestrictteaminvite <- v A..: "RestrictTeamInvite"+ teamSettingsEnableteamcreation <- v A..: "EnableTeamCreation"+ teamSettingsSitename <- v A..: "SiteName"+ teamSettingsRestrictpublicchannelmanagement <- v A..: "RestrictPublicChannelManagement"+ teamSettingsMaxnotificationsperchannel <- v A..: "MaxNotificationsPerChannel"+ teamSettingsRestrictdirectmessage <- v A..: "RestrictDirectMessage"+ teamSettingsUserstatusawaytimeout <- v A..: "UserStatusAwayTimeout"+ teamSettingsEnablecustombrand <- v A..: "EnableCustomBrand"+ teamSettingsRestrictprivatechannelmanagement <- v A..: "RestrictPrivateChannelManagement"+ teamSettingsRestrictprivatechannelcreation <- v A..: "RestrictPrivateChannelCreation"+ teamSettingsRestrictpublicchannelcreation <- v A..: "RestrictPublicChannelCreation"+ return TeamSettings { .. }++instance A.ToJSON TeamSettings where+ toJSON TeamSettings { .. } = A.object+ [ "RestrictPublicChannelDeletion" A..= teamSettingsRestrictpublicchanneldeletion+ , "RestrictCreationToDomains" A..= teamSettingsRestrictcreationtodomains+ , "MaxUsersPerTeam" A..= teamSettingsMaxusersperteam+ , "CustomDescriptionText" A..= teamSettingsCustomdescriptiontext+ , "EnableOpenServer" A..= teamSettingsEnableopenserver+ , "EnableUserCreation" A..= teamSettingsEnableusercreation+ , "CustomBrandText" A..= teamSettingsCustombrandtext+ , "RestrictPrivateChannelDeletion" A..= teamSettingsRestrictprivatechanneldeletion+ , "MaxChannelsPerTeam" A..= teamSettingsMaxchannelsperteam+ , "RestrictTeamInvite" A..= teamSettingsRestrictteaminvite+ , "EnableTeamCreation" A..= teamSettingsEnableteamcreation+ , "SiteName" A..= teamSettingsSitename+ , "RestrictPublicChannelManagement" A..= teamSettingsRestrictpublicchannelmanagement+ , "MaxNotificationsPerChannel" A..= teamSettingsMaxnotificationsperchannel+ , "RestrictDirectMessage" A..= teamSettingsRestrictdirectmessage+ , "UserStatusAwayTimeout" A..= teamSettingsUserstatusawaytimeout+ , "EnableCustomBrand" A..= teamSettingsEnablecustombrand+ , "RestrictPrivateChannelManagement" A..= teamSettingsRestrictprivatechannelmanagement+ , "RestrictPrivateChannelCreation" A..= teamSettingsRestrictprivatechannelcreation+ , "RestrictPublicChannelCreation" A..= teamSettingsRestrictpublicchannelcreation+ ]+++data WebrtcSettings = WebrtcSettings+ { webrtcSettingsStunuri :: Text+ , webrtcSettingsTurnsharedkey :: Text+ , webrtcSettingsEnable :: Bool+ , webrtcSettingsGatewayadminsecret :: Text+ , webrtcSettingsTurnuri :: Text+ , webrtcSettingsGatewayadminurl :: Text+ , webrtcSettingsTurnusername :: Text+ , webrtcSettingsGatewaywebsocketurl :: Text+ } deriving (Read, Show, Eq)++instance A.FromJSON WebrtcSettings where+ parseJSON = A.withObject "webrtcSettings" $ \v -> do+ webrtcSettingsStunuri <- v A..: "StunURI"+ webrtcSettingsTurnsharedkey <- v A..: "TurnSharedKey"+ webrtcSettingsEnable <- v A..: "Enable"+ webrtcSettingsGatewayadminsecret <- v A..: "GatewayAdminSecret"+ webrtcSettingsTurnuri <- v A..: "TurnURI"+ webrtcSettingsGatewayadminurl <- v A..: "GatewayAdminUrl"+ webrtcSettingsTurnusername <- v A..: "TurnUsername"+ webrtcSettingsGatewaywebsocketurl <- v A..: "GatewayWebsocketUrl"+ return WebrtcSettings { .. }++instance A.ToJSON WebrtcSettings where+ toJSON WebrtcSettings { .. } = A.object+ [ "StunURI" A..= webrtcSettingsStunuri+ , "TurnSharedKey" A..= webrtcSettingsTurnsharedkey+ , "Enable" A..= webrtcSettingsEnable+ , "GatewayAdminSecret" A..= webrtcSettingsGatewayadminsecret+ , "TurnURI" A..= webrtcSettingsTurnuri+ , "GatewayAdminUrl" A..= webrtcSettingsGatewayadminurl+ , "TurnUsername" A..= webrtcSettingsTurnusername+ , "GatewayWebsocketUrl" A..= webrtcSettingsGatewaywebsocketurl+ ]+++data PasswordSettings = PasswordSettings+ { passwordSettingsUppercase :: Bool+ , passwordSettingsLowercase :: Bool+ , passwordSettingsNumber :: Bool+ , passwordSettingsSymbol :: Bool+ , passwordSettingsMinimumlength :: Int+ } deriving (Read, Show, Eq)++instance A.FromJSON PasswordSettings where+ parseJSON = A.withObject "passwordSettings" $ \v -> do+ passwordSettingsUppercase <- v A..: "Uppercase"+ passwordSettingsLowercase <- v A..: "Lowercase"+ passwordSettingsNumber <- v A..: "Number"+ passwordSettingsSymbol <- v A..: "Symbol"+ passwordSettingsMinimumlength <- v A..: "MinimumLength"+ return PasswordSettings { .. }++instance A.ToJSON PasswordSettings where+ toJSON PasswordSettings { .. } = A.object+ [ "Uppercase" A..= passwordSettingsUppercase+ , "Lowercase" A..= passwordSettingsLowercase+ , "Number" A..= passwordSettingsNumber+ , "Symbol" A..= passwordSettingsSymbol+ , "MinimumLength" A..= passwordSettingsMinimumlength+ ]++--++data PrivacySettings = PrivacySettings+ { privacySettingsShowemailaddress :: Bool+ , privacySettingsShowfullname :: Bool+ } deriving (Read, Show, Eq)++instance A.FromJSON PrivacySettings where+ parseJSON = A.withObject "privacySettings" $ \v -> do+ privacySettingsShowemailaddress <- v A..: "ShowEmailAddress"+ privacySettingsShowfullname <- v A..: "ShowFullName"+ return PrivacySettings { .. }++instance A.ToJSON PrivacySettings where+ toJSON PrivacySettings { .. } = A.object+ [ "ShowEmailAddress" A..= privacySettingsShowemailaddress+ , "ShowFullName" A..= privacySettingsShowfullname+ ]++--++data RateLimitSettings = RateLimitSettings+ { rateLimitSettingsEnable :: Bool+ , rateLimitSettingsVarybyremoteaddr :: Bool+ , rateLimitSettingsMemorystoresize :: Int+ , rateLimitSettingsMaxburst :: Int+ , rateLimitSettingsVarybyheader :: Text+ , rateLimitSettingsPersec :: Int+ } deriving (Read, Show, Eq)++instance A.FromJSON RateLimitSettings where+ parseJSON = A.withObject "rateLimitSettings" $ \v -> do+ rateLimitSettingsEnable <- v A..: "Enable"+ rateLimitSettingsVarybyremoteaddr <- v A..: "VaryByRemoteAddr"+ rateLimitSettingsMemorystoresize <- v A..: "MemoryStoreSize"+ rateLimitSettingsMaxburst <- v A..: "MaxBurst"+ rateLimitSettingsVarybyheader <- v A..: "VaryByHeader"+ rateLimitSettingsPersec <- v A..: "PerSec"+ return RateLimitSettings { .. }++instance A.ToJSON RateLimitSettings where+ toJSON RateLimitSettings { .. } = A.object+ [ "Enable" A..= rateLimitSettingsEnable+ , "VaryByRemoteAddr" A..= rateLimitSettingsVarybyremoteaddr+ , "MemoryStoreSize" A..= rateLimitSettingsMemorystoresize+ , "MaxBurst" A..= rateLimitSettingsMaxburst+ , "VaryByHeader" A..= rateLimitSettingsVarybyheader+ , "PerSec" A..= rateLimitSettingsPersec+ ]+++data LogSettings = LogSettings+ { logSettingsEnablefile :: Bool+ , logSettingsFilelocation :: Text+ , logSettingsFilelevel :: Text+ , logSettingsEnableconsole :: Bool+ , logSettingsEnablewebhookdebugging :: Bool+ , logSettingsConsolelevel :: Text+ , logSettingsFileformat :: Text+ , logSettingsEnablediagnostics :: Bool+ } deriving (Read, Show, Eq)++instance A.FromJSON LogSettings where+ parseJSON = A.withObject "logSettings" $ \v -> do+ logSettingsEnablefile <- v A..: "EnableFile"+ logSettingsFilelocation <- v A..: "FileLocation"+ logSettingsFilelevel <- v A..: "FileLevel"+ logSettingsEnableconsole <- v A..: "EnableConsole"+ logSettingsEnablewebhookdebugging <- v A..: "EnableWebhookDebugging"+ logSettingsConsolelevel <- v A..: "ConsoleLevel"+ logSettingsFileformat <- v A..: "FileFormat"+ logSettingsEnablediagnostics <- v A..: "EnableDiagnostics"+ return LogSettings { .. }++instance A.ToJSON LogSettings where+ toJSON LogSettings { .. } = A.object+ [ "EnableFile" A..= logSettingsEnablefile+ , "FileLocation" A..= logSettingsFilelocation+ , "FileLevel" A..= logSettingsFilelevel+ , "EnableConsole" A..= logSettingsEnableconsole+ , "EnableWebhookDebugging" A..= logSettingsEnablewebhookdebugging+ , "ConsoleLevel" A..= logSettingsConsolelevel+ , "FileFormat" A..= logSettingsFileformat+ , "EnableDiagnostics" A..= logSettingsEnablediagnostics+ ]++--++data MetricsSettings = MetricsSettings+ { metricsSettingsBlockprofilerate :: Integer+ , metricsSettingsEnable :: Bool+ , metricsSettingsListenaddress :: Text+ } deriving (Read, Show, Eq)++instance A.FromJSON MetricsSettings where+ parseJSON = A.withObject "metricsSettings" $ \v -> do+ metricsSettingsBlockprofilerate <- v A..: "BlockProfileRate"+ metricsSettingsEnable <- v A..: "Enable"+ metricsSettingsListenaddress <- v A..: "ListenAddress"+ return MetricsSettings { .. }++instance A.ToJSON MetricsSettings where+ toJSON MetricsSettings { .. } = A.object+ [ "BlockProfileRate" A..= metricsSettingsBlockprofilerate+ , "Enable" A..= metricsSettingsEnable+ , "ListenAddress" A..= metricsSettingsListenaddress+ ]++--++data NativeAppSettings = NativeAppSettings+ { nativeAppSettingsAndroidappdownloadlink :: Text+ , nativeAppSettingsAppdownloadlink :: Text+ , nativeAppSettingsIosappdownloadlink :: Text+ } deriving (Read, Show, Eq)++instance A.FromJSON NativeAppSettings where+ parseJSON = A.withObject "nativeAppSettings" $ \v -> do+ nativeAppSettingsAndroidappdownloadlink <- v A..: "AndroidAppDownloadLink"+ nativeAppSettingsAppdownloadlink <- v A..: "AppDownloadLink"+ nativeAppSettingsIosappdownloadlink <- v A..: "IosAppDownloadLink"+ return NativeAppSettings { .. }++instance A.ToJSON NativeAppSettings where+ toJSON NativeAppSettings { .. } = A.object+ [ "AndroidAppDownloadLink" A..= nativeAppSettingsAndroidappdownloadlink+ , "AppDownloadLink" A..= nativeAppSettingsAppdownloadlink+ , "IosAppDownloadLink" A..= nativeAppSettingsIosappdownloadlink+ ]+++data ComplianceSettings = ComplianceSettings+ { complianceSettingsDirectory :: Text+ , complianceSettingsEnable :: Bool+ , complianceSettingsEnabledaily :: Bool+ } deriving (Read, Show, Eq)++instance A.FromJSON ComplianceSettings where+ parseJSON = A.withObject "complianceSettings" $ \v -> do+ complianceSettingsDirectory <- v A..: "Directory"+ complianceSettingsEnable <- v A..: "Enable"+ complianceSettingsEnabledaily <- v A..: "EnableDaily"+ return ComplianceSettings { .. }++instance A.ToJSON ComplianceSettings where+ toJSON ComplianceSettings { .. } = A.object+ [ "Directory" A..= complianceSettingsDirectory+ , "Enable" A..= complianceSettingsEnable+ , "EnableDaily" A..= complianceSettingsEnabledaily+ ]+++data SupportSettings = SupportSettings+ { supportSettingsReportaproblemlink :: Text+ , supportSettingsHelplink :: Text+ , supportSettingsPrivacypolicylink :: Text+ , supportSettingsTermsofservicelink :: Text+ , supportSettingsAboutlink :: Text+ , supportSettingsSupportemail :: Text+ } deriving (Read, Show, Eq)++instance A.FromJSON SupportSettings where+ parseJSON = A.withObject "supportSettings" $ \v -> do+ supportSettingsReportaproblemlink <- v A..: "ReportAProblemLink"+ supportSettingsHelplink <- v A..: "HelpLink"+ supportSettingsPrivacypolicylink <- v A..: "PrivacyPolicyLink"+ supportSettingsTermsofservicelink <- v A..: "TermsOfServiceLink"+ supportSettingsAboutlink <- v A..: "AboutLink"+ supportSettingsSupportemail <- v A..: "SupportEmail"+ return SupportSettings { .. }++instance A.ToJSON SupportSettings where+ toJSON SupportSettings { .. } = A.object+ [ "ReportAProblemLink" A..= supportSettingsReportaproblemlink+ , "HelpLink" A..= supportSettingsHelplink+ , "PrivacyPolicyLink" A..= supportSettingsPrivacypolicylink+ , "TermsOfServiceLink" A..= supportSettingsTermsofservicelink+ , "AboutLink" A..= supportSettingsAboutlink+ , "SupportEmail" A..= supportSettingsSupportemail+ ]
src/Network/Mattermost/Util.hs view
@@ -23,8 +23,11 @@ , ConnectionParams(..) , TLSSettings(..) , connectionGet+ , connectionGetLine+ , connectionPut , connectionClose , connectTo )+import qualified Network.HTTP.Stream as HTTP import Network.Mattermost.Types.Internal @@ -59,11 +62,26 @@ -- | Creates a new connection to 'Hostname' from an already initialized 'ConnectionContext'. -- Internally it uses 'bracket' to cleanup the connection.-withConnection :: ConnectionData -> (Connection -> IO a) -> IO a+withConnection :: ConnectionData -> (MMConn -> IO a) -> IO a withConnection cd action =- bracket (mkConnection cd)- connectionClose+ bracket (MMConn <$> mkConnection cd)+ (connectionClose . fromMMConn) action++maxLineLength :: Int+maxLineLength = 2^(16::Int)++newtype MMConn = MMConn { fromMMConn :: Connection }++-- | This instance allows us to use 'simpleHTTP' from 'Network.HTTP.Stream' with+-- connections from the 'connection' package.+instance HTTP.Stream MMConn where+ readLine con = Right . B.unpack . dropTrailingChar <$> connectionGetLine maxLineLength (fromMMConn con)+ readBlock con n = Right . B.unpack <$> connectionGetExact (fromMMConn con) n+ writeBlock con block = Right <$> connectionPut (fromMMConn con) (B.pack block)+ close con = connectionClose (fromMMConn con)+ closeOnEnd _ _ = return ()+ -- | Creates a connection from a 'ConnectionData' value, returning it. It -- is the user's responsibility to close this appropriately.
src/Network/Mattermost/WebSocket.hs view
@@ -7,6 +7,7 @@ , MMWebSocketTimeoutException , mmWithWebSocket , mmCloseWebSocket+, mmSendWSAction , mmGetConnectionHealth , module Network.Mattermost.WebSocket.Types ) where@@ -142,3 +143,8 @@ propagate ts e = do sequence_ [ throwTo t e | t <- ts ] throwIO e++mmSendWSAction :: ConnectionData -> MMWebSocket -> WebsocketAction -> IO ()+mmSendWSAction cd (MMWS ws _) a = do+ runLogger cd "websocket" $ WebSocketRequest $ toJSON a+ WS.sendTextData ws a
src/Network/Mattermost/WebSocket/Types.hs view
@@ -7,6 +7,7 @@ , WebsocketEvent(..) , WEData(..) , WEBroadcast(..)+, WebsocketAction(..) ) where import Control.Applicative@@ -255,3 +256,29 @@ , "user_id" .= webUserId , "omit_users" .= webOmitUsers ]++--++data WebsocketAction =+ UserTyping { waSeq :: Int64+ , waChannelId :: ChannelId+ , waParentPostId :: Maybe PostId+ }+ -- -- | GetStatuses { waSeq :: Int64 }+ -- -- | GetStatusesByIds { waSeq :: Int64, waUserIds :: [UserId] }+ deriving (Read, Show, Eq, Ord)++instance ToJSON WebsocketAction where+ toJSON (UserTyping s cId pId) = A.object+ [ "seq" .= s+ , "action" .= T.pack "user_typing"+ , "data" .= A.object+ [ "channel_id" .= unId (toId cId)+ , "parent_id" .= maybe "" (unId . toId) pId+ ]+ ]++instance WebSocketsData WebsocketAction where+ fromDataMessage _ = error "Not implemented"+ fromLazyByteString _ = error "Not implemented"+ toLazyByteString = A.encode
test/Main.hs view
@@ -10,14 +10,14 @@ import Text.Show.Pretty ( ppShow ) -import Data.Aeson import Data.Monoid ((<>))-import qualified Data.HashMap.Strict as HM import qualified Data.Sequence as Seq+import qualified Data.Text as T (Text) import Test.Tasty import Network.Mattermost.Types+import Network.Mattermost.Types.Config import Network.Mattermost.WebSocket.Types import Network.Mattermost.Exceptions @@ -32,8 +32,8 @@ -- Users and other test configuration data -testConfig :: Config-testConfig = Config+testConfig :: TestConfig+testConfig = TestConfig { configUsername = "testAdmin" , configEmail = "testAdmin@example.com" , configHostname = "localhost"@@ -48,15 +48,20 @@ , password = "password" } -testMinChannel :: MinChannel-testMinChannel = MinChannel+testMinChannel :: TeamId -> MinChannel+testMinChannel tId = MinChannel { minChannelName = "test-channel" , minChannelDisplayName = "Test Channel" , minChannelPurpose = Just "A channel for test cases" , minChannelHeader = Just "Test Header" , minChannelType = Ordinary+ , minChannelTeamId = tId } +testMinChannelName :: T.Text+testMinChannelName = "test-channel"++ testTeamsCreate :: TeamsCreate testTeamsCreate = TeamsCreate { teamsCreateDisplayName = "Test Team"@@ -91,6 +96,7 @@ , leaveChannelTest , joinChannelTest , deleteChannelTest+ , clientConfigTest ] -- Test definitions@@ -120,16 +126,16 @@ print_ "Saving Config" -- Enable open team so that the admin can create -- new users.- let Object oldConfig = config- Object teamSettings = oldConfig HM.! "TeamSettings"- newConfig = Object (HM.insert "TeamSettings"- (Object (HM.insert "EnableOpenServer"- (Bool True) teamSettings)) oldConfig)+ let newTeamSettings = (configTeamsettings config) { teamSettingsEnableopenserver = True }+ newConfig = config { configTeamsettings = newTeamSettings } saveConfig newConfig expectWSEvent "admin joined town square" (isPost adminUser townSquare "testadmin has joined the channel.") + expectWSEvent "admin joined test team"+ (isAddedToTeam adminUser testTeam)+ print_ "Creating test account" testUser <- createAccount testAccount @@ -162,9 +168,8 @@ mmTestCase "Initial Load" testConfig $ do loginAccount testUserLogin - initialLoad <- getInitialLoad- -- print the team names- print_ (ppShow (fmap teamName (initialLoadTeams initialLoad)))+ teams <- getTeams+ print_ (ppShow (fmap teamName teams)) expectWSEvent "hello" (hasWSEventType WMHello) expectWSDone@@ -174,12 +179,16 @@ mmTestCase "Create Channel" testConfig $ do loginAccount testUserLogin - initialLoad <- getInitialLoad- let team Seq.:< _ = Seq.viewl (initialLoadTeams initialLoad)- chan <- createChannel team testMinChannel+ testUser <- getMe+ teams <- getTeams+ let team Seq.:< _ = Seq.viewl teams++ chan <- createChannel (testMinChannel (teamId team)) print_ (ppShow chan) expectWSEvent "hello" (hasWSEventType WMHello)+ expectWSEvent "test user joins test channel"+ (isPost testUser chan "test-user has joined the channel.") expectWSEvent "new channel event" (isChannelCreatedEvent chan) expectWSDone @@ -187,8 +196,8 @@ getChannelsTest = mmTestCase "Get Channels" testConfig $ do loginAccount testUserLogin- initialLoad <- getInitialLoad- let team Seq.:< _ = Seq.viewl (initialLoadTeams initialLoad)+ teams <- getTeams+ let team Seq.:< _ = Seq.viewl teams chans <- getChannels team let chan Seq.:< _ = Seq.viewl chans@@ -202,14 +211,14 @@ mmTestCase "Leave Channel" testConfig $ do loginAccount testUserLogin Just testUser <- getUserByName (username testUserLogin)- initialLoad <- getInitialLoad+ teams <- getTeams - let team Seq.:< _ = Seq.viewl (initialLoadTeams initialLoad)+ let team Seq.:< _ = Seq.viewl teams chans <- getChannels team print_ (ppShow chans) - let chan = findChannel chans $ minChannelName testMinChannel- leaveChannel team chan+ let chan = findChannel chans $ testMinChannelName+ leaveChannel chan expectWSEvent "hello" (hasWSEventType WMHello) expectWSEvent "leave channel" (isUserLeave testUser chan)@@ -220,25 +229,26 @@ mmTestCase "Join Channel" testConfig $ do loginAccount testUserLogin Just testUser <- getUserByName (username testUserLogin)- initialLoad <- getInitialLoad+ teams <- getTeams - let team Seq.:< _ = Seq.viewl (initialLoadTeams initialLoad)- chans <- getMoreChannels team+ let team Seq.:< _ = Seq.viewl teams+ chans <- getChannels team print_ (ppShow chans) - let chan = findChannel chans $ minChannelName testMinChannel- joinChannel team chan+ let chan = findChannel chans $ testMinChannelName+ joinChannel testUser chan - members <- getChannelMembers team chan+ members <- getChannelMembers chan let expected :: [User] expected = [testUser]- when (members /= expected) $- error $ "Expected channel members: " <> show expected+ when (fmap userId members /= fmap userId expected) $+ error $ "Expected channel members: " <> show expected <> "\ngot: " <> show members expectWSEvent "hello" (hasWSEventType WMHello) expectWSEvent "join channel" (isUserJoin testUser chan) expectWSEvent "join post" (isPost testUser chan "test-user has joined the channel.")+ expectWSEvent "view channel" isViewedChannel expectWSDone deleteChannelTest :: TestTree@@ -247,13 +257,13 @@ loginAccount testUserLogin Just testUser <- getUserByName (username testUserLogin) - initialLoad <- getInitialLoad- let team Seq.:< _ = Seq.viewl (initialLoadTeams initialLoad)+ teams <- getTeams+ let team Seq.:< _ = Seq.viewl teams chans <- getChannels team - let toDelete = findChannel chans (minChannelName testMinChannel)+ let toDelete = findChannel chans (testMinChannelName) - deleteChannel team toDelete+ deleteChannel toDelete expectWSEvent "hello" (hasWSEventType WMHello) @@ -264,3 +274,30 @@ (isChannelDeleteEvent toDelete) expectWSDone++clientConfigTest :: TestTree+clientConfigTest =+ mmTestCase "Client Config Test" testConfig $ do+ loginAccount testUserLogin++ print_ "Getting Client Config"+ config <- getClientConfig++ print_ (ppShow config)++ return ()++ -- let Object config = configObj++ -- keyAssert "AboutLink" config+ -- keyAssert "EnableSignInWithEmail" config+ -- keyAssert "RestrictPrivateChannelCreation" config+ -- keyAssert "SiteName" config+ -- keyAssert "TermsOfServiceLink" config+ -- keyAssert "WebsocketSecurePort" config++ -- where+ -- keyAssert k c = unless (HM.member k c) $+ -- let m = T.unpack k <> " key not present"+ -- in print_ m+ -- >> error m
test/Tests/Types.hs view
@@ -1,5 +1,5 @@ module Tests.Types- ( Config(..)+ ( TestConfig(..) , TestM , TestState(..) )@@ -14,20 +14,21 @@ import Network.Mattermost.Types (Session) import Network.Mattermost.WebSocket.Types -data Config- = Config { configUsername :: Text- , configHostname :: Text- , configTeam :: Text- , configPort :: Int- , configPassword :: Text- , configEmail :: Text- }+data TestConfig+ = TestConfig+ { configUsername :: Text+ , configHostname :: Text+ , configTeam :: Text+ , configPort :: Int+ , configPassword :: Text+ , configEmail :: Text+ } type TestM a = StateT TestState IO a data TestState = TestState { tsPrinter :: String -> IO ()- , tsConfig :: Config+ , tsConfig :: TestConfig , tsConnectionData :: ConnectionData , tsSession :: Maybe Session , tsDebug :: Bool
test/Tests/Util.hs view
@@ -3,16 +3,17 @@ , print_ , getConnection , getSession- , getInitialLoad+ , getTeams , createChannel , deleteChannel , joinChannel , leaveChannel- , getMoreChannels+-- , getMoreChannels , getChannels , getChannelMembers , getUserByName , getConfig+ , getClientConfig , saveConfig , teamAddUser , reportJSONExceptions@@ -24,6 +25,7 @@ , createTeam , findChannel , connectFromConfig+ , getMe -- * Testing Websocket Events , expectWSEvent@@ -38,18 +40,20 @@ , isNewUserEvent , isChannelCreatedEvent , isChannelDeleteEvent+ , isAddedToTeam , isUserJoin , isUserLeave+ , isViewedChannel , wsHas , (&&&) ) where -import qualified Data.Aeson as A import qualified Control.Exception as E import qualified Control.Concurrent.STM as STM import Control.Concurrent (forkIO) import Control.Concurrent.MVar+import qualified Data.Foldable as F import Data.Monoid ((<>)) import qualified Data.Sequence as Seq import qualified Data.Text as T@@ -57,15 +61,18 @@ import Test.Tasty.HUnit (testCaseSteps) import Control.Monad.State.Lazy import System.Timeout (timeout)-import qualified Data.HashMap.Lazy as HM -import Network.Mattermost+import Network.Mattermost (ConnectionData)+import Network.Mattermost.Endpoints+import Network.Mattermost.Types+import Network.Mattermost.Types.Config import Network.Mattermost.WebSocket import Network.Mattermost.Exceptions+import Network.Mattermost.Util import Tests.Types -mmTestCase :: String -> Config -> TestM () -> TestTree+mmTestCase :: String -> TestConfig -> TestM () -> TestTree mmTestCase testName cfg act = testCaseSteps testName $ \prnt -> do cd <- connectFromConfig cfg@@ -101,7 +108,7 @@ putStrLn badJson E.throwIO e -adminAccount :: Config -> UsersCreate+adminAccount :: TestConfig -> UsersCreate adminAccount cfg = UsersCreate { usersCreateEmail = configEmail cfg , usersCreatePassword = configPassword cfg@@ -113,7 +120,7 @@ createAdminAccount = do cd <- getConnection cfg <- gets tsConfig- u <- liftIO $ mmUsersCreate cd $ adminAccount cfg+ u <- liftIO $ mmInitialUser cd $ adminAccount cfg print_ "Admin Account created" return u @@ -196,6 +203,20 @@ isNewUserEvent u = hasWSEventType WMNewUser &&& forUser u +isViewedChannel :: WebsocketEvent -> Bool+isViewedChannel = hasWSEventType WMChannelViewed++-- | Is the websocket event indicating that a new user was added to the+-- team+isAddedToTeam :: User+ -- ^ The user that was added+ -> Team+ -- ^ The team to which the user was added+ -> WebsocketEvent+ -> Bool+isAddedToTeam u _ =+ hasWSEventType WMAddedToTeam &&& forUser u+ isChannelCreatedEvent :: Channel -> WebsocketEvent -> Bool@@ -282,14 +303,14 @@ createAccount :: UsersCreate -> TestM User createAccount account = do session <- getSession- newUser <- liftIO $ mmUsersCreateWithSession session account+ newUser <- liftIO $ mmCreateUser account session print_ $ "account created for " <> (T.unpack $ usersCreateUsername account) return newUser createTeam :: TeamsCreate -> TestM Team createTeam tc = do session <- getSession- team <- liftIO $ mmCreateTeam session tc+ team <- liftIO $ mmCreateTeam tc session print_ $ "Team created: " <> (T.unpack $ teamsCreateName tc) return team @@ -307,7 +328,7 @@ in error $ "Expected to find channel by name " <> show name <> " but got " <> show namePairs -connectFromConfig :: Config -> IO ConnectionData+connectFromConfig :: TestConfig -> IO ConnectionData connectFromConfig cfg = initConnectionDataInsecure (configHostname cfg) (fromIntegral (configPort cfg))@@ -322,73 +343,95 @@ Just s -> return s Nothing -> error "Expected authentication token but none was present" -getInitialLoad :: TestM InitialLoad-getInitialLoad = do+getTeams :: TestM (Seq.Seq Team)+getTeams = do session <- getSession- liftIO $ mmGetInitialLoad session+ liftIO $ mmGetUsersTeams UserMe session +getMe :: TestM User+getMe = do+ session <- getSession+ liftIO $ mmGetUser UserMe session+ getUserByName :: T.Text -> TestM (Maybe User) getUserByName uname = do session <- getSession- allUserMap <- liftIO $ mmGetUsers session 0 10000+ let query = defaultUserQuery+ { userQueryPage = Just 0+ , userQueryPerPage = Just 10000+ }+ allUserMap <- liftIO $ mmGetUsers query session -- Find the user matching the username and get its ID- let matches = HM.filter matchingUser allUserMap+ let matches = Seq.filter matchingUser allUserMap matchingUser u = userUsername u == uname - case HM.size matches == 1 of- False -> return Nothing- True -> do- let uId = fst $ HM.toList matches !! 0+ case Seq.viewl matches of+ user Seq.:< _ -> do+ let uId = userId user -- Then load the User record- Just <$> (liftIO $ mmGetUser session uId)--createChannel :: Team -> MinChannel -> TestM Channel-createChannel team mc = do- session <- getSession- liftIO $ mmCreateChannel session (teamId team) mc+ Just <$> (liftIO $ mmGetUser (UserById uId) session)+ _ -> return Nothing -deleteChannel :: Team -> Channel -> TestM ()-deleteChannel team ch = do+createChannel :: MinChannel -> TestM Channel+createChannel mc = do session <- getSession- liftIO $ mmDeleteChannel session (teamId team) (channelId ch)+ liftIO $ mmCreateChannel mc session -joinChannel :: Team -> Channel -> TestM ()-joinChannel team chan = do+deleteChannel :: Channel -> TestM ()+deleteChannel ch = do session <- getSession- liftIO $ mmJoinChannel session (teamId team) (channelId chan)+ liftIO $ mmDeleteChannel (channelId ch) session -getMoreChannels :: Team -> TestM Channels-getMoreChannels team = do+joinChannel :: User -> Channel -> TestM ()+joinChannel user chan = do session <- getSession- liftIO $ mmGetMoreChannels session (teamId team) 0 100+ let member = MinChannelMember+ { minChannelMemberUserId = userId user+ , minChannelMemberChannelId = channelId chan+ }+ liftIO $ void $ mmAddUser (channelId chan) member session -leaveChannel :: Team -> Channel -> TestM ()-leaveChannel team chan = do+leaveChannel :: Channel -> TestM ()+leaveChannel chan = do session <- getSession- liftIO $ mmLeaveChannel session (teamId team) (channelId chan)+ liftIO $ mmRemoveUserFromChannel (channelId chan) UserMe session -getChannelMembers :: Team -> Channel -> TestM [User]-getChannelMembers team chan = do+getChannelMembers :: Channel -> TestM [User]+getChannelMembers chan = do session <- getSession- (snd <$>) <$> HM.toList <$>- (liftIO $ mmGetChannelMembers session (teamId team) (channelId chan) 0 10000)+ let query = defaultUserQuery+ { userQueryPage = Just 0+ , userQueryPerPage = Just 10000+ , userQueryInChannel = Just (channelId chan)+ }+ F.toList <$> (liftIO $ mmGetUsers query session) getChannels :: Team -> TestM Channels getChannels team = do session <- getSession- liftIO $ mmGetChannels session (teamId team)+ liftIO $ mmGetPublicChannels (teamId team) Nothing Nothing session -getConfig :: TestM A.Value+getConfig :: TestM ServerConfig getConfig = do session <- getSession- liftIO $ mmGetConfig session+ liftIO $ mmGetConfiguration session -saveConfig :: A.Value -> TestM ()+getClientConfig :: TestM ClientConfig -- A.Value+getClientConfig = do+ session <- getSession+ liftIO $ mmGetClientConfiguration (Just (T.pack "old")) session++saveConfig :: ServerConfig -> TestM () saveConfig newConfig = do session <- getSession- liftIO $ mmSaveConfig session newConfig+ liftIO $ void $ mmUpdateConfiguration newConfig session teamAddUser :: Team -> User -> TestM () teamAddUser team user = do session <- getSession- liftIO $ mmTeamAddUser session (teamId team) (userId user)+ let member = TeamMember+ { teamMemberUserId = userId user+ , teamMemberTeamId = teamId team+ , teamMemberRoles = T.empty+ }+ liftIO $ void $ mmAddUserToTeam (teamId team) member session