namespace LOC.Website.Common.Models { using System; using System.Collections.Generic; using System.Data.Entity; using System.Linq; using Core; using Core.Data; using Core.Model.Account; using Core.Model.Sales; using Core.Model.Server.GameServer; using Core.Model.Server.PvpServer; using Core.Tokens; using Core.Tokens.Client; using Data; using LOC.Website.Common.Contexts; using System.Data.Entity.Infrastructure; public class AccountAdministrator : IAccountAdministrator { private readonly INautilusRepositoryFactory _repositoryFactory; private readonly IGameServerMonitor _gameServerMonitor; private readonly ILogger _logger; private readonly object _transactionLock = new object(); public AccountAdministrator(INautilusRepositoryFactory nautilusRepositoryFactory, ILogger logger) { _repositoryFactory = nautilusRepositoryFactory; _gameServerMonitor = GameServerMonitor.Instance; _logger = logger; } public List GetAccountNames() { using (var repository = _repositoryFactory.CreateRepository()) { return repository.GetAll().Select(x => x.Name).ToList(); } } public List GetAllAccountsMatching() { using (var repository = _repositoryFactory.CreateRepository()) { return repository.GetAll().Include(x => x.Rank).ToList(); } } public List GetAllAccountsMatching(string name) { using (var repository = _repositoryFactory.CreateRepository()) { return repository.GetAll().Where(c => c.Name == name).Include(x => x.Rank).ToList(); } } public List GetAllAccountNamesMatching(string name) { using (var repository = _repositoryFactory.CreateRepository()) { return repository.GetAll().Where(c => c.Name == name).Select(y => y.Name).ToList(); } } public Account Login(LoginRequestToken loginToken) { using (var repository = _repositoryFactory.CreateRepository()) { var account = repository.Where(x => x.Uuid == loginToken.Uuid).FirstOrDefault() ?? CreateAccount(loginToken, repository); account.LoadNavigationProperties(repository.Context); account.LastLogin = DateTime.Now.Ticks; // Expire punishments if (account.Punishments != null) { foreach (var expiredPunishment in account.Punishments.Where(x => x.Active && (x.Duration - 0d) > 0 && TimeUtil.GetCurrentMilliseconds() > (x.Time + (x.Duration * 3600000)))) { expiredPunishment.Active = false; } } // Insert UUID if not there if (String.IsNullOrEmpty(account.Uuid) && !String.IsNullOrEmpty(loginToken.Uuid)) { account.Uuid = loginToken.Uuid; } // Update account name if changed if (!String.Equals(account.Name, loginToken.Name)) { account.Name = loginToken.Name; } // Expire ranks if ((account.Rank.Name == "ULTRA") && !account.RankPerm && DateTime.Now.CompareTo(account.RankExpire) >= 0) { account.Rank = repository.Where(x => x.Name == "ALL").First(); repository.Attach(account.Rank); } repository.CommitChanges(); return account; } } public void Logout(string name) { using (var repository = _repositoryFactory.CreateRepository()) { var account = GetAccountByName(name, repository); if (account.Logins.Any()) { account.LastLogin = account.Logins.OrderBy(x => x.Time).Last().Time; account.TotalPlayingTime += DateTime.Now.Subtract(TimeSpan.FromTicks(account.LastLogin)).Ticks; } repository.CommitChanges(); _gameServerMonitor.PlayerLoggedOut(account); } } public Account GetAccountByName(string name) { using (var repository = _repositoryFactory.CreateRepository()) { return GetAccountByName(name, repository); } } public Account GetAccountById(int id) { using (var repository = _repositoryFactory.CreateRepository()) { return GetAccountByName(repository.GetAll().First(x => x.AccountId == id).Name, repository); } } public Account CreateAccount(string name) { using (var repository = _repositoryFactory.CreateRepository()) { var account = repository.Add(new Account { Gems = 1200, Coins = 0, Name = name, Rank = repository.Where(x => x.RankId == 1).First(), LastVote = DateTime.Today.Subtract(TimeSpan.FromDays(5)), RankExpire = DateTime.Now }); repository.CommitChanges(); return account; } } public void UpdateAccountUUIDs(List tokens) { try { using (var repository = _repositoryFactory.CreateRepository()) { foreach (AccountNameToken token in tokens) { var account = GetAccountByName(token.Name); account.Uuid = token.UUID; repository.Context.Database.ExecuteSqlCommand("UPDATE dbo.Accounts SET Uuid = {0} WHERE Name = {1}", token.UUID, token.Name); } repository.CommitChanges(); } } catch (Exception exception) { _logger.Log("Error", exception.Message); } } public List GetAccounts(AccountBatchToken token) { using (var repository = _repositoryFactory.CreateRepository()) { return repository.GetAll().OrderBy(x => x.AccountId).Skip(token.Start).Take(token.End - token.Start).Select(x => new AccountNameToken { Name = x.Name }).ToList(); } } public bool GemReward(GemRewardToken token) { using (var repository = _repositoryFactory.CreateRepository()) { var account = repository.Where(x => x.Name == token.Name).FirstOrDefault(); account.LoadNavigationProperties(repository.Context); if (account == null) return false; account.Gems += token.Amount; if (!token.Source.Contains("Earned") && !token.Source.Contains("Tutorial") && !token.Source.Contains("Parkour")) { var gemTransaction = new GemTransaction { Source = token.Source, Account = account, Amount = token.Amount, Date = (long)TimeUtil.GetCurrentMilliseconds() }; repository.Add(gemTransaction); } repository.Edit(account); repository.CommitChanges(); } return true; } public bool CoinReward(GemRewardToken token) { using (var repository = _repositoryFactory.CreateRepository()) { var account = repository.Where(x => x.Name == token.Name).FirstOrDefault(); account.LoadNavigationProperties(repository.Context); if (account == null) return false; account.Coins += token.Amount; if (!token.Source.Contains("Earned") && !token.Source.Contains("Tutorial") && !token.Source.Contains("Parkour")) { var coinTransaction = new CoinTransaction { Source = token.Source, Account = account, Amount = token.Amount, Date = (long)TimeUtil.GetCurrentMilliseconds() }; repository.Add(coinTransaction); } repository.Edit(account); repository.CommitChanges(); } return true; } public void AddTask(UpdateTaskToken token) { using (var repository = _repositoryFactory.CreateRepository()) { var account = repository.Where(x => x.Name == token.Name).Include(x => x.Tasks).FirstOrDefault(); if (account != null) { if (account.Tasks == null) account.Tasks = new List(); var task = new GameTask { Account = account, TaskName = token.NewTaskCompleted, }; account.Tasks.Add(task); repository.Edit(account); repository.CommitChanges(); } } } public PunishmentResponse Punish(PunishToken punish) { using (var repository = _repositoryFactory.CreateRepository()) { var account = repository.Where(x => x.Name == punish.Target).Include(x => x.Rank).FirstOrDefault(); if (account == null) return PunishmentResponse.AccountDoesNotExist; if (!String.Equals(punish.Admin, "Mineplex Enjin Server")) { var punisher = repository.Where(x => x.Name == punish.Admin).Include(x => x.Rank).FirstOrDefault(); if (punisher == null) return PunishmentResponse.NotPunished; } var punishment = new Punishment { UserId = account.AccountId, Admin = punish.Admin, Category = punish.Category, Sentence = punish.Sentence, Time = (long)TimeUtil.GetCurrentMilliseconds(), Reason = punish.Reason, Duration = punish.Duration, Severity = punish.Severity, Active = true }; if (account.Punishments == null) account.Punishments = new List(); account.Punishments.Add(punishment); repository.Edit(account); repository.CommitChanges(); } return PunishmentResponse.Punished; } public PunishmentResponse RemovePunishment(RemovePunishmentToken token) { using (var repository = _repositoryFactory.CreateRepository()) { var account = repository.Where(x => x.Name == token.Target).Include(x => x.Punishments).FirstOrDefault(); if (account == null) return PunishmentResponse.AccountDoesNotExist; if (account.Punishments == null || account.Punishments.Count == 0) return PunishmentResponse.NotPunished; var activePunishment = account.Punishments.FirstOrDefault(x => x.PunishmentId == token.PunishmentId && x.Active); if (activePunishment == null) return PunishmentResponse.NotPunished; var punishment = repository.Where(x => x.UserId == account.AccountId && x.PunishmentId == token.PunishmentId && x.Active).First(); punishment.Active = false; punishment.Removed = true; punishment.RemoveAdmin = token.Admin; punishment.RemoveTime = (long)TimeUtil.GetCurrentMilliseconds(); punishment.RemoveReason = token.Reason; repository.Edit(punishment); repository.CommitChanges(); } return PunishmentResponse.PunishmentRemoved; } public string PurchaseGameSalesPackage(PurchaseToken token) { lock (_transactionLock) { try { using (var repository = _repositoryFactory.CreateRepository()) { var account = repository.Where(x => x.Name == token.AccountName) .Include(x => x.PvpTransactions) .First(); var salesPackage = repository.Where(x => x.GameSalesPackageId == token.SalesPackageId) .FirstOrDefault(); if (account == null || salesPackage == null) return TransactionResponse.Failed.ToString(); if (account.Gems < salesPackage.Gems) return TransactionResponse.InsufficientFunds.ToString(); var accountTransaction = new GameTransaction { Account = account, GameSalesPackageId = salesPackage.GameSalesPackageId, Gems = salesPackage.Gems, }; repository.Attach(account); repository.Edit(account); if (account.PvpTransactions == null) account.PvpTransactions = new List {accountTransaction}; else { account.PvpTransactions.Add(accountTransaction); } account.Gems -= salesPackage.Gems; repository.CommitChanges(); return TransactionResponse.Success.ToString(); } } catch (Exception exception) { return TransactionResponse.Failed.ToString() + ":" + exception.Message; } } } public bool AccountExists(string name) { using (var repository = _repositoryFactory.CreateRepository()) { return repository.Any(x => x.Name == name); } } public void SaveCustomBuild(CustomBuildToken token) { using (var repository = _repositoryFactory.CreateRepository()) { var account = repository.Where(x => x.Name == token.PlayerName).Include(x => x.CustomBuilds).First(); var customBuild = account.CustomBuilds.FirstOrDefault( x => String.Equals(x.PvpClass, token.PvpClass) && x.CustomBuildNumber == token.CustomBuildNumber); if (customBuild == null) { customBuild = repository.Add(token.GetCustomBuild()); account.CustomBuilds.Add(customBuild); } else { token.UpdateCustomBuild(customBuild); repository.Edit(customBuild); } if (customBuild.Active) { foreach ( var otherClassBuild in account.CustomBuilds.Where( x => String.Equals(x.PvpClass, token.PvpClass) && x.CustomBuildNumber != customBuild.CustomBuildNumber) .ToList()) { otherClassBuild.Active = false; repository.Edit(otherClassBuild); } } repository.Edit(account); repository.CommitChanges(); } } public void Ignore(string accountName, string ignoredPlayer) { using (var repository = _repositoryFactory.CreateRepository()) { var account = repository.Where(x => x.Name == accountName).First(); account.IgnoredPlayers.Add(ignoredPlayer); repository.CommitChanges(); } } public void RemoveIgnore(string accountName, string ignoredPlayer) { using (var repository = _repositoryFactory.CreateRepository()) { var account = repository.Where(x => x.Name == accountName).First(); account.IgnoredPlayers.Remove(ignoredPlayer); repository.CommitChanges(); } } public string PurchaseUnknownSalesPackage(UnknownPurchaseToken token) { lock (_transactionLock) { try { using (var repository = _repositoryFactory.CreateRepository()) { var account = repository.Where(x => x.Name == token.AccountName) .Include(x => x.AccountTransactions) .First(); if (account == null) return TransactionResponse.Failed.ToString(); if (token.CoinPurchase ? account.Coins < token.Cost : account.Gems < token.Cost) return TransactionResponse.InsufficientFunds.ToString(); var accountTransaction = new AccountTransaction { Account = account, SalesPackageName = token.SalesPackageName, Date = (long)TimeUtil.GetCurrentMilliseconds(), Gems = token.CoinPurchase ? 0 : token.Cost, Coins = token.CoinPurchase ? token.Cost : 0 }; repository.Attach(account); repository.Edit(account); if (account.AccountTransactions == null) account.AccountTransactions = new List { accountTransaction }; else { account.AccountTransactions.Add(accountTransaction); } if (token.CoinPurchase) account.Coins -= token.Cost; else account.Gems -= token.Cost; repository.CommitChanges(); return TransactionResponse.Success.ToString(); } } catch (Exception exception) { return TransactionResponse.Failed.ToString() + ":" + exception.Message; } } } public string UpdateRank(RankUpdateToken token) { using (var repository = _repositoryFactory.CreateRepository()) { var account = repository.Where(x => String.Equals(x.Name, token.Name)).Include(x => x.Rank).FirstOrDefault(); var rank = repository.Where(x => String.Equals(x.Name, token.Rank)).FirstOrDefault(); if (account == null) return "ALL"; if (account.Rank.Name == "ADMIN" || account.Rank.Name == "OWNER" || account.Rank.Name == "DEVELOPER" || account.Rank.Name == "YOUTUBE") return account.Rank.Name; if (rank == null) return account.Rank.ToString(); account.Rank = rank; account.RankExpire = DateTime.Now.AddMonths(1); account.RankPerm = token.Perm; repository.CommitChanges(); return rank.Name.ToString(); } } public void RemoveBan(RemovePunishmentToken token) { using (var repository = _repositoryFactory.CreateRepository()) { var account = repository.Where(x => x.Name == token.Target).Include(x => x.Punishments).FirstOrDefault(); if (account == null) return; if (account.Punishments == null || account.Punishments.Count == 0) return; var activePunishments = account.Punishments.Where(x => x.Active); if (!activePunishments.Any()) return; foreach (Punishment punishment in activePunishments) { punishment.Active = false; punishment.Removed = true; punishment.RemoveAdmin = token.Admin; punishment.RemoveTime = DateTime.Now.Ticks; punishment.RemoveReason = token.Reason; repository.Edit(punishment); } repository.CommitChanges(); } } public void ApplySalesPackage(SalesPackage salesPackage, int accountId, decimal gross, decimal fee) { using (var repository = _repositoryFactory.CreateRepository()) { var account = repository.Where(x => x.AccountId == accountId).Include(x => x.Transactions).First(); var accountTransaction = new Transaction {Account = account, SalesPackage = salesPackage, Fee = fee, Profit = (gross - fee), Time = DateTime.Now}; repository.Attach(salesPackage); repository.Attach(account); repository.Edit(account); if (account.Transactions == null) account.Transactions = new List(); account.Transactions.Add(accountTransaction); account.Gems += salesPackage.Gems; account.Donated = true; account.RankPerm = salesPackage.RankPerm; if (salesPackage.Rank.RankId != 1 && !salesPackage.RankPerm) { account.Rank = salesPackage.Rank; account.RankExpire = DateTime.Now.AddDays(salesPackage.Length); } repository.CommitChanges(); } } protected Account GetAccountByName(string name, IRepository repository) { var account = repository.Where(x => x.Name == name).FirstOrDefault(); account.LoadNavigationProperties(repository.Context); return account; } protected Account CreateAccount(LoginRequestToken loginToken, IRepository repository) { var newAccount = new Account { Name = loginToken.Name, Uuid = loginToken.Uuid, Rank = repository.Where(x => x.RankId == 1).First(), Gems = 0, Coins = 0, Transactions = new List(), PvpTransactions = new List(), IpAddresses = new List(), MacAddresses = new List(), Logins = new List(), CustomBuilds = new List(), LastVote = DateTime.Today.Subtract(TimeSpan.FromDays(5)), RankExpire = DateTime.Now }; newAccount = repository.Add(newAccount); repository.CommitChanges(); newAccount = repository.Where(x => x.AccountId == newAccount.AccountId) .Include(x => x.Rank) .Include(x => x.Punishments) .Include(x => x.Clan) .Include(x => x.ClanRole) .Include(x => x.CustomBuilds) .Include(x => x.FishCatches) .Include(x => x.PvpTransactions) .Include(x => x.Pets) .First(); return newAccount; } protected LoginAddress CreateIpAddress(LoginRequestToken loginToken, IRepository repository) { var newLoginAddress = new LoginAddress { Address = loginToken.IpAddress }; newLoginAddress = repository.Add(newLoginAddress); repository.CommitChanges(); return newLoginAddress; } protected void CreateMacAddress(LoginRequestToken loginToken, IRepository repository) { var newMacAddress = new MacAddress { Address = loginToken.MacAddress, Accounts = new List() }; repository.Add(newMacAddress); repository.CommitChanges(); } public ClientToken GetAccountByUUID(string uuid) { using (var repository = _repositoryFactory.CreateRepository()) { var account = repository.Where(x => x.Uuid == uuid).FirstOrDefault(); if (account == null) return null; account.LoadNavigationProperties(repository.Context); ClientToken clientToken = null; clientToken = new ClientToken(account); foreach (var trans in repository.Where(x => x.Account.AccountId == account.AccountId).ToList()) { clientToken.DonorToken.CoinRewards.Add(new CoinTransactionToken(trans)); } return clientToken; } } } }