Initial version.

This commit is contained in:
Oliver Hauff 2021-05-13 20:03:07 +02:00
parent 193aaa1a56
commit b72c67a53e
228 changed files with 25924 additions and 0 deletions

View file

@ -0,0 +1,48 @@
namespace TINK.Model.Repository.Exception
{
/// <summary>
/// Is fired with reqest used a cookie which is not defined.
/// Reasons for cookie to be not defined might be
/// - user used more thant 8 different devices (copri invalidates cookies in this case)
/// - user account has been deleted?
/// </summary>
public class AuthcookieNotDefinedException : InvalidResponseException<Response.ResponseBase>
{
/// <summary>Constructs a authorization exceptions. </summary>
/// <param name="p_strTextOfAction">Text describing request which is shown if validation fails.</param>
public AuthcookieNotDefinedException(string p_strTextOfAction, Response.ResponseBase response) :
base($"{p_strTextOfAction}\r\nDie Sitzung ist abgelaufen. Bitte neu anmelden.", response)
{
}
public static bool IsAuthcookieNotDefined(
Response.ResponseBase reponse,
string actionText,
out AuthcookieNotDefinedException exception)
{
if (!reponse.response_state.ToUpper().Contains(AUTH_FAILURE_QUERY_AUTHCOOKIENOTDEFIED.ToUpper())
&& !reponse.response_state.ToUpper().Contains(AUTH_FAILURE_BOOK_AUTICOOKIENOTDEFIED.ToUpper())
&& !reponse.response_state.ToUpper().Contains(AUTH_FAILURE_BIKESOCCUPIED_AUTICOOKIENOTDEFIED.ToUpper())
&& !reponse.response_state.ToUpper().Contains(AUTH_FAILURE_LOGOUT_AUTHCOOKIENOTDEFIED.ToUpper()))
{
exception = null;
return false;
}
exception = new AuthcookieNotDefinedException(actionText, reponse);
return true;
}
/// <summary> Holds error description if session expired. From COPRI 4.0.0.0 1001 is the only authcookie not defined error. </summary>
private const string AUTH_FAILURE_QUERY_AUTHCOOKIENOTDEFIED = "Failure 1001: authcookie not defined";
/// <summary> Holds error description if session expired (Applies to COPRI < 4.0.0.0) </summary>
private const string AUTH_FAILURE_BOOK_AUTICOOKIENOTDEFIED = "Failure 1002: authcookie not defined";
/// <summary> Holds error description if session expired (Applies to COPRI < 4.0.0.0) </summary>
private const string AUTH_FAILURE_BIKESOCCUPIED_AUTICOOKIENOTDEFIED = "Failure 1003: authcookie not defined";
/// <summary> Holds error description if session expired. (Applies to COPRI < 4.0.0.0)</summary>
private const string AUTH_FAILURE_LOGOUT_AUTHCOOKIENOTDEFIED = "Failure 1004: authcookie not defined";
}
}

View file

@ -0,0 +1,15 @@
namespace TINK.Model.Repository.Exception
{
public class InvalidAuthorizationResponseException : InvalidResponseException<Response.ResponseBase>
{
/// <summary>Constructs a authorization exceptions. </summary>
/// <param name="p_strMail">Mail address to create a detailed error message.</param>
public InvalidAuthorizationResponseException(string p_strMail, Response.ResponseBase p_oResponse) :
base(string.Format("Kann Benutzer {0} nicht anmelden. Mailadresse unbekannt oder Passwort ungültig.", p_strMail), p_oResponse)
{
}
/// <summary> Holds error description if user/ password combination is not valid. </summary>
public const string AUTH_FAILURE_STATUS_MESSAGE_UPPERCASE = "FAILURE: CANNOT GENERATE AUTHCOOKIE";
}
}

View file

@ -0,0 +1,42 @@
using System.Text.RegularExpressions;
namespace TINK.Model.Repository.Exception
{
/// <summary> Handles booking request which fail due to too many bikes requested/ booked.</summary>
public class BookingDeclinedException : InvalidResponseException
{
/// <summary> Holds error description if user/ password combination is not valid. </summary>
public const string BOOKING_FAILURE_STATUS_MESSAGE_UPPERCASE = "(OK: BOOKING_REQUEST DECLINED\\. MAX COUNT OF )([0-9]+)( OCCUPIED BIKES HAS BEEN REACHED)";
/// <summary> Prevents invalid use of exception. </summary>
private BookingDeclinedException() : base(typeof(BookingDeclinedException).Name)
{
}
/// <summary> Prevents invalid use of exception. </summary>
public BookingDeclinedException(int maxBikesCount) : base(typeof(BookingDeclinedException).Name)
{
MaxBikesCount = maxBikesCount;
}
public static bool IsBookingDeclined(string responseState, out BookingDeclinedException exception)
{
// Check if there are too many bikes requested/ booked.
var match = Regex.Match(
responseState.ToUpper(),
BOOKING_FAILURE_STATUS_MESSAGE_UPPERCASE);
if (match.Groups.Count!= 4
|| !int.TryParse(match.Groups[2].ToString(), out int maxBikesCount))
{
exception = null;
return false;
}
exception = new BookingDeclinedException(maxBikesCount);
return true;
}
/// <summary> Holds the maximum count of bikes allowed to reserve/ book.</summary>
public int MaxBikesCount { get; private set; }
}
}

View file

@ -0,0 +1,6 @@
namespace TINK.Model.Repository.Exception
{
public class CallNotRequiredException : System.Exception
{
}
}

View file

@ -0,0 +1,28 @@
namespace TINK.Model.Repository.Exception
{
public class CommunicationException : System.Exception
{
/// <summary>
/// Constructs a communication exception object.
/// </summary>
public CommunicationException()
{ }
/// <summary>
/// Constructs a communication exeption object.
/// </summary>
/// <param name="p_strMessage">Error message.</param>
public CommunicationException(string p_strMessage) : base(p_strMessage)
{
}
/// <summary>
/// Constructs a communication exeption object.
/// </summary>
/// <param name="p_strMessage">Error message.</param>
/// <param name="p_oException">Inner exceptions.</param>
public CommunicationException(string p_strMessage, System.Exception p_oException) : base(p_strMessage, p_oException)
{
}
}
}

View file

@ -0,0 +1,11 @@
using TINK.Model.Repository.Exception;
namespace TINK.Repository.Exception
{
public class DeserializationException : CommunicationException
{
public DeserializationException(System.Exception ex) : base(ex.Message, ex)
{
}
}
}

View file

@ -0,0 +1,34 @@
namespace TINK.Model.Repository.Exception
{
public class InvalidResponseException<T> : InvalidResponseException
{
/// <summary> Constructs an invalid response Exception. </summary>
/// <param name="p_strActionWhichFailed">Describes the action which failed.</param>
/// <param name="p_oResponse">Response from copri.</param>
public InvalidResponseException(string p_strActionWhichFailed, T p_oResponse)
: base(string.Format(
"{0}{1}",
p_strActionWhichFailed,
p_oResponse == null ? string.Format(" Response des Typs {0} ist null.", typeof(T).Name.ToString()) : string.Empty))
{
Response = p_oResponse;
}
public T Response { get; private set; }
}
/// <summary>
/// Base exception for all generic invalid response exceptions.
/// </summary>
public class InvalidResponseException : CommunicationException
{
/// <summary> Prevents an invalid instance to be created. </summary>
private InvalidResponseException()
{ }
/// <summary> Constructs a invalid response execption.</summary>
/// <param name="p_strMessage">Exception.</param>
public InvalidResponseException(string p_strMessage) : base(p_strMessage)
{ }
}
}

View file

@ -0,0 +1,28 @@
using TINK.Model.Repository.Exception;
namespace TINK.Repository.Exception
{
public class NoGPSDataException : InvalidResponseException
{
/// <summary> COPRI response status. </summary>
public const string RETURNBIKE_FAILURE_STATUS_MESSAGE_UPPERCASE = "FAILURE 2245: NO GPS DATA, STATE CHANGE FORBIDDEN.";
/// <summary> Prevents invalid use of exception. </summary>
private NoGPSDataException() : base(typeof(NoGPSDataException).Name)
{
}
public static bool IsNoGPSData(string responseState, out NoGPSDataException exception)
{
// Check if there are too many bikes requested/ booked.
if (!responseState.Trim().ToUpper().StartsWith(RETURNBIKE_FAILURE_STATUS_MESSAGE_UPPERCASE))
{
exception = null;
return false;
}
exception = new NoGPSDataException();
return true;
}
}
}

View file

@ -0,0 +1,39 @@
using System.Text.RegularExpressions;
namespace TINK.Model.Repository.Exception
{
public class NotAtStationException : InvalidResponseException
{
/// <summary> COPRI response status regular expression. </summary>
public const string RETURNBIKE_FAILURE_STATUS_MESSAGE_UPPERCASE = "(FAILURE 2178: BIKE [0-9]+ OUT OF GEO FENCING\\. )([0-9]+)( METER DISTANCE TO NEXT STATION )([0-9]+)";
/// <summary> Prevents invalid use of exception. </summary>
private NotAtStationException() : base(typeof(NotAtStationException).Name)
{
}
public static bool IsNotAtStation(string responseState, out NotAtStationException exception)
{
// Check if there are too many bikes requested/ booked.
var match = Regex.Match(
responseState.ToUpper(),
RETURNBIKE_FAILURE_STATUS_MESSAGE_UPPERCASE);
if (match.Groups.Count != 5
|| !int.TryParse(match.Groups[2].ToString(), out int meters)
|| !int.TryParse(match.Groups[4].ToString(), out int stationNr))
{
exception = null;
return false;
}
exception = new NotAtStationException { Distance = meters, StationNr = stationNr };
return true;
}
/// <summary> Holds the maximum count of bikes allowed to reserve/ book.</summary>
public int Distance { get; private set; }
/// <summary> Holds the maximum count of bikes allowed to reserve/ book.</summary>
public int StationNr { get; private set; }
}
}

View file

@ -0,0 +1,15 @@
using TINK.Model.Repository.Response;
namespace TINK.Repository.Exception
{
public class ResponseException : System.Exception
{
private readonly ResponseBase _response;
public ResponseException(ResponseBase response, string message) : base(message)
{
_response = response;
}
public string Response => _response.response_text;
}
}

View file

@ -0,0 +1,10 @@
using TINK.Model.Repository.Response;
namespace TINK.Repository.Exception
{
public class ReturnBikeException : ResponseException
{
public ReturnBikeException(ReservationCancelReturnResponse response, string message) : base(response, message)
{ }
}
}

View file

@ -0,0 +1,24 @@
namespace TINK.Model.Repository.Exception
{
public class WebConnectFailureException : CommunicationException
{
/// <summary>
/// Returns a hint to fix communication problem.
/// </summary>
public static string GetHintToPossibleExceptionsReasons
{
get
{
return "Ist WLAN verfügbar/ Mobilfunknetz vefügbar und mobile Daten aktiviert / ... ?";
}
}
/// <summary>
/// Constructs a communication exeption object.
/// </summary>
/// <param name="p_strMessage"></param>
/// <param name="p_oException"></param>
public WebConnectFailureException(string p_strMessage, System.Exception p_oException) : base(p_strMessage, p_oException)
{
}
}
}

View file

@ -0,0 +1,42 @@
using System.Net;
namespace TINK.Model.Repository.Exception
{
public static class WebExceptionHelper
{
/// <summary> Gets if a exception is caused by an error connecting to copri (LAN or mobile data off/ not reachable, proxy, ...).</summary>
/// <param name="p_oException">Expection to check.</param>
/// <returns>True if exception if caused by an connection error. </returns>
public static bool GetIsConnectFailureException(this System.Exception p_oException)
{
var l_oException = p_oException as WebException;
if (l_oException == null)
{
return false;
}
return l_oException.Status == WebExceptionStatus.ConnectFailure // Happens if WLAN and mobile data is off/ Router denies internet access/ ...
|| l_oException.Status == WebExceptionStatus.NameResolutionFailure // Happens sometimes when not WLAN and no mobil connection are available (bad connection in lift).
|| l_oException.Status == WebExceptionStatus.ReceiveFailure; // Happened when modile was connected to WLAN
}
/// <summary> Gets if a exception is caused by clicking too fast.</summary>
/// <param name="p_oException">Expection to check.</param>
/// <returns>True if exception if caused by a fast click sequence. </returns>
public static bool GetIsForbiddenException(this System.Exception p_oException)
{
if (!(p_oException is WebException l_oException))
{
return false;
}
if (!(l_oException?.Response is HttpWebResponse l_oResponse))
{
return false;
}
return l_oException.Status == WebExceptionStatus.ProtocolError
&& l_oResponse.StatusCode == HttpStatusCode.Forbidden;
}
}
}

View file

@ -0,0 +1,14 @@
namespace TINK.Model.Repository.Exception
{
public class WebForbiddenException : CommunicationException
{
/// <summary>
/// Constructs a communication exeption object.
/// </summary>
/// <param name="p_strMessage"></param>
/// <param name="p_oException"></param>
public WebForbiddenException(string p_strMessage, System.Exception p_oException) : base($"{p_strMessage}\r\nSchnell getippt?\r\nBitte die App etwas langsamer bedienen...", p_oException)
{
}
}
}