Add Exceptions
parent
cb3c570c39
commit
206353b583
|
@ -0,0 +1,217 @@
|
||||||
|
module Internal.Values.Exceptions exposing (Error(..), ClientError(..), ServerError(..), errorCatches, errorToString)
|
||||||
|
|
||||||
|
{-| This module contains all potential errors that may be passed around in the SDK.
|
||||||
|
-}
|
||||||
|
|
||||||
|
import Dict
|
||||||
|
import Http
|
||||||
|
import Internal.Tools.DecodeExtra exposing (opField)
|
||||||
|
import Internal.Config.ErrorStrings as ES
|
||||||
|
import Json.Decode as D
|
||||||
|
import Json.Encode as E
|
||||||
|
|
||||||
|
|
||||||
|
type Error
|
||||||
|
= InternetException Http.Error
|
||||||
|
| SDKException ClientError
|
||||||
|
| ServerException ServerError
|
||||||
|
| UnsupportedVersion
|
||||||
|
|
||||||
|
|
||||||
|
{-| Errors that this SDK might return if it doesn't like its own input, if it
|
||||||
|
notices some internal inconsistencies or if it cannot interpret the server's
|
||||||
|
input.
|
||||||
|
|
||||||
|
- `ServerReturnsBadJSON` The homeserver sent JSON that does not parse.
|
||||||
|
- `ServerDoesntFollowJSONSpec` The homeserver sent data that lacks keys
|
||||||
|
required by spec.
|
||||||
|
- `ServerDoesntReturnBaseURL` The homeserver does not clarify its API
|
||||||
|
endpoints.
|
||||||
|
- `CouldntGetTimestamp` The Elm core somehow failed to get the current
|
||||||
|
Unix timestamp.
|
||||||
|
- `InvalidInputAccordingToSpec` The function contains invalid values.
|
||||||
|
|
||||||
|
-}
|
||||||
|
type ClientError
|
||||||
|
= ServerReturnsBadJSON String
|
||||||
|
| CouldntGetTimestamp
|
||||||
|
| InsufficientCredentials String
|
||||||
|
| NotSupportedYet String
|
||||||
|
|
||||||
|
|
||||||
|
{-| Potential error codes that the server may return. If the error is not a
|
||||||
|
default one described in the Matrix Spec, it will be a `CustomServerError`
|
||||||
|
and provide with the custom string.
|
||||||
|
-}
|
||||||
|
type
|
||||||
|
ServerError
|
||||||
|
-- COMMON ERROR CODES
|
||||||
|
-- These error codes can be returned by any API endpoint.
|
||||||
|
-- See https://spec.matrix.org/v1.5/client-server-api/#common-error-codes
|
||||||
|
= M_FORBIDDEN { error : Maybe String }
|
||||||
|
| M_UNKNOWN_TOKEN { error : Maybe String, soft_logout : Maybe Bool }
|
||||||
|
| M_MISSING_TOKEN { error : Maybe String, soft_logout : Maybe Bool }
|
||||||
|
| M_BAD_JSON { error : Maybe String }
|
||||||
|
| M_NOT_JSON { error : Maybe String }
|
||||||
|
| M_NOT_FOUND { error : Maybe String }
|
||||||
|
| M_LIMIT_EXCEEDED { error : Maybe String, retryAfterMs : Maybe Int }
|
||||||
|
| M_UNKNOWN { error : Maybe String }
|
||||||
|
-- OTHER ERROR CODES
|
||||||
|
-- These error codes are specific to certain endpoints.
|
||||||
|
-- See https://spec.matrix.org/v1.4/client-server-api/#other-error-codes
|
||||||
|
| M_UNRECOGNIZED { error : Maybe String }
|
||||||
|
| M_UNAUTHORIZED { error : Maybe String }
|
||||||
|
| M_USER_DEACTIVATED { error : Maybe String }
|
||||||
|
| M_USER_IN_USE { error : Maybe String }
|
||||||
|
| M_INVALID_USERNAME { error : Maybe String }
|
||||||
|
| M_ROOM_IN_USE { error : Maybe String }
|
||||||
|
| M_INVALID_ROOM_STATE { error : Maybe String }
|
||||||
|
| M_THREEPID_IN_USE { error : Maybe String }
|
||||||
|
| M_THREEPID_NOT_FOUND { error : Maybe String }
|
||||||
|
| M_THREEPID_AUTH_FAILED { error : Maybe String }
|
||||||
|
| M_THREEPID_DENIED { error : Maybe String }
|
||||||
|
| M_SERVER_NOT_TRUSTED { error : Maybe String }
|
||||||
|
| M_UNSUPPORTED_ROOM_VERSION { error : Maybe String }
|
||||||
|
| M_INCOMPATIBLE_ROOM_VERSION
|
||||||
|
{ error : Maybe String
|
||||||
|
, room_version : Maybe String
|
||||||
|
}
|
||||||
|
| M_BAD_STATE { error : Maybe String }
|
||||||
|
| M_GUEST_ACCESS_FORBIDDEN { error : Maybe String }
|
||||||
|
| M_CAPTCHA_NEEDED { error : Maybe String }
|
||||||
|
| M_CAPTCHA_INVALID { error : Maybe String }
|
||||||
|
| M_MISSING_PARAM { error : Maybe String }
|
||||||
|
| M_INVALID_PARAM { error : Maybe String }
|
||||||
|
| M_TOO_LARGE { error : Maybe String }
|
||||||
|
| M_EXCLUSIVE { error : Maybe String }
|
||||||
|
| M_RESOURCE_LIMIT_EXCEEDED
|
||||||
|
{ error : Maybe String
|
||||||
|
, adminContact : String
|
||||||
|
}
|
||||||
|
| M_CANNOT_LEAVE_SERVER_NOTICE_ROOM { error : Maybe String }
|
||||||
|
-- Error codes that help understand the server's output
|
||||||
|
| RequiresUserInteractiveAuthentication
|
||||||
|
{ completed : List String
|
||||||
|
, flows : List (List String)
|
||||||
|
, params : Dict.Dict String (Dict.Dict String String)
|
||||||
|
, session : Maybe String
|
||||||
|
}
|
||||||
|
-- CUSTOM ERROR CODES
|
||||||
|
-- These can be defined by custom homeserver implementations
|
||||||
|
| CustomServerError
|
||||||
|
{ errcode : String
|
||||||
|
, fullError : E.Value
|
||||||
|
, statusCode : Int
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{-| Shortcut for the decoder of most errors defined in the Matrix spec
|
||||||
|
-}
|
||||||
|
standardErrorDescription : D.Decoder { error : Maybe String }
|
||||||
|
standardErrorDescription =
|
||||||
|
D.map (\err -> { error = err }) (opField "error" D.string)
|
||||||
|
|
||||||
|
|
||||||
|
{-| Dictionary of known errors that the homeserver may return.
|
||||||
|
The key is the error type, while the value is a function that reads all required
|
||||||
|
and optional fields from the response based on Matrix specifications.
|
||||||
|
-}
|
||||||
|
errorCatches : D.Decoder ServerError
|
||||||
|
errorCatches =
|
||||||
|
D.oneOf
|
||||||
|
[ errorDecoder "M_FORBIDDEN" M_FORBIDDEN standardErrorDescription
|
||||||
|
, errorDecoder "M_UNKNOWN_TOKEN"
|
||||||
|
M_UNKNOWN_TOKEN
|
||||||
|
(D.map2
|
||||||
|
(\err slg -> { error = err, soft_logout = slg })
|
||||||
|
(opField "error" D.string)
|
||||||
|
(opField "soft_logout" D.bool)
|
||||||
|
)
|
||||||
|
, errorDecoder "M_MISSING_TOKEN"
|
||||||
|
M_MISSING_TOKEN
|
||||||
|
(D.map2
|
||||||
|
(\err slg -> { error = err, soft_logout = slg })
|
||||||
|
(opField "error" D.string)
|
||||||
|
(opField "soft_logout" D.bool)
|
||||||
|
)
|
||||||
|
, errorDecoder "M_BAD_JSON" M_BAD_JSON standardErrorDescription
|
||||||
|
, errorDecoder "M_NOT_JSON" M_NOT_JSON standardErrorDescription
|
||||||
|
, errorDecoder "M_NOT_FOUND" M_NOT_FOUND standardErrorDescription
|
||||||
|
, errorDecoder "M_LIMIT_EXCEEDED"
|
||||||
|
M_LIMIT_EXCEEDED
|
||||||
|
(D.map2
|
||||||
|
(\err rams -> { error = err, retryAfterMs = rams })
|
||||||
|
(opField "error" D.string)
|
||||||
|
(opField "retry_after_ms" D.int)
|
||||||
|
)
|
||||||
|
, errorDecoder "M_UNKNOWN" M_UNKNOWN standardErrorDescription
|
||||||
|
, errorDecoder "M_UNRECOGNIZED" M_UNRECOGNIZED standardErrorDescription
|
||||||
|
, errorDecoder "M_UNAUTHORIZED" M_UNAUTHORIZED standardErrorDescription
|
||||||
|
, errorDecoder "M_USER_DEACTIVATED" M_USER_DEACTIVATED standardErrorDescription
|
||||||
|
, errorDecoder "M_USER_IN_USE" M_USER_IN_USE standardErrorDescription
|
||||||
|
, errorDecoder "M_INVALID_USERNAME" M_INVALID_USERNAME standardErrorDescription
|
||||||
|
, errorDecoder "M_ROOM_IN_USE" M_ROOM_IN_USE standardErrorDescription
|
||||||
|
, errorDecoder "M_INVALID_ROOM_STATE" M_INVALID_ROOM_STATE standardErrorDescription
|
||||||
|
, errorDecoder "M_THREEPID_IN_USE" M_THREEPID_IN_USE standardErrorDescription
|
||||||
|
, errorDecoder "M_THREEPID_NOT_FOUND" M_THREEPID_NOT_FOUND standardErrorDescription
|
||||||
|
, errorDecoder "M_THREEPID_AUTH_FAILED" M_THREEPID_AUTH_FAILED standardErrorDescription
|
||||||
|
, errorDecoder "M_THREEPID_DENIED" M_THREEPID_DENIED standardErrorDescription
|
||||||
|
, errorDecoder "M_SERVER_NOT_TRUSTED" M_SERVER_NOT_TRUSTED standardErrorDescription
|
||||||
|
, errorDecoder "M_UNSUPPORTED_ROOM_VERSION" M_UNSUPPORTED_ROOM_VERSION standardErrorDescription
|
||||||
|
, errorDecoder "M_INCOMPATIBLE_ROOM_VERSION"
|
||||||
|
M_INCOMPATIBLE_ROOM_VERSION
|
||||||
|
(D.map2
|
||||||
|
(\err rv -> { error = err, room_version = rv })
|
||||||
|
(opField "error" D.string)
|
||||||
|
(opField "room_version" D.string)
|
||||||
|
)
|
||||||
|
, errorDecoder "M_BAD_STATE" M_BAD_STATE standardErrorDescription
|
||||||
|
, errorDecoder "M_GUEST_ACCESS_FORBIDDEN" M_GUEST_ACCESS_FORBIDDEN standardErrorDescription
|
||||||
|
, errorDecoder "M_CAPTCHA_NEEDED" M_CAPTCHA_NEEDED standardErrorDescription
|
||||||
|
, errorDecoder "M_CAPTCHA_INVALID" M_CAPTCHA_INVALID standardErrorDescription
|
||||||
|
, errorDecoder "M_MISSING_PARAM" M_MISSING_PARAM standardErrorDescription
|
||||||
|
, errorDecoder "M_INVALID_PARAM" M_INVALID_PARAM standardErrorDescription
|
||||||
|
, errorDecoder "M_TOO_LARGE" M_TOO_LARGE standardErrorDescription
|
||||||
|
, errorDecoder "M_EXCLUSIVE" M_EXCLUSIVE standardErrorDescription
|
||||||
|
, errorDecoder "M_RESOURCE_LIMIT_EXCEEDED"
|
||||||
|
M_RESOURCE_LIMIT_EXCEEDED
|
||||||
|
(D.map2
|
||||||
|
(\err ac -> { error = err, adminContact = ac })
|
||||||
|
(opField "error" D.string)
|
||||||
|
(D.field "admin_contact" D.string)
|
||||||
|
)
|
||||||
|
, errorDecoder "M_CANNOT_LEAVE_SERVER_NOTICE_ROOM" M_CANNOT_LEAVE_SERVER_NOTICE_ROOM standardErrorDescription
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
errorDecoder : String -> (a -> ServerError) -> D.Decoder a -> D.Decoder ServerError
|
||||||
|
errorDecoder name code decoder =
|
||||||
|
D.field "errcode" D.string
|
||||||
|
|> D.andThen
|
||||||
|
(\errcode ->
|
||||||
|
if errcode == name then
|
||||||
|
D.map code decoder
|
||||||
|
|
||||||
|
else
|
||||||
|
D.fail "Not the right errcode"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
errorToString : Error -> String
|
||||||
|
errorToString e =
|
||||||
|
case e of
|
||||||
|
UnsupportedVersion ->
|
||||||
|
ES.unsupportedVersion
|
||||||
|
|
||||||
|
SDKException (ServerReturnsBadJSON s) ->
|
||||||
|
ES.serverReturnsBadJSON s
|
||||||
|
|
||||||
|
SDKException CouldntGetTimestamp ->
|
||||||
|
ES.couldNotGetTimestamp
|
||||||
|
|
||||||
|
ServerException (M_FORBIDDEN data) ->
|
||||||
|
ES.serverSaysForbidden data.error
|
||||||
|
|
||||||
|
-- ServerError (M_UNKNOWN_TOKEN data) ->
|
||||||
|
_ ->
|
||||||
|
"ERROR NEEDS STRING"
|
Loading…
Reference in New Issue