/// <summary> /// Check whether a simple user currently exists with the details provided. /// </summary> /// <returns> If the simple user exists already, this method returns <see langword="true"/> </returns> public static bool SimpleUserIsRegistered(string gameId, string username, string email, string connectionId = "public") { if (string.IsNullOrEmpty(gameId)) { throw new ArgumentException("A game ID must be specified in order to use this method."); } if (string.IsNullOrEmpty(username) && string.IsNullOrEmpty(email)) { throw new ArgumentException("A username or email must be specified in order to use this method."); } var response = true; try { PlayerIO.Authenticate(gameId, connectionId, DictionaryEx.Create( ("checkusername", "true"), ("username", username), ("email", email) )); } catch (PlayerIOError error) { if (error.ErrorCode == ErrorCode.UnknownUser) { response = false; } } return(response); }
/// <summary> Connects to Player.IO using as the given user </summary> /// <param name="gameId"> The game ID of the game you wish to connect to. This value can be found in the admin panel </param> /// <param name="connectionId"> The ID of the connection, as given in the settings section of the admin panel. 'public' should be used as the default </param> /// <param name="authenticationArguments"> A dictionary of arguments for the given connection. </param> /// <param name="playerInsightSegments"> Custom segments for the user in PlayerInsight. </param> /// <param name="successCallback"> A callback called when successfully connected. </param> /// <param name="errorCallback"> A callback called instead of <paramref name="successCallback"/> when an error occurs during connection. </param> public static void Authenticate(string gameId, string connectionId, Dictionary <string, string> authenticationArguments = null, string[] playerInsightSegments = null, Callback <Client> successCallback = null, Callback <PlayerIOError> errorCallback = null) { var authenticationOutput = Channel.Request <AuthenticateArgs, AuthenticateOutput, PlayerIOError>(13, new AuthenticateArgs { GameId = gameId, ConnectionId = connectionId, AuthenticationArguments = Converter.Convert(authenticationArguments ?? new Dictionary <string, string>()), PlayerInsightSegments = playerInsightSegments?.ToList() ?? new List <string>(), ClientAPI = GetClientAPI(), ClientInfo = Converter.Convert(GetClientInfo()), PlayCodes = GetPlayCodes() }, errorCallback); if (authenticationOutput != null) { PlayerIO.ServerApiEndpoints = authenticationOutput.ApiServerHosts; PlayerIO.ServerApiSecurity = authenticationOutput.ApiSecurity; // TODO: Don't want to overwrite any custom user-set endpoint... PlayerIO.SetAPIEndpoint(PlayerIO.ServerApiEndpoints[0]); successCallback(new Client(Channel, gameId, authenticationOutput.GameFSRedirectMap, authenticationOutput.Token, authenticationOutput.UserId, authenticationOutput.ShowBranding, authenticationOutput.IsSocialNetworkUser, null)); } }
/// <summary> /// Authenticate with Facebook using the Access Token provided. /// </summary> public static Client FacebookConnect(string gameId, string accessToken, string connectionId = "public") { if (string.IsNullOrEmpty(gameId)) { throw new ArgumentException("A game ID must be specified in order to use this method."); } if (string.IsNullOrEmpty(accessToken)) { throw new ArgumentException("A Facebook access token must be specified in order to use this method."); } return(PlayerIO.Authenticate(gameId, connectionId, DictionaryEx.Create(("accessToken", accessToken)))); }
/// <summary> /// Authenticate with ArmorGames using the userId and token provided. /// </summary> public static Client ArmorGamesConnect(string gameId, string userId, string token, string connectionId = "public") { if (string.IsNullOrEmpty(gameId)) { throw new ArgumentException("A game ID must be specified in order to use this method."); } if (string.IsNullOrEmpty(userId)) { throw new ArgumentException("An ArmorGames userId must be specified in order to use this method."); } if (string.IsNullOrEmpty(token)) { throw new ArgumentException("An ArmorGames auth token must be specified in order to use this method."); } return(PlayerIO.Authenticate(gameId, connectionId, DictionaryEx.Create(("userId", userId), ("authToken", token)))); }
/// <summary> /// Authenticate with Steam using the Steam App ID and Steam Session Ticket provided. /// </summary> public static Client SteamConnect(string gameId, string appId, string sessionTicket, string connectionId = "public") { if (string.IsNullOrEmpty(gameId)) { throw new ArgumentException("A game ID must be specified in order to use this method."); } if (string.IsNullOrEmpty(appId)) { throw new ArgumentException("A Steam App ID must be specified in order to use this method."); } if (string.IsNullOrEmpty(sessionTicket)) { throw new ArgumentException("A Steam Session Ticket must be specified in order to use this method."); } return(PlayerIO.Authenticate(gameId, connectionId, DictionaryEx.Create(("steamSessionTicket", sessionTicket), ("steamAppId", appId)))); }
/// <summary>Connects to Player.IO using as the given user</summary> /// <param name="gameId">The game id of the game you wish to connect to. This value can be found in the admin panel</param> /// <param name="connectionId">The id of the connection, as given in the settings section of the admin panel. 'public' should be used as the default</param> /// <param name="authenticationArguments">A dictionary of arguments for the given connection.</param> /// <param name="playerInsightSegments">Custom segments for the user in PlayerInsight.</param> public static Client Authenticate(string gameId, string connectionId, Dictionary <string, string> authenticationArguments = null, string[] playerInsightSegments = null) { if (authenticationArguments?.ContainsKey("secureSimpleUserPasswordsOverHttp") == true && authenticationArguments["secureSimpleUserPasswordsOverHttp"] == "true") { var identifier = SimpleUserGetSecureLoginInfo(); authenticationArguments["password"] = PlayerIO.SimpleUserPasswordEncrypt(identifier.PublicKey, authenticationArguments["password"]); authenticationArguments["nonce"] = identifier.Nonce; } var identifier2 = Authenticate(gameId, connectionId, authenticationArguments ?? null, playerInsightSegments?.ToList() ?? null, PlayerIO.GetClientAPI(), PlayerIO.GetClientInfo(), PlayerIO.GetPlayCodes()); PlayerIO.ServerApiEndpoints = identifier2.ApiServerHosts; PlayerIO.ServerApiSecurity = identifier2.ApiSecurity; // TODO: Don't want to overwrite any custom user-set end-point... PlayerIO.SetAPIEndpoint(PlayerIO.ServerApiEndpoints[0]); return(new Client(Channel, gameId, identifier2.GameFSRedirectMap, identifier2.Token, identifier2.UserId, identifier2.ShowBranding, identifier2.IsSocialNetworkUser, null)); }
/// <summary> /// Change the email for a simple user with the provided username or email address, and valid password. /// </summary> /// <returns> If the change was successful, returns <see langword="true"/>. </returns> public static bool ChangeEmail(string gameId, string usernameOrEmail, string password, string newEmail, string connectionId = "public") { if (string.IsNullOrEmpty(gameId)) { throw new ArgumentException("A game ID must be specified in order to use this method."); } if (string.IsNullOrEmpty(usernameOrEmail)) { throw new ArgumentException("A username or email must be specified in order to use this method."); } if (string.IsNullOrEmpty(newEmail)) { throw new ArgumentException("You must specify a new email to use for this method."); } var response = false; try { PlayerIO.Authenticate(gameId, connectionId, DictionaryEx.Create( ("changeemail", "true"), ("username", usernameOrEmail.Contains("@") ? null : usernameOrEmail), ("email", usernameOrEmail.Contains("@") ? usernameOrEmail : null), ("password", password), ("newemail", newEmail) )); } catch (PlayerIOError error) { if (error.ErrorCode == ErrorCode.GeneralError && error.Message.ToLower().Contains("email address changed")) { response = true; } } return(response); }
/// <summary> /// Authenticate with SimpleUser connection type using the username or email address and password provided. /// </summary> public static Client SimpleConnect(string gameId, string usernameOrEmail, string password, string connectionId = "public") { if (string.IsNullOrEmpty(gameId)) { throw new ArgumentException("A game ID must be specified in order to use this method."); } if (string.IsNullOrEmpty(usernameOrEmail)) { throw new ArgumentException("A username or email must be specified in order to use this method."); } if (string.IsNullOrEmpty(password)) { throw new ArgumentException("A password must be specified in order to use this method."); } return(PlayerIO.Authenticate(gameId, connectionId, DictionaryEx.Create( ("username", usernameOrEmail.Contains("@") ? null : usernameOrEmail), ("email", usernameOrEmail.Contains("@") ? usernameOrEmail : null), ("password", password)))); }
/// <summary> /// Connects to a game based on Player.IO as the given user using basic authentiation. /// </summary> /// <param name="gameId"> /// The ID of the game you wish to connect to. This value can be found in the admin panel. /// </param> /// <param name="connectionId"> /// The ID of the connection, as given in the settings section of the admin panel. 'public' /// should be used as the default. /// </param> /// <param name="userId"> The ID of the user you wish to authenticate. </param> /// <param name="auth"> /// If the connection identified by ConnectionIdentifier only accepts authenticated requests: /// The auth value generated based on 'userId'. You can generate an auth value using the /// CalcAuth256() method. /// </param> public static Client Connect(string gameId, string connectionId, string userId, string auth) => PlayerIO.Authenticate(gameId, connectionId, DictionaryEx.Create(("userId", userId), ("auth", auth)));
/// <summary> /// Create a captcha image and key for the game the client is connected to, for use in registrations where the added security of captcha is required. /// </summary> /// <param name="width"> The width of the captcha image. </param> /// <param name="height"> The height of the captcha image. </param> public static SimpleCaptcha CreateCaptcha(this Client client, int width, int height) => PlayerIO.CreateCaptcha(client.GameId, width, height);
internal bool SimpleChangeEmail(string gameId, string connectionId, string connectionType, string currentUsernameOrEmail, string currentPassword, string newEmail, out string requestResponse) { var requestFinished = false; var changeSuccessful = false; var playerIOError = default(PlayerIOError); _channel.Request <AuthenticateArgs, NoArgsOrOutput, PlayerIOError>(13, new AuthenticateArgs { GameId = gameId, ClientAPI = PlayerIO.GetClientAPI(), ConnectionId = connectionId, AuthenticationArguments = new KeyValuePair[] { new KeyValuePair() { Key = connectionType, Value = currentUsernameOrEmail }, new KeyValuePair() { Key = "password", Value = currentPassword }, new KeyValuePair() { Key = "changeemail", Value = "true" }, new KeyValuePair() { Key = "newemail", Value = newEmail } } }, new Callback <PlayerIOError>((error) => { if (error.ErrorCode == ErrorCode.GeneralError && error.Message.ToLower().Contains("email address changed")) { changeSuccessful = true; } playerIOError = error; requestFinished = true; })); // this is really sloppy and could be improved, but it's quick and easy... // and the same description would generally apply to Player.IO as a whole :wink: // - atillabyte requestResponse = playerIOError?.Message ?? ""; var requestTimeout = 0; while (!requestFinished && ++requestTimeout <= 10000 / 100) { Thread.Sleep(100); } if (!requestFinished) { throw new Exception("The email change request timed out without returning a response."); } if (requestFinished && changeSuccessful) { return(true); } return(false); }
/// <summary> /// A tool to assist with exporting a Player.IO game. /// </summary> /// <param name="username"> The username of your Player.IO account </param> /// <param name="password"> The password of your Player.IO account </param> /// <param name="gameId"> The ID of the game to export. For example: tictactoe-vk6aoralf0yflzepwnhdvw </param> /// <param name="importFolder"> A directory containing the .ZIP BigDB export files given to you by Player.IO. </param> static async Task Main(string username, string password, string gameId, string importFolder) { if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(gameId) || string.IsNullOrEmpty(importFolder)) { Console.WriteLine("Unable to launch program. An argument may be missing or invalid. To view the required arguments, use -h."); return; } #region header Console.WriteLine(@" ╔═╗┬ ┌─┐┬ ┬┌─┐┬─┐ ╦╔═╗ ╠═╝│ ├─┤└┬┘├┤ ├┬┘ ║║ ║ ╩ ┴─┘┴ ┴ ┴ └─┘┴└─o╩╚═╝ ╔═╗─┐ ┬┌─┐┌─┐┬─┐┌┬┐ ╔╦╗┌─┐┌─┐┬ ║╣ ┌┴┬┘├─┘│ │├┬┘ │ ║ │ ││ ││ ╚═╝┴ └─┴ └─┘┴└─ ┴ ╩ └─┘└─┘┴─┘ ================================= by https://github.com/atillabyte/"); #endregion var log = new LoggerConfiguration() .WriteTo.Console() .CreateLogger(); DeveloperAccount developer; DeveloperGame game; Client client; if (!Directory.Exists(importFolder)) { log.Error("Unable to export game. The input directory specified does not exist."); return; } var archive_files = Directory.GetFiles(importFolder, "*.zip", SearchOption.TopDirectoryOnly).ToList(); if (archive_files.Count == 0) { log.Error("Unable to export game. The input directory specified does not contain any .ZIP export files."); return; } // attempt to login and select game try { developer = await AutoPIO.LoginAsync(username, password); log.Information("Signed in as: " + developer.Username + " (" + developer.Email + ")"); } catch { log.Error("Unable to export game. The login details provided were invalid."); return; } try { game = developer.Games.FirstOrDefault(game => game.GameId == gameId); log.Information("Selected game: " + game.Name + " (" + game.GameId + ")"); } catch { log.Error("Unable to export game. No game was found matching the specified gameId."); return; } // delete export connection if already exists while (true) { var connections = await game.LoadConnectionsAsync(); if (!connections.Any(c => c.Name == "export")) { break; } log.Information("An existing export connection was found - attempting to recreate it. This process should only take a few seconds."); await game.DeleteConnectionAsync(connections.First(c => c.Name == "export")); // wait a second (we don't want to spam) await Task.Delay(1000); } var shared_secret = CreateSharedSecret(username, password, game.GameId); var tables = (await game.LoadBigDBAsync()).Tables; log.Information("Now attempting to create export connection with shared_secret = " + shared_secret); await game.CreateConnectionAsync("export", "A connection with read access to all BigDB tables - used for exporting games.", DeveloperGame.AuthenticationMethod.BasicRequiresAuthentication, "Default", tables.Select(t => (t, true, false, false, false, false, false)).ToList(), shared_secret); // ensure the export connection exists before continuing while (true) { var connections = await game.LoadConnectionsAsync(); if (connections.Any(c => c.Name == "export")) { break; } log.Information("Waiting until we have confirmation that the export connection exists..."); Thread.Sleep(1000); // we don't want to spam. } log.Information("The export connection has been created."); // connect to the game and start export process. try { client = VenturePIO.Connect(game.GameId, "export", "user", VenturePIO.CalcAuth256("user", shared_secret)); } catch (Exception ex) { log.Error("Unable to export game. An error occurred while trying to authenticate with the export connection. Details: " + ex.Message); return; } log.Information("Connected to the game. The export process will now begin."); var export_tasks = new List <Task <List <DatabaseObject> > >(); var progress_bars = new ConcurrentBag <ProgressBar>(); foreach (var archive_file in archive_files) { var split = new FileInfo(archive_file).Name.Split('_'); var game_name = split[0]; var table = split[1]; var game_db = split[2]; // create output directory var output_directory = Path.Combine("exports", game_name, table, game_db); // ensure output directory exists. Directory.CreateDirectory(output_directory); // find all keys in table export as fujson. var archive_keys = GetDatabaseObjectKeysFromArchive(archive_file); var already_exported = Directory.GetDirectories(output_directory, "*", SearchOption.TopDirectoryOnly).Select(x => new DirectoryInfo(x).Name).ToList(); // add progress bar to the console var progress_bar = new ProgressBar(PbStyle.DoubleLine, archive_keys.Count); progress_bars.Add(progress_bar); progress_bar.Refresh(0, table); export_tasks.Add(ProcessJob(client, output_directory, table, archive_keys, progress_bar)); } Task.WaitAll(export_tasks.ToArray()); Console.WriteLine(); log.Information("The export process has completed successfully. You can now close the program."); Console.ReadLine(); }