using UnityEditor;
using UnityEngine.Networking;
using System.Text.RegularExpressions;
#if UNITY_EDITOR
using System;
using UnityEngine;
using System.Collections.Generic;
namespace Bolt.Utils
{
///
/// Creates a instance of the Account Service to register Photon Cloud accounts.
///
public class AccountService
{
private const string ServiceUrl = "https://partner.photonengine.com/api/Unity/User/RegisterEx";
private readonly Dictionary requestHeaders = new Dictionary
{
{"Content-Type", "application/json"},
{"x-functions-key", "VQ920wVUieLHT9c3v1ZCbytaLXpXbktUztKb3iYLCdiRKjUagcl6eg=="}
};
///
/// Attempts to create a Photon Cloud Account asynchronously.
/// Once your callback is called, check ReturnCode, Message and AppId to get the result of this attempt.
///
/// Email of the account.
/// Defines which type of Photon-service is being requested.
/// Called when the result is available.
public bool RegisterByEmail(string email, string serviceTypes, Action callback = null,
Action errorCallback = null)
{
if (IsValidEmail(email) == false)
{
Debug.LogErrorFormat("Email \"{0}\" is not valid", email);
return false;
}
if (string.IsNullOrEmpty(serviceTypes))
{
Debug.LogError("serviceTypes string is null or empty");
return false;
}
AccountServiceRequest req = new AccountServiceRequest();
req.Email = email;
req.ServiceTypes = serviceTypes;
return this.RegisterByEmail(req, callback, errorCallback);
}
public bool RegisterByEmail(string email, List serviceTypes,
Action callback = null, Action errorCallback = null)
{
if (serviceTypes == null || serviceTypes.Count == 0)
{
Debug.LogError("serviceTypes list is null or empty");
return false;
}
return this.RegisterByEmail(email, GetServiceTypesFromList(serviceTypes), callback, errorCallback);
}
public bool RegisterByEmail(AccountServiceRequest request, Action callback = null,
Action errorCallback = null)
{
if (request == null)
{
Debug.LogError("Registration request is null");
return false;
}
StartCoroutine(
HttpPost(GetUrlWithQueryStringEscaped(request),
requestHeaders,
null,
s =>
{
if (string.IsNullOrEmpty(s))
{
if (errorCallback != null)
{
errorCallback(
"Server's response was empty. Please register through account website during this service interruption.");
}
}
else
{
AccountServiceResponse ase = this.ParseResult(s);
if (ase == null)
{
if (errorCallback != null)
{
errorCallback(
"Error parsing registration response. Please try registering from account website");
}
}
else if (callback != null)
{
callback(ase);
}
}
},
e =>
{
if (errorCallback != null)
{
errorCallback(e);
}
})
);
return true;
}
private static string GetUrlWithQueryStringEscaped(AccountServiceRequest request)
{
string email = UnityEngine.Networking.UnityWebRequest.EscapeURL(request.Email);
string st = UnityEngine.Networking.UnityWebRequest.EscapeURL(request.ServiceTypes);
return string.Format("{0}?email={1}&st={2}", ServiceUrl, email, st);
}
///
/// Reads the Json response and applies it to local properties.
///
///
private AccountServiceResponse ParseResult(string result)
{
try
{
AccountServiceResponse res = JsonUtility.FromJson(result);
// Unity's JsonUtility does not support deserializing Dictionary, we manually parse it, dirty & ugly af, better then using a 3rd party lib
if (res.ReturnCode == AccountServiceReturnCodes.Success)
{
string[] parts = result.Split(new[] {"\"ApplicationIds\":{"},
StringSplitOptions.RemoveEmptyEntries);
parts = parts[1].Split('}');
string applicationIds = parts[0];
if (!string.IsNullOrEmpty(applicationIds))
{
parts = applicationIds.Split(new[] {',', '"', ':'}, StringSplitOptions.RemoveEmptyEntries);
res.ApplicationIds = new Dictionary(parts.Length / 2);
for (int i = 0; i < parts.Length; i = i + 2)
{
res.ApplicationIds.Add(parts[i], parts[i + 1]);
}
}
else
{
Debug.LogError(
"The server did not return any AppId, ApplicationIds was empty in the response.");
return null;
}
}
return res;
}
catch (Exception ex) // probably JSON parsing exception, check if returned string is valid JSON
{
Debug.LogException(ex);
return null;
}
}
private static string GetServiceTypesFromList(List appTypes)
{
if (appTypes != null)
{
string serviceTypes = string.Empty;
if (appTypes.Count > 0)
{
serviceTypes = ((int) appTypes[0]).ToString();
for (int i = 1; i < appTypes.Count; i++)
{
int appType = (int) appTypes[i];
serviceTypes = string.Format("{0},{1}", serviceTypes, appType);
}
}
return serviceTypes;
}
return null;
}
// RFC2822 compliant matching 99.9% of all email addresses in actual use today
// according to http://www.regular-expressions.info/email.html [22.02.2012]
private static Regex reg = new Regex(
"^((?>[a-zA-Z\\d!#$%&'*+\\-/=?^_{|}~]+\\x20*|\"((?=[\\x01-\\x7f])[^\"\\]|\\[\\x01-\\x7f])*\"\\x20*)*(?<))?((?!\\.)(?>\\.?[a-zA-Z\\d!#$%&'*+\\-/=?^_{|}~]+)+|\"((?=[\\x01-\\x7f])[^\"\\]|\\[\\x01-\\x7f])*\")@(((?!-)[a-zA-Z\\d\\-]+(?)$",
RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
public static bool IsValidEmail(string mailAddress)
{
if (string.IsNullOrEmpty(mailAddress))
{
return false;
}
var result = reg.Match(mailAddress);
return result.Success;
}
//https://forum.unity.com/threads/using-unitywebrequest-in-editor-tools.397466/#post-4485181
private static void StartCoroutine(System.Collections.IEnumerator update)
{
EditorApplication.CallbackFunction closureCallback = null;
closureCallback = () =>
{
try
{
if (update.MoveNext() == false)
{
EditorApplication.update -= closureCallback;
}
}
catch (Exception ex)
{
Debug.LogException(ex);
EditorApplication.update -= closureCallback;
}
};
EditorApplication.update += closureCallback;
}
private static System.Collections.IEnumerator HttpPost(string url, Dictionary headers,
byte[] payload, Action successCallback, Action errorCallback)
{
using (UnityWebRequest w = new UnityWebRequest(url, "POST"))
{
if (payload != null)
{
w.uploadHandler = new UploadHandlerRaw(payload);
}
w.downloadHandler = new DownloadHandlerBuffer();
if (headers != null)
{
foreach (var header in headers)
{
w.SetRequestHeader(header.Key, header.Value);
}
}
#if UNITY_2017_2_OR_NEWER
yield return w.SendWebRequest();
#else
yield return w.Send();
#endif
while (w.isDone == false)
yield return null;
#if UNITY_2017_1_OR_NEWER
if (w.isNetworkError || w.isHttpError)
#else
if (w.isError)
#endif
{
if (errorCallback != null)
{
errorCallback(w.error);
}
}
else
{
if (successCallback != null)
{
successCallback(w.downloadHandler.text);
}
}
}
}
}
[Serializable]
public class AccountServiceResponse
{
public int ReturnCode;
public string Message;
public Dictionary
ApplicationIds; // Unity's JsonUtility does not support deserializing Dictionary
}
[Serializable]
public class AccountServiceRequest
{
public string Email;
public string ServiceTypes;
}
public class AccountServiceReturnCodes
{
public static int Success = 0;
public static int EmailAlreadyRegistered = 8;
public static int InvalidParameters = 12;
public static readonly Dictionary ReturnCodes = new Dictionary()
{
{Success, "Success"},
{EmailAlreadyRegistered, "Email Already Registered"},
{InvalidParameters, "Invalid Parameters"}
};
}
public enum ServiceTypes
{
Realtime = 0,
Turnbased = 1,
Chat = 2,
Voice = 3,
TrueSync = 4,
Pun = 5,
Thunder = 6,
Bolt = 20
}
}
#endif