Version 3.0.381

This commit is contained in:
Anja 2024-04-09 12:53:23 +02:00
parent f963c0a219
commit 3a363acf3a
1525 changed files with 60589 additions and 125098 deletions

View file

@ -0,0 +1,62 @@
namespace ShareeBike.Repository.Exception
{
/// <summary>
/// Is fired with request used a cookie which is not defined.
/// Reasons for cookie to be not defined might be
/// - user used more that 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)
{
}
/// <summary>
/// Gets whether authcookie is defined or not.
/// </summary>
/// <param name="reponse">Response to check</param>
/// <param name="actionText">Text holding context in which authcookie is checked.</param>
/// <param name="exception">Exception thrown if cookie is not defined.</param>
/// <returns></returns>
public static bool IsAuthcookieNotDefined(
Response.ResponseBase reponse,
string actionText,
out AuthcookieNotDefinedException exception)
{
if (reponse == null || reponse.response_state == null)
{
// Empty response or response without response state is no authcookie not defined exception.
exception = null;
return false;
}
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,17 @@
using ShareeBike.MultilingualResources;
namespace ShareeBike.Repository.Exception
{
public class InvalidAuthorizationResponseException : InvalidResponseException<Response.ResponseBase>
{
/// <summary>Constructs a authorization exceptions. </summary>
/// <param name="mail">Mail address to create a detailed error message.</param>
public InvalidAuthorizationResponseException(string mail, Response.ResponseBase response) :
base(string.Format(AppResources.ErrorAccountInvalidAuthorization, mail), response)
{
}
/// <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 ShareeBike.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 ShareeBike.Repository.Exception
{
public class CallNotRequiredException : System.Exception
{
}
}

View file

@ -0,0 +1,28 @@
namespace ShareeBike.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,13 @@
using ShareeBike.MultilingualResources;
namespace ShareeBike.Repository.Exception
{
public class DeserializationException : CommunicationException
{
public DeserializationException(System.Exception ex) : base(
string.Format(AppResources.ErrorDeserializingServerResponse, ex.Message),
ex)
{
}
}
}

View file

@ -0,0 +1,34 @@
namespace ShareeBike.Repository.Exception
{
public class InvalidResponseException<T> : InvalidResponseException
{
/// <summary> Constructs an invalid response Exception. </summary>
/// <param name="actionWhichFailed">Describes the action which failed.</param>
/// <param name="response">Response from copri.</param>
public InvalidResponseException(string actionWhichFailed, T response)
: base(string.Format(
"{0}{1}",
actionWhichFailed,
response == null ? string.Format(" Response of type {0} is null.", typeof(T).Name.ToString()) : string.Empty))
{
Response = response;
}
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="message">Exception.</param>
public InvalidResponseException(string message) : base(message)
{ }
}
}

View file

@ -0,0 +1,27 @@

namespace ShareeBike.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,52 @@
using System.Text.RegularExpressions;
namespace ShareeBike.Repository.Exception
{
public class NotAtStationException : InvalidResponseException
{
public const string RETURNBIKE_FAILURE_STATUS_MESSAGE_CODE = "FAILURE 2178:";
/// <summary> COPRI response status regular expression to extract detail information. </summary>
public const string RETURNBIKE_FAILURE_STATUS_MESSAGE_UPPERCASE = "(BIKE [A-Za-z0-9_]+ OUT OF GEO FENCING\\. )([0-9]+)( METER DISTANCE TO NEXT STATION )([A-Za-z0-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 response = responseState.Trim().ToUpper();
if (!response.StartsWith(RETURNBIKE_FAILURE_STATUS_MESSAGE_CODE))
{
exception = null;
return false;
}
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))
{
exception = new NotAtStationException();
return true;
}
exception = new NotAtStationException {
Distance = meters,
StationNr = match.Groups[4].ToString()
};
return true;
}
/// <summary> Holds the distance to next station.</summary>
public int? Distance { get; private set; } = null;
/// <summary> Holds the id of next station.</summary>
public string StationNr { get; private set; } = string.Empty;
}
}

View file

@ -0,0 +1,15 @@
using ShareeBike.Repository.Response;
namespace ShareeBike.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 ShareeBike.Repository.Response;
namespace ShareeBike.Repository.Exception
{
public class ReturnBikeException : ResponseException
{
public ReturnBikeException(BikesReservedOccupiedResponse response, string message) : base(response, message)
{ }
}
}

View file

@ -0,0 +1,8 @@
namespace ShareeBike.Repository.Exception
{
public class UnsupportedCopriVersionDetectedException : System.Exception
{
public UnsupportedCopriVersionDetectedException() : base("Unsupported app version detected.")
{ }
}
}

View file

@ -0,0 +1,16 @@
using ShareeBike.MultilingualResources;
namespace ShareeBike.Repository.Exception
{
public class WebConnectFailureException : CommunicationException
{
/// <summary>
/// Constructs a communication exception object.
/// </summary>
/// <param name="message"></param>
/// <param name="exception"></param>
public WebConnectFailureException(string message, System.Exception exception) : base(message, exception)
{
}
}
}

View file

@ -0,0 +1,53 @@
using System.Net;
namespace ShareeBike.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="exception">Expection to check.</param>
/// <returns>True if exception if caused by an connection error. </returns>
public static bool GetIsConnectFailureException(this System.Exception exception)
{
#if !USCSHARP9
if (!(exception is WebException webException))
#else
if (exception is not WebException webException)
#endif
{
return false;
}
return webException.Status == WebExceptionStatus.ConnectFailure // Happens if WLAN and mobile data is off/ Router denies internet access/ ...
|| webException.Status == WebExceptionStatus.NameResolutionFailure // Happens sometimes when not WLAN and no mobil connection are available (bad connection in lift).
|| webException.Status == WebExceptionStatus.ReceiveFailure; // Happened when mobile was connected to WLAN
}
/// <summary> Gets if a exception is caused by clicking too fast.</summary>
/// <param name="exception">Expection to check.</param>
/// <returns>True if exception if caused by a fast click sequence. </returns>
public static bool GetIsForbiddenException(this System.Exception exception)
{
#if !USCSHARP9
if (!(exception is WebException webException))
#else
if (exception is not WebException webException)
#endif
{
return false;
}
#if !USCSHARP9
if (!(webException?.Response is HttpWebResponse response))
#else
if (webException?.Response is not HttpWebResponse response)
#endif
{
return false;
}
return webException.Status == WebExceptionStatus.ProtocolError
&& response.StatusCode == HttpStatusCode.Forbidden;
}
}
}

View file

@ -0,0 +1,14 @@
namespace ShareeBike.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)
{
}
}
}