static void AddPwPlayer(BattleContext context, string matchUser, BalanceTeamsResult res, int allyID) { PlayerTeam player = context.Players.FirstOrDefault(x => x.Name == matchUser); if (player == null) { player = new PlayerTeam() { Name = matchUser }; User us; if (Global.Nightwatch.Tas.GetExistingUser(matchUser, out us)) { player.LobbyID = us.AccountID; } else { var db = new ZkDataContext(); var acc = Account.AccountByName(db, matchUser); if (acc != null) { player.LobbyID = acc.AccountID; } } } res.Players.Add(new PlayerTeam { AllyID = allyID, IsSpectator = false, Name = player.Name, LobbyID = player.LobbyID, TeamID = player.TeamID }); }
private async Task JoinPlanet(string name, int planetId) { try { var user = server.ConnectedUsers.Get(name)?.User; if (user != null) { var faction = factions.FirstOrDefault(x => x.Shortcut == user.Faction); if (faction == null) { var db = new ZkDataContext(); // this is a fallback, should not be needed var acc = Account.AccountByName(db, name); faction = factions.FirstOrDefault(x => x.FactionID == acc.FactionID); } if (faction == AttackingFaction) { await JoinPlanetAttack(planetId, name); } else if ((Challenge != null) && GetDefendingFactions(Challenge).Contains(faction)) { await JoinPlanetDefense(planetId, name); } } } catch (Exception ex) { Trace.TraceError("PlanetWars {0} {1} {2} : {3}", nameof(JoinPlanet), name, planetId, ex); } }
void MvcApplication_PostAuthenticateRequest(object sender, EventArgs e) { if (DateTime.UtcNow.Subtract(lastPollCheck).TotalMinutes > 15) { PollController.AutoClosePolls(); lastPollCheck = DateTime.UtcNow; } Account acc = null; if (Request[GlobalConst.ASmallCakeCookieName] != null) { var testAcc = Account.AccountByName(new ZkDataContext(), Request[GlobalConst.ASmallCakeLoginCookieName]); if (testAcc != null) { if (AuthTools.ValidateSiteAuthToken(testAcc.Name, testAcc.Password, Request[GlobalConst.ASmallCakeCookieName])) { acc = testAcc; } } } if (acc == null) { if (Request[GlobalConst.LoginCookieName] != null) { acc = AuthServiceClient.VerifyAccountHashed(Request[GlobalConst.LoginCookieName], Request[GlobalConst.PasswordHashCookieName]); } } if (acc != null) { var ip = GetUserIP(); using (var db = new ZkDataContext()) { var penalty = Punishment.GetActivePunishment(acc.AccountID, ip, null, x => x.BanSite, db); if (penalty != null) { Response.Write(string.Format("You are banned! (IP match to account {0})\n", penalty.AccountByAccountID.Name)); Response.Write(string.Format("Ban expires: {0} UTC\n", penalty.BanExpires)); Response.Write(string.Format("Reason: {0}\n", penalty.Reason)); Response.End(); } else { HttpContext.Current.User = acc; // todo replace with safer permanent cookie Response.SetCookie(new HttpCookie(GlobalConst.LoginCookieName, acc.Name) { Expires = DateTime.Now.AddMonths(12) }); Response.SetCookie(new HttpCookie(GlobalConst.PasswordHashCookieName, acc.Password) { Expires = DateTime.Now.AddMonths(12) }); } } } }
public void NotifyMissionRun(string login, string missionName) { missionName = Mission.GetNameWithoutVersion(missionName); using (var db = new ZkDataContext()){ db.Missions.Single(x => x.Name == missionName).MissionRunCount++; Account.AccountByName(db, login).MissionRunCount++; db.SubmitChanges(); } }
private void MvcApplication_PostAuthenticateRequest(object sender, EventArgs e) { if (DateTime.UtcNow.Subtract(lastPollCheck).TotalMinutes > 60) { PollController.AutoClosePolls(); // this is silly here, should be a seaprate timer/thread lastPollCheck = DateTime.UtcNow; } Account acc = null; if (FormsAuthentication.IsEnabled && User.Identity.IsAuthenticated) { acc = Account.AccountByName(new ZkDataContext(), User.Identity.Name); } else if (Request[GlobalConst.SessionTokenVariable] != null) { int id = 0; if (Global.Server?.SessionTokens.TryRemove(Request[GlobalConst.SessionTokenVariable], out id) == true) { acc = new ZkDataContext().Accounts.Find(id); } } if (acc != null) { var ip = Request.UserHostAddress; var lastLogin = acc.AccountUserIDs.OrderByDescending(x => x.LastLogin).FirstOrDefault(); var userID = lastLogin?.UserID; var installID = lastLogin?.InstallID; var penalty = Punishment.GetActivePunishment(acc.AccountID, ip, userID, installID, x => x.BanSite); if (penalty != null) { Response.Write(string.Format("You are banned! (IP match to account {0})\n", penalty.AccountByAccountID.Name)); Response.Write(string.Format("Ban expires: {0} UTC\n", penalty.BanExpires)); Response.Write(string.Format("Reason: {0}\n", penalty.Reason)); Response.End(); } else { HttpContext.Current.User = acc; FormsAuthentication.SetAuthCookie(acc.Name, true); } } // remove cake from URL var removeCake = Regex.Replace(Request.Url.ToString(), $"([?|&])({GlobalConst.SessionTokenVariable}=[^&?]+[?|&]*)", m => m.Groups[1].Value); if (removeCake != Request.Url.ToString()) { Response.Redirect(removeCake, true); } }
/// <summary> /// Get user detail page by username or <see cref="Account"/> ID /// </summary> /// <param name="id">Name or ID</param> public ActionResult LobbyDetail(string id) { var db = new ZkDataContext(); int idint; Account user = null; if (int.TryParse(id, out idint)) { user = db.Accounts.Find(idint); } if (user == null) { user = Account.AccountByName(db, id); } return(View("UserDetail", user)); }
public ActionResult ReportToAdminFromLobby(string id) { var db = new ZkDataContext(); int idint; Account user = null; if (int.TryParse(id, out idint)) { user = db.Accounts.Find(idint); } if (user == null) { user = Account.AccountByName(db, id); } return(View("ReportToAdmin", user)); }
public ActionResult GetReplayList() { if (!Global.IsTourneyController) { return(DenyAccess()); } var db = new ZkDataContext(); List <string> replayList = new List <string>(); var tourneyBattles = Global.Server.Battles.Values.Where(x => x != null).OfType <TourneyBattle>().ToList(); foreach (var tBat in tourneyBattles) { string line = string.Format(""); foreach (var team in tBat.Prototype.TeamPlayers) { foreach (var p in team) { line += "@U" + Account.AccountByName(db, p).AccountID + ", "; } line = line.Remove(line.Length - 2); line += " vs "; } line = line.Remove(line.Length - 4); line += ": "; int batCount = 0; foreach (var deb in tBat.Debriefings) { var bat = db.SpringBattles.FirstOrDefault(x => x.SpringBattleID == deb.ServerBattleID); if (bat != null) { batCount++; line += "@B" + deb.ServerBattleID + ", "; } } line = line.Remove(line.Length - 2); if (batCount > 0) { replayList.Add(line); } } return(Content(string.Join("<br />", replayList))); }
/// <summary> /// <para>Converts strings preceded with an @ to a printed <see cref="Account"/>, <see cref="SpringBattle"/>, etc. as appropriate</para> /// <para>e.g. @KingRaptor becomes the printed account for user KingRaptor</para> /// </summary> /// <param name="str"></param> /// <returns></returns> public static string ProcessAtSignTags(string str) { var db = new ZkDataContext(); str = Regex.Replace(str, @"@([\w\[\]]+)", m => { var val = m.Groups[1].Value; var acc = Account.AccountByName(db, val); if (acc != null) { return(PrintAccount(null, acc).ToString()); } var clan = db.Clans.FirstOrDefault(x => x.Shortcut == val); if (clan != null) { return(PrintClan(null, clan).ToString()); } var fac = db.Factions.FirstOrDefault(x => x.Shortcut == val); if (fac != null) { return(PrintFaction(null, fac, false).ToString()); } if (val.StartsWith("b", StringComparison.InvariantCultureIgnoreCase)) { var bid = 0; if (int.TryParse(val.Substring(1), out bid)) { var bat = db.SpringBattles.FirstOrDefault(x => x.SpringBattleID == bid); if (bat != null) { return(PrintBattle(null, bat).ToString()); } } } return("@" + val); }); return(str); }
public ActionResult Detail(string id) { var db = new ZkDataContext(); int idint; Account user = null; if (int.TryParse(id, out idint)) { user = db.Accounts.Find(idint); } if (user == null) { user = Account.AccountByName(db, id); } if (user == null) { return(Content("Invalid account (neither an ID nor name)")); } return(View("UserDetail", user)); }
public void JoinPlanet(string name, int planetId) { if (tas.ExistingUsers.ContainsKey(name)) { Faction faction = factions.FirstOrDefault(x => x.Shortcut == tas.ExistingUsers[name].Faction); if (faction == null) { var db = new ZkDataContext(); // this is a fallback, should not be needed var acc = Account.AccountByName(db, name); faction = factions.FirstOrDefault(x => x.FactionID == acc.FactionID); } if (faction == AttackingFaction) { JoinPlanetAttack(planetId, name); } else if (Challenge != null && GetDefendingFactions(Challenge).Contains(faction)) { JoinPlanetDefense(planetId, name); } } }
public async Task Process(SetAccountRelation rel) { if (!IsLoggedIn) { return; } if (string.IsNullOrEmpty(rel.TargetName) && string.IsNullOrEmpty(rel.SteamID)) { return; } using (var db = new ZkDataContext()) { ulong steamId = 0; var srcAccount = db.Accounts.Find(User.AccountID); ulong.TryParse(rel.SteamID, out steamId); var trgtAccount = Account.AccountByName(db, rel.TargetName) ?? db.Accounts.FirstOrDefault(x => x.SteamID == steamId); if (trgtAccount == null) { if (!string.IsNullOrEmpty(rel.TargetName)) { await Respond("No such account found"); // only warn if name is set and not just steam id } return; } var friendAdded = false; var entry = srcAccount.RelalationsByOwner.FirstOrDefault(x => x.TargetAccountID == trgtAccount.AccountID); if ((rel.Relation == Relation.None) && (entry != null)) { db.AccountRelations.Remove(entry); } if (rel.Relation != Relation.None) { if (entry == null) { if (rel.Relation == Relation.Friend) { friendAdded = true; } entry = new AccountRelation() { Owner = srcAccount, Target = trgtAccount, Relation = rel.Relation }; srcAccount.RelalationsByOwner.Add(entry); } else { entry.Relation = rel.Relation; } } db.SaveChanges(); ConnectedUser targetConnectedUser; if (server.ConnectedUsers.TryGetValue(trgtAccount.Name, out targetConnectedUser)) { targetConnectedUser.LoadFriendsIgnores(); // update partner's mutual lists if (friendAdded) // friend added, sync new friend to me (user, battle and channels) { await server.TwoWaySyncUsers(Name, new List <string>() { targetConnectedUser.Name }); foreach (var chan in server.Channels.Values.Where( x => (x != null) && x.Users.ContainsKey(Name) && x.Users.ContainsKey(targetConnectedUser.Name))) { await SendCommand(new ChannelUserAdded() { ChannelName = chan.Name, UserName = targetConnectedUser.Name }); } } } LoadFriendsIgnores(); await SendCommand(new FriendList() { Friends = FriendEntries.ToList() }); await SendCommand(new IgnoreList() { Ignores = Ignores.ToList() }); } }
public ActionResult AddMultipleBattles(string battleList) { if (!Global.IsTourneyController) { return(DenyAccess()); } var db = new ZkDataContext(); string[] splitters = { "//" }; string[] battleSpecs = battleList.Split(splitters, System.StringSplitOptions.RemoveEmptyEntries); foreach (var bSpec in battleSpecs) { bool validBattle = true; string[] bItems = bSpec.Split(','); string bName = bItems[0]; // must have an even number of players; the first N/2 are assigned to the first team if (bItems.Length % 2 == 0) { validBattle = false; } ; int playersPerTeam = (bItems.Length - 1) / 2; List <int> team1Ids = new List <int>(); List <int> team2Ids = new List <int>(); // if any of the remaining entries are not ints or account names the battle is invalid for (int i = 1; i <= playersPerTeam; i++) { Account tryAcc = Account.AccountByName(db, bItems[i]); if (tryAcc != null) { team1Ids.Add(tryAcc.AccountID); } else { try { team1Ids.Add(Int32.Parse(bItems[i])); } catch (FormatException) { validBattle = false; } } } for (int i = playersPerTeam + 1; i < bItems.Length; i++) { Account tryAcc = Account.AccountByName(db, bItems[i]); if (tryAcc != null) { team2Ids.Add(tryAcc.AccountID); } else { try { team2Ids.Add(Int32.Parse(bItems[i])); } catch (FormatException) { validBattle = false; } } } if (validBattle) { var tb = new TourneyBattle(Global.Server, new TourneyBattle.TourneyPrototype() { Title = bName, FounderName = Global.Account.Name, TeamPlayers = new List <List <string> >() { team1Ids.Select(x => db.Accounts.Find(x)?.Name).Where(x => x != null).ToList(), team2Ids.Select(x => db.Accounts.Find(x)?.Name).Where(x => x != null).ToList() } }); Global.Server.AddBattle(tb); } } return(RedirectToAction("Index")); }
void client_Said(object sender, TasSayEventArgs e) { User user; if (!client.ExistingUsers.TryGetValue(e.UserName, out user)) { return; } if (e.Place == SayPlace.Channel && e.Channel != "main") { Task.Factory.StartNew(() => { try { using (var db = new ZkDataContext()) { Channel channel; if (!client.JoinedChannels.TryGetValue(e.Channel, out channel)) { return; } foreach (var s in db.LobbyChannelSubscriptions.Where(x => x.Channel == e.Channel).Select(x => x.Account)) { if (!channel.Users.ContainsKey(s.Name)) { var fac = db.Factions.FirstOrDefault(x => x.Shortcut == e.Channel); // if faction channel check if allowed if (fac == null || (fac.FactionID == s.AccountID && s.Level >= GlobalConst.FactionChannelMinLevel)) { var message = new LobbyMessage() { SourceLobbyID = user.AccountID, SourceName = e.UserName, Created = DateTime.UtcNow, Message = e.Text, TargetName = s.Name, Channel = e.Channel }; db.LobbyMessages.InsertOnSubmit(message); } } } db.SubmitChanges(); } } catch (Exception ex) { Trace.TraceError("Error storing message: {0}", ex); } }); } else if (e.Place == SayPlace.User) { Task.Factory.StartNew(() => { try { if (e.Place == SayPlace.User) { if (e.Text.StartsWith("!pm")) { var regex = Regex.Match(e.Text, "!pm ([^ ]+) (.+)"); if (regex.Success) { var name = regex.Groups[1].Value; var text = regex.Groups[2].Value; var message = new LobbyMessage() { SourceLobbyID = user.AccountID, SourceName = e.UserName, Created = DateTime.UtcNow, Message = text, TargetName = name }; using (var db = new ZkDataContext()) { db.LobbyMessages.InsertOnSubmit(message); db.SubmitChanges(); } } } else if (e.Text.StartsWith("!subscribe")) { var regex = Regex.Match(e.Text, "!subscribe #([^ ]+)"); if (regex.Success) { var chan = regex.Groups[1].Value; if (chan != "main") { using (var db = new ZkDataContext()) { Account account = Account.AccountByName(db, e.UserName); if (chan == AuthService.ModeratorChannel && !(account.IsZeroKAdmin)) { client.Say(SayPlace.User, user.Name, "Not authorized to subscribe to this channel", false); } else { var accountID = account.AccountID; var subs = db.LobbyChannelSubscriptions.FirstOrDefault(x => x.AccountID == accountID && x.Channel == chan); if (subs == null) { subs = new LobbyChannelSubscription() { AccountID = accountID, Channel = chan }; db.LobbyChannelSubscriptions.InsertOnSubmit(subs); db.SubmitChanges(); client.JoinChannel(chan); } client.Say(SayPlace.User, user.Name, "Subscribed", false); } } } } } else if (e.Text.StartsWith("!unsubscribe")) { var regex = Regex.Match(e.Text, "!unsubscribe #([^ ]+)"); if (regex.Success) { var chan = regex.Groups[1].Value; using (var db = new ZkDataContext()) { var accountID = Account.AccountByName(db, e.UserName).AccountID; var subs = db.LobbyChannelSubscriptions.FirstOrDefault(x => x.AccountID == accountID && x.Channel == chan); if (subs != null) { db.LobbyChannelSubscriptions.DeleteOnSubmit(subs); db.SubmitChanges(); } client.Say(SayPlace.User, user.Name, "Unsubscribed", false); } } } else if (e.Text.Equals("!listsubscriptions")) { using (var db = new ZkDataContext()) { var accountID = Account.AccountByName(db, e.UserName).AccountID; var subscriptionList = "No channels subscribed."; var subs = db.LobbyChannelSubscriptions.Where(x => x.AccountID == accountID).OrderBy(x => x.Channel).Select(x => x.Channel); if (subs != null) { subscriptionList = "Subscribed to: " + String.Join(", ", subs); } client.Say(SayPlace.User, user.Name, subscriptionList, false); } } } } catch (Exception ex) { Trace.TraceError("Error sending stored message: {0}", ex); } }); } }
private static SpringBattle SaveSpringBattle(SpringBattleContext result, ZkDataContext db) { var sb = new SpringBattle { HostAccountID = Account.AccountByName(db, result.LobbyStartContext.FounderName)?.AccountID, Mode = result.LobbyStartContext.Mode, Duration = result.Duration, EngineGameID = result.EngineBattleID, MapResourceID = db.Resources.Single(x => x.InternalName == result.LobbyStartContext.Map).ResourceID, ModResourceID = db.Resources.Single(x => x.InternalName == result.LobbyStartContext.Mod).ResourceID, HasBots = result.LobbyStartContext.Bots.Any(), IsMission = result.LobbyStartContext.IsMission, PlayerCount = result.ActualPlayers.Count(x => !x.IsSpectator), StartTime = result.StartTime, Title = result.LobbyStartContext.Title, ReplayFileName = Path.GetFileName(result.ReplayName), EngineVersion = result.LobbyStartContext.EngineVersion, IsMatchMaker = result.LobbyStartContext.IsMatchMakerGame, ApplicableRatings = 0, }; db.SpringBattles.InsertOnSubmit(sb); // store players foreach (BattlePlayerResult p in result.ActualPlayers) { var account = Account.AccountByName(db, p.Name); if (account != null) { sb.SpringBattlePlayers.Add(new SpringBattlePlayer { Account = account, AccountID = account.AccountID, AllyNumber = p.AllyNumber, IsInVictoryTeam = p.IsVictoryTeam, IsSpectator = p.IsSpectator, LoseTime = p.LoseTime }); } } // store bots var victoryAllyID = result.ActualPlayers.Where(x => x.IsVictoryTeam).Select(x => (int?)x.AllyNumber).FirstOrDefault() ?? -1; if (victoryAllyID == -1) { victoryAllyID = (result.ActualPlayers.Min(x => (int?)x.AllyNumber) ?? -1) + 1; // no player won, its likely to be next lowes team (stupid hack needed) } foreach (var bot in result.LobbyStartContext.Bots) { sb.SpringBattleBots.Add(new SpringBattleBot() { AllyNumber = bot.AllyID, BotAI = bot.BotAI, BotName = bot.BotName, IsInVictoryTeam = bot.AllyID == victoryAllyID }); } db.SaveChanges(); return(db.SpringBattles.FirstOrDefault(x => x.SpringBattleID == sb.SpringBattleID)); // reselect from db to get proper lazy proxies }
public AuthService(TasClient client) { this.client = client; /* * this.client.Input += (s, e) => * { * Console.WriteLine(e.Command +" "+ Utils.Glue(e.Args)); * }; * this.client.Output += (s, e) => * { * Console.WriteLine(e.Data.Key + " " +Utils.Glue(e.Data.Value.Select(x=>x.ToString()).ToArray())); * };*/ this.client.LoginAccepted += (s, e) => { requests.Clear(); client.JoinChannel(ModeratorChannel); client.JoinChannel(Top20Channel); using (var db = new ZkDataContext()) foreach (var fac in db.Factions.Where(x => !x.IsDeleted)) { client.JoinChannel(fac.Shortcut); } }; this.client.TestLoginAccepted += (s, e) => { RequestInfo entry; if (requests.TryGetValue(client.MessageID, out entry)) { entry.CorrectName = e.ServerParams[0]; entry.LobbyID = Convert.ToInt32(e.ServerParams[1]); if (client.ExistingUsers.ContainsKey(entry.CorrectName)) { entry.User = client.ExistingUsers[entry.CorrectName]; } entry.WaitHandle.Set(); } requests.TryRemove(client.MessageID, out entry); }; this.client.UserAdded += (s, e) => { using (var db = new ZkDataContext()) { var acc = Account.AccountByLobbyID(db, e.Data.LobbyID); if (acc != null) { this.client.Extensions.PublishAccountData(acc); if (acc.SpringieLevel > 2 || acc.IsZeroKAdmin) { client.ForceJoinChannel(e.Data.Name, ModeratorChannel); } if (topPlayers.IsTop20(e.Data.LobbyID)) { client.ForceJoinChannel(e.Data.Name, Top20Channel); } if (acc.Clan != null) { client.ForceJoinChannel(e.Data.Name, acc.Clan.GetClanChannel(), acc.Clan.Password); } if (acc.Faction != null && acc.Level >= GlobalConst.FactionChannelMinLevel && acc.CanPlayerPlanetWars()) { client.ForceJoinChannel(e.Data.Name, acc.Faction.Shortcut); } } client.RequestUserIP(e.Data.Name); client.RequestUserID(e.Data.Name); } }; this.client.UserIDRecieved += (sender, args) => { Task.Factory.StartNew(() => { try { using (var db = new ZkDataContext()) { var acc = Account.AccountByName(db, args.Name); var penalty = Punishment.GetActivePunishment(acc != null ? acc.AccountID : 0, null, args.ID, x => x.BanLobby, db); if (penalty != null) { client.AdminKickFromLobby(args.Name, string.Format("Banned until {0} (ID match to {1}), reason: {2}", penalty.BanExpires, penalty.AccountByAccountID.Name, penalty.Reason)); } ; if (acc != null && args.ID != 0) { var entry = acc.AccountUserIDS.FirstOrDefault(x => x.UserID == args.ID); if (entry == null) { entry = new AccountUserID { AccountID = acc.AccountID, UserID = args.ID, FirstLogin = DateTime.UtcNow }; db.AccountUserIDS.InsertOnSubmit(entry); } entry.LoginCount++; entry.LastLogin = DateTime.UtcNow; } Account accAnteep = db.Accounts.FirstOrDefault(x => x.AccountID == 4490); bool isAnteepSmurf = accAnteep.AccountUserIDS.Any(x => x.UserID == args.ID); if (isAnteepSmurf) { client.Say(TasClient.SayPlace.Channel, ModeratorChannel, String.Format("Suspected Anteep smurf: {0} (ID match {1}) {2}", args.Name, args.ID, acc != null ? "http://zero-k.info/Users/Detail/" + acc.AccountID : ""), false); } if (args.ID != 0 && args.ID < 1000) { client.Say(TasClient.SayPlace.Channel, ModeratorChannel, String.Format("Suspected Anteep smurf: {0} (too short userID {1}) {2}", args.Name, args.ID, acc != null ? "http://zero-k.info/Users/Detail/" + acc.AccountID : ""), false); } db.SubmitChanges(); } } catch (Exception ex) { Trace.TraceError("Error getting user ID: {0}", ex); } }); }; this.client.UserIPRecieved += (sender, args) => { Task.Factory.StartNew(() => { try { Account acc = null; using (var db = new ZkDataContext()) { acc = Account.AccountByName(db, args.Name); var penalty = Punishment.GetActivePunishment(acc != null ? acc.AccountID : 0, args.IP, null, x => x.BanLobby, db); if (penalty != null) { client.AdminKickFromLobby(args.Name, string.Format("Banned until {0} (IP match to {1}), reason: {2}", penalty.BanExpires, penalty.AccountByAccountID.Name, penalty.Reason)); } if (acc != null) { var entry = acc.AccountIPS.FirstOrDefault(x => x.IP == args.IP); if (entry == null) { entry = new AccountIP { AccountID = acc.AccountID, IP = args.IP, FirstLogin = DateTime.UtcNow }; db.AccountIPS.InsertOnSubmit(entry); } entry.LoginCount++; entry.LastLogin = DateTime.UtcNow; } db.SubmitChanges(); } try { if (acc == null || !acc.HasVpnException) { if (GlobalConst.VpnCheckEnabled) { // check user IP against http://dnsbl.tornevall.org // does not catch all smurfs // mostly false positives, do not use var reversedIP = string.Join(".", args.IP.Split('.').Reverse().ToArray()); try { var resolved = Dns.GetHostEntry(string.Format("{0}.dnsbl.tornevall.org", reversedIP)).AddressList; if (resolved.Length > 0) { client.Say(TasClient.SayPlace.Channel, ModeratorChannel, String.Format("User {0} {3} has IP {1} on dnsbl.tornevall.org ({2} result/s)", args.Name, args.IP, resolved.Length, acc != null ? "http://zero-k.info/Users/Detail/" + acc.AccountID : ""), false); //client.AdminKickFromLobby(args.Name, // "Connection using proxy or VPN is not allowed! (You can ask for exception). See http://dnsbl.tornevall.org/removal.php to get your IP removed from the blacklist."); } } catch (System.Net.Sockets.SocketException sockEx) { // not in database, do nothing } } using (var db = new ZkDataContext()) { Account accAnteep = db.Accounts.FirstOrDefault(x => x.AccountID == 4490); bool isAnteepSmurf = accAnteep.AccountIPS.Any(x => x.IP == args.IP); if (isAnteepSmurf) { client.Say(TasClient.SayPlace.Channel, ModeratorChannel, String.Format("Suspected Anteep smurf: {0} (IP match {1}) {2}", args.Name, args.IP, acc != null ? "http://zero-k.info/Users/Detail/" + acc.AccountID : ""), false); } } using (ZkDataContext db = new ZkDataContext()) { for (int i = 0; i <= 1; i++) { var whois = new Whois(); var data = whois.QueryByIp(args.IP, i == 1); if (!data.ContainsKey("netname")) { data["netname"] = "UNKNOWN NETNAME"; } if (!data.ContainsKey("org-name")) { data["org-name"] = "UNKNOWN ORG"; } if (!data.ContainsKey("abuse-mailbox")) { data["abuse-mailbox"] = "no mailbox"; } if (!data.ContainsKey("notify")) { data["notify"] = "no notify address"; } if (!data.ContainsKey("role")) { data["role"] = "UNKNOWN ROLE"; } if (!data.ContainsKey("descr")) { data["descr"] = "no description"; } if (!data.ContainsKey("remarks")) { data["remarks"] = "no remarks"; } var blockedCompanies = db.BlockedCompanies.Select(x => x.CompanyName.ToLower()).ToList(); var blockedHosts = db.BlockedHosts.Select(x => x.HostName).ToList(); /*if (acc.Country == "MY") * { * client.Say(TasClient.SayPlace.User, "KingRaptor", String.Format("USER {0}\nnetname: {1}\norgname: {2}\ndescr: {3}\nabuse-mailbox: {4}", * acc.Name, data["netname"], data["org-name"], data["descr"], data["abuse-mailbox"]), false); * }*/ if (blockedHosts.Any(x => data["abuse-mailbox"].Contains(x)) || (blockedHosts.Any(x => data["notify"].Contains(x)))) { client.AdminKickFromLobby(args.Name, "Connection using proxy or VPN is not allowed! (You can ask for exception)"); } foreach (string company in blockedCompanies) { if (data["netname"].ToLower().Contains(company) || data["org-name"].ToLower().Contains(company) || data["descr"].ToLower().Contains(company) || data["role"].ToLower().Contains(company) || data["remarks"].ToLower().Contains(company)) { client.AdminKickFromLobby(args.Name, "Connection using proxy or VPN is not allowed! (You can ask for exception)"); break; } } var hostname = Dns.GetHostEntry(args.IP).HostName; if (blockedHosts.Any(hostname.Contains)) { client.AdminKickFromLobby(args.Name, "Connection using proxy or VPN is not allowed! (You can ask for exception)"); } } } } } catch (System.Net.Sockets.SocketException sockEx) { // do nothing } catch (Exception ex) { Trace.TraceError("VPN check error: {0}", ex); client.Say(TasClient.SayPlace.Channel, ModeratorChannel, ex.ToString(), false); } } catch (Exception ex) { Trace.TraceError("Error getting user IP: {0}", ex); //client.Say(TasClient.SayPlace.User, "KingRaptor", ex.ToString(), false); } }); }; this.client.UserStatusChanged += (s, e) => { var user = client.ExistingUsers[e.ServerParams[0]]; Task.Factory.StartNew(() => { try { using (var db = new ZkDataContext()) UpdateUser(user.LobbyID, user.Name, user, null, db); } catch (Exception ex) { Trace.TraceError(ex.ToString()); } }, TaskCreationOptions.LongRunning); }; this.client.BattleUserJoined += (s, e) => { var battle = client.ExistingBattles[e.BattleID]; var founder = battle.Founder; if (founder.IsSpringieManaged) { try { var user = client.ExistingUsers[e.UserName]; /* obsolete; all major lobbies have multiengine support * if (!user.IsZkLobbyUser && !user.IsNotaLobby && battle.EngineVersion != client.ServerSpringVersion && * battle.EngineVersion != client.ServerSpringVersion + ".0") { * client.Say(TasClient.SayPlace.User, * user.Name, * string.Format( * "ALERT! YOU WILL DESYNC!! You NEED SPRING ENGINE {0} to play here. Simply join the game with Zero-K lobby ( http://zero-k.info/Wiki/Download ) OR get the engine from http://springrts.com/dl/buildbot/default/ OR build it on your Linux: http://springrts.com/wiki/Building_Spring_on_Linux ", * battle.EngineVersion), * false); * } */ using (var db = new ZkDataContext()) { var acc = Account.AccountByLobbyID(db, user.LobbyID); var name = founder.Name.TrimNumbers(); var aconf = db.AutohostConfigs.FirstOrDefault(x => x.Login == name); if (acc != null && user != null && aconf != null && (acc.LastLobbyVersionCheck == null || DateTime.UtcNow.Subtract(acc.LastLobbyVersionCheck.Value).TotalDays > 3) && aconf.AutohostMode != 0) { client.RequestLobbyVersion(user.Name); } /* * if (acc != null) * { * int numIDs = acc.AccountUserIDS != null ? acc.AccountUserIDS.Count : 0; * if (numIDs == 0) client.Say(TasClient.SayPlace.User, "KingRaptor", string.Format("USER {0} joined battle {1}; has {2} userIDs; lobby version {3}", acc.Name, founder.Name, numIDs, acc.LobbyVersion), false); * } * else * client.Say(TasClient.SayPlace.User, "KingRaptor", string.Format("USER {0} joined battle {1}", e.UserName + " (NO ACCOUNT)", founder.Name), false); * * if (acc != null) * { * if (!acc.AccountUserIDS.Any()) * { * string reason = string.Format("Sorry you are using unsupported lobby ({0}), please upgrade or use Zero-K Lobby, Weblobby or SpringLobby", acc.LobbyVersion); * client.Say(TasClient.SayPlace.User, user.Name, reason, false); * client.Say(TasClient.SayPlace.User, founder.Name, string.Format("!kick {0} {1}", acc.LobbyVersion, reason), false); * } * }*/ } } catch (Exception ex) { //client.Say(TasClient.SayPlace.User, "KingRaptor", ex.ToString(), false); Trace.TraceError("Error procesisng battle user joined: {0}", ex); } } }; this.client.TestLoginDenied += (s, e) => { RequestInfo entry; if (requests.TryGetValue(client.MessageID, out entry)) { entry.WaitHandle.Set(); } requests.TryRemove(client.MessageID, out entry); }; this.client.UserLobbyVersionRecieved += (s, e) => { using (var db = new ZkDataContext()) { var acc = Account.AccountByName(db, e.Name); if (acc != null) { acc.LobbyVersion = e.LobbyVersion; acc.LastLobbyVersionCheck = DateTime.UtcNow; db.SubmitAndMergeChanges(); if (!acc.LobbyVersion.StartsWith("ZK")) { // FIXME abma broke this (LobbyVersion is now some huge-ass integer instead) //client.Say(TasClient.SayPlace.User, // e.Name, // string.Format( // "WARNING: You are connected using {0} which is not fully compatible with this host. Please use Zero-K lobby. Download it from http://zero-k.info NOTE: to play all Spring games with Zero-K lobby, untick \"Official games\" on its multiplayer tab. Thank you!", // e.LobbyVersion), // false); } } } }; this.client.BattleFound += (s, e) => { if (e.Data.Founder.IsZkLobbyUser && !e.Data.Founder.IsBot) { client.SetBotMode(e.Data.Founder.Name, true); } }; this.client.ChannelUserAdded += (sender, args) => { try { var channel = args.ServerParams[0]; var user = args.ServerParams[1]; if (channel == ModeratorChannel) { var u = client.ExistingUsers[user]; if (u.SpringieLevel <= 2 && !u.IsZeroKAdmin) { client.ForceLeaveChannel(user, ModeratorChannel); } } else if (channel == Top20Channel) { var u = client.ExistingUsers[user]; if (!topPlayers.IsTop20(u.LobbyID) && u.Name != client.UserName) { client.ForceLeaveChannel(user, Top20Channel); } } else { using (var db = new ZkDataContext()) { var fac = db.Factions.FirstOrDefault(x => x.Shortcut == channel); if (fac != null) { // faction channel var u = client.ExistingUsers[user]; var acc = Account.AccountByLobbyID(db, u.LobbyID); if (acc == null || acc.FactionID != fac.FactionID || acc.Level < GlobalConst.FactionChannelMinLevel) { client.ForceLeaveChannel(user, channel); } } } } } catch (Exception ex) { Trace.TraceError("Error procesisng channel user added: {0}", ex); } }; this.client.ChannelUserRemoved += (sender, args) => { try { var channel = args.ServerParams[0]; var user = args.ServerParams[1]; if (channel == ModeratorChannel) { var u = client.ExistingUsers[user]; if (u.SpringieLevel > 2 || u.IsZeroKAdmin) { client.ForceJoinChannel(user, ModeratorChannel); } } } catch (Exception ex) { Trace.TraceError("Error procesisng channel user added: {0}", ex); } }; }
List <Faction> GetDefendingFactions(AttackOption target) { if (target.OwnerFactionID != null) { return new List <Faction> { factions.Find(x => x.FactionID == target.OwnerFactionID) } } ; return(factions.Where(x => x != AttackingFaction).ToList()); } void JoinPlanetAttack(int targetPlanetId, string userName) { AttackOption attackOption = AttackOptions.Find(x => x.PlanetID == targetPlanetId); if (attackOption != null) { User user; if (tas.ExistingUsers.TryGetValue(userName, out user)) { var db = new ZkDataContext(); Account account = Account.AccountByLobbyID(db, user.LobbyID); if (account != null && account.FactionID == AttackingFaction.FactionID && account.CanPlayerPlanetWars()) { // remove existing user from other options foreach (AttackOption aop in AttackOptions) { aop.Attackers.RemoveAll(x => x == userName); } // add user to this option if (attackOption.Attackers.Count < attackOption.TeamSize) { attackOption.Attackers.Add(user.Name); tas.Say(TasClient.SayPlace.Channel, user.Faction, string.Format("{0} joins attack on {1}", userName, attackOption.Name), true); if (attackOption.Attackers.Count == attackOption.TeamSize) { StartChallenge(attackOption); } else { UpdateLobby(); } } } } } } void JoinPlanetDefense(int targetPlanetID, string userName) { if (Challenge != null && Challenge.PlanetID == targetPlanetID && Challenge.Defenders.Count < Challenge.TeamSize) { User user; if (tas.ExistingUsers.TryGetValue(userName, out user)) { var db = new ZkDataContext(); Account account = Account.AccountByLobbyID(db, user.LobbyID); if (account != null && GetDefendingFactions(Challenge).Any(y => y.FactionID == account.FactionID) && account.CanPlayerPlanetWars()) { if (!Challenge.Defenders.Any(y => y == user.Name)) { Challenge.Defenders.Add(user.Name); tas.Say(TasClient.SayPlace.Channel, user.Faction, string.Format("{0} joins defense of {1}", userName, Challenge.Name), true); if (Challenge.Defenders.Count == Challenge.TeamSize) { AcceptChallenge(); } else { UpdateLobby(); } } } } } } void RecordPlanetwarsLoss(AttackOption option) { if (option.OwnerFactionID != null) { if (option.OwnerFactionID == missedDefenseFactionID) { missedDefenseCount++; } else { missedDefenseCount = 0; missedDefenseFactionID = option.OwnerFactionID.Value; } } var message = string.Format("{0} won because nobody tried to defend", AttackingFaction.Name); foreach (var fac in factions) { tas.Say(TasClient.SayPlace.Channel, fac.Shortcut, message, true); } var text = new StringBuilder(); try { var db = new ZkDataContext(); List <string> playerIds = option.Attackers.Select(x => x).Union(option.Defenders.Select(x => x)).ToList(); PlanetWarsTurnHandler.EndTurn(option.Map, null, db, 0, db.Accounts.Where(x => playerIds.Contains(x.Name) && x.Faction != null).ToList(), text, null, db.Accounts.Where(x => option.Attackers.Contains(x.Name) && x.Faction != null).ToList()); } catch (Exception ex) { Trace.TraceError(ex.ToString()); text.Append(ex); } } void ResetAttackOptions() { AttackOptions.Clear(); AttackerSideChangeTime = DateTime.UtcNow; Challenge = null; ChallengeTime = null; using (var db = new ZkDataContext()) { var gal = db.Galaxies.First(x => x.IsDefault); int cnt = 2; var attacker = db.Factions.Single(x => x.FactionID == AttackingFaction.FactionID); var planets = gal.Planets.Where(x => x.OwnerFactionID != AttackingFaction.FactionID).OrderByDescending(x => x.PlanetFactions.Where(y => y.FactionID == AttackingFaction.FactionID).Sum(y => y.Dropships)).ThenByDescending(x => x.PlanetFactions.Where(y => y.FactionID == AttackingFaction.FactionID).Sum(y => y.Influence)).ToList(); // list of planets by attacker's influence foreach (var planet in planets) { if (planet.CanMatchMakerPlay(attacker)) { // pick only those where you can actually attack atm InternalAddOption(planet); cnt--; } if (cnt == 0) { break; } } if (!AttackOptions.Any(y => y.TeamSize == 2)) { var planet = planets.FirstOrDefault(x => x.TeamSize == 2 && x.CanMatchMakerPlay(attacker)); if (planet != null) { InternalAddOption(planet); } } } UpdateLobby(); tas.Say(TasClient.SayPlace.Channel, AttackingFaction.Shortcut, "It's your turn! Select a planet to attack", true); } void InternalAddOption(Planet planet) { AttackOptions.Add(new AttackOption { PlanetID = planet.PlanetID, Map = planet.Resource.InternalName, OwnerFactionID = planet.OwnerFactionID, Name = planet.Name, TeamSize = planet.TeamSize, }); } void SaveStateToDb() { var db = new ZkDataContext(); Galaxy gal = db.Galaxies.First(x => x.IsDefault); gal.MatchMakerState = JsonConvert.SerializeObject((MatchMakerState)this); gal.AttackerSideCounter = AttackerSideCounter; gal.AttackerSideChangeTime = AttackerSideChangeTime; db.SubmitAndMergeChanges(); } void StartChallenge(AttackOption attackOption) { Challenge = attackOption; ChallengeTime = DateTime.UtcNow; AttackOptions.Clear(); UpdateLobby(); } void TasOnChannelUserAdded(object sender, TasEventArgs args) { string chan = args.ServerParams[0]; string userName = args.ServerParams[1]; Faction faction = factions.FirstOrDefault(x => x.Shortcut == chan); if (faction != null) { var db = new ZkDataContext(); var acc = Account.AccountByName(db, userName); if (acc != null && acc.CanPlayerPlanetWars()) { UpdateLobby(userName); } } } /// <summary> /// Intercept channel messages for attacking/defending /// </summary> /// <param name="sender"></param> /// <param name="args"></param> void TasOnPreviewSaid(object sender, CancelEventArgs <TasSayEventArgs> args) { if (args.Data.Text.StartsWith("!") && (args.Data.Place == TasSayEventArgs.Places.Channel || args.Data.Place == TasSayEventArgs.Places.Normal) && args.Data.Origin == TasSayEventArgs.Origins.Player && args.Data.UserName != GlobalConst.NightwatchName) { int targetPlanetId; if (int.TryParse(args.Data.Text.Substring(1), out targetPlanetId)) { JoinPlanet(args.Data.UserName, targetPlanetId); } } } /// <summary> /// Remove/reduce poll count due to lobby quits /// </summary> void TasOnUserRemoved(object sender, TasEventArgs args) { if (Challenge == null) { if (AttackOptions.Count > 0) { string userName = args.ServerParams[0]; int sumRemoved = 0; foreach (AttackOption aop in AttackOptions) { sumRemoved += aop.Attackers.RemoveAll(x => x == userName); } if (sumRemoved > 0) { UpdateLobby(); } } } else { string userName = args.ServerParams[0]; if (Challenge.Defenders.RemoveAll(x => x == userName) > 0) { UpdateLobby(); } } } void TimerOnElapsed(object sender, ElapsedEventArgs elapsedEventArgs) { try { if (Challenge == null) { // attack timer if (DateTime.UtcNow > GetAttackDeadline()) { AttackerSideCounter++; ResetAttackOptions(); } } else { // accept timer if (DateTime.UtcNow > GetAcceptDeadline()) { if (Challenge.Defenders.Count >= Challenge.Attackers.Count - 1 && Challenge.Defenders.Count > 0) { AcceptChallenge(); } else { RecordPlanetwarsLoss(Challenge); AttackerSideCounter++; ResetAttackOptions(); } } } } catch (Exception ex) { Trace.TraceError(ex.ToString()); } }
public override async Task ExecuteArmed(ServerBattle battle, Say e) { var b = battle; List <IEnumerable <Account> > teams; RatingCategory cat = RatingCategory.Casual; if (b.IsMatchMakerBattle) { cat = RatingCategory.MatchMaking; } if (b.Mode == PlasmaShared.AutohostMode.Planetwars) { cat = RatingCategory.Planetwars; } using (var db = new ZkDataContext()) { if (battle.IsInGame) { teams = b.spring.LobbyStartContext?.Players.Where(u => !u.IsSpectator) .GroupBy(u => u.AllyID) .Select(x => x.Select(p => Account.AccountByName(db, p.Name))).ToList(); } else { switch (battle.Mode) { case PlasmaShared.AutohostMode.Game1v1: teams = b.Users.Values.Where(u => !u.IsSpectator) .GroupBy(u => u.Name) .Select(x => x.Select(p => Account.AccountByName(db, p.Name))).ToList(); break; case PlasmaShared.AutohostMode.Teams: teams = PartitionBalance.Balance(battle.IsCbalEnabled ? Balancer.BalanceMode.ClanWise : Balancer.BalanceMode.Normal, b.Users.Values.Where(u => !u.IsSpectator).Select(x => x.LobbyUser).Select(x => new PartitionBalance.PlayerItem(x.AccountID, x.EffectiveElo, x.Clan, x.PartyID)).ToList()) .Players .GroupBy(u => u.AllyID) .Select(x => x.Select(p => db.Accounts.Where(a => a.AccountID == p.LobbyID).FirstOrDefault())).ToList(); break; default: teams = b.Users.Values.Where(u => !u.IsSpectator) .GroupBy(u => u.AllyNumber) .Select(x => x.Select(p => Account.AccountByName(db, p.Name))).ToList(); break; } } if (teams.Count < 2) { await battle.SayBattle($"!predict needs at least two human teams to work"); return; } var chances = RatingSystems.GetRatingSystem(cat).PredictOutcome(teams, DateTime.UtcNow); for (int i = 0; i < teams.Count; i++) { await battle.SayBattle($"Team {teams[i].OrderByDescending(x => x.GetRating(cat).Elo).Select(x => x.Name).Aggregate((a, y) => a + ", " + y)} has a {Math.Round(1000 * chances[i]) / 10}% chance to win"); } } }
public override LinkedListNode <Tag> Translate(TranslateContext context, LinkedListNode <Tag> self) { if (!(self.Previous?.Value is LiteralTag)) // previous is not a continuous text { var ender = self.Next.FirstNode(x => !(x.Value is LiteralTag || x.Value is UnderscoreTag)); var text = self.Next.GetOriginalContentUntilNode(ender); // get next string if (!string.IsNullOrEmpty(text)) { int idx; for (idx = 0; idx < text.Length; idx++) { if (!Utils.ValidLobbyNameCharacter(text[idx])) { break; } } string remainder = null; string val = text; if (idx != 0 && idx < text.Length) { remainder = text.Substring(idx, text.Length - idx); val = text.Substring(0, idx); } if (!string.IsNullOrEmpty(val)) { var db = new ZkDataContext(); var fac = db.Factions.FirstOrDefault(x => x.Shortcut == val); if (fac != null) { context.Append(context.Html.PrintFaction(fac, false)); context.Append(remainder); return(ender); } var acc = Account.AccountByName(db, val); if (acc != null) { context.Append(context.Html.PrintAccount(acc)); context.Append(remainder); return(ender); } var clan = db.Clans.FirstOrDefault(x => x.Shortcut == val); if (clan != null) { context.Append(context.Html.PrintClan(clan)); context.Append(remainder); return(ender); } if (val.StartsWith("b", StringComparison.InvariantCultureIgnoreCase)) { var bid = 0; if (int.TryParse(val.Substring(1), out bid)) { var bat = db.SpringBattles.FirstOrDefault(x => x.SpringBattleID == bid); if (bat != null) { context.Append(context.Html.PrintBattle(bat)); context.Append(remainder); return(ender); } } } } } } context.Append("@"); return(self.Next); }
public override async Task ExecuteArmed(ServerBattle battle, Say e) { var b = battle; Dictionary <int, double> grouping; using (var db = new ZkDataContext()) { if (battle.IsInGame) { grouping = b.spring.LobbyStartContext?.Players.Where(u => !u.IsSpectator) .GroupBy(u => u.AllyID) .ToDictionary(x => x.Key, x => x.Average(y => RatingSystems.DisableRatingSystems ? Account.AccountByName(db, y.Name).BestEffectiveElo : Account.AccountByName(db, y.Name).GetBestRating().Elo)); } else { grouping = b.Users.Values.Where(u => !u.IsSpectator) .GroupBy(u => u.AllyNumber) .ToDictionary(x => x.Key, x => x.Average(y => Math.Max(y.LobbyUser.EffectiveMmElo, y.LobbyUser.EffectiveElo))); } } KeyValuePair <int, double>?oldg = null; foreach (var g in grouping) { if (oldg != null) { var t1elo = oldg.Value.Value; var t2elo = g.Value; await battle.Respond(e, $"team {oldg.Value.Key + 1} has {Utils.GetWinChancePercent(t2elo - t1elo)}% chance to win over team {g.Key + 1}"); } oldg = g; } }
public override async Task ExecuteArmed(ServerBattle battle, Say e) { var b = battle; List <IEnumerable <Account> > teams; RatingCategory cat = RatingCategory.Casual; if (b.IsMatchMakerBattle) { cat = RatingCategory.MatchMaking; } if (b.Mode == PlasmaShared.AutohostMode.Planetwars) { cat = RatingCategory.Planetwars; } using (var db = new ZkDataContext()) { if (battle.IsInGame) { teams = b.spring.LobbyStartContext?.Players.Where(u => !u.IsSpectator) .GroupBy(u => u.AllyID) .Select(x => x.Select(p => Account.AccountByName(db, p.Name))).ToList(); } else { switch (battle.Mode) { case PlasmaShared.AutohostMode.Game1v1: teams = b.Users.Values.Where(u => !u.IsSpectator) .GroupBy(u => u.Name) .Select(x => x.Select(p => Account.AccountByName(db, p.Name))).ToList(); break; case PlasmaShared.AutohostMode.Teams: await battle.SayBattle($"The battle will be balanced when it starts"); return; default: teams = b.Users.Values.Where(u => !u.IsSpectator) .GroupBy(u => u.AllyNumber) .Select(x => x.Select(p => Account.AccountByName(db, p.Name))).ToList(); break; } } if (teams.Count < 2) { await battle.SayBattle($"!predict needs at least two human teams to work"); return; } var chances = RatingSystems.GetRatingSystem(cat).PredictOutcome(teams, DateTime.UtcNow); for (int i = 0; i < teams.Count; i++) { await battle.SayBattle($"Team {teams[i].OrderByDescending(x => x.GetRating(cat).Elo).First().Name} has a {Math.Round(1000 * chances[i]) / 10}% chance to win"); } } }
public override LinkedListNode <Tag> Translate(TranslateContext context, LinkedListNode <Tag> self) { if (self.Previous?.Value is LiteralTag) // previous is contiguous text { context.Append("@"); return(self.Next); } var ender = self.Next.FirstNode(x => !(x.Value is LiteralTag || x.Value is UnderscoreTag)); var text = self.Next.GetOriginalContentUntilNode(ender); // get next string if (string.IsNullOrEmpty(text)) { context.Append("@"); return(self.Next); } int idx; for (idx = 0; idx < text.Length; idx++) { if (!Utils.ValidLobbyNameCharacter(text[idx])) { break; } } string remainder = null; string val = text; if (idx != 0 && idx < text.Length) { remainder = text.Substring(idx, text.Length - idx); val = text.Substring(0, idx); } if (string.IsNullOrEmpty(val)) { context.Append("@"); return(self.Next); } var db = new ZkDataContext(); char prefix = Char.ToLowerInvariant(val[0]); int id = 0; int.TryParse(val.Substring(1), out id); var fac = db.Factions.FirstOrDefault(x => x.Shortcut == val); if (fac == null && prefix == 'f') { fac = db.Factions.FirstOrDefault(x => x.FactionID == id); } if (fac != null) { context.Append(context.Html.PrintFaction(fac, false)); context.Append(remainder); return(ender); } var acc = Account.AccountByName(db, val); if (acc == null && prefix == 'u') { acc = db.Accounts.FirstOrDefault(x => x.AccountID == id); } if (acc != null) { context.Append(context.Html.PrintAccount(acc)); context.Append(remainder); return(ender); } var clan = db.Clans.FirstOrDefault(x => x.Shortcut == val); if (clan == null && prefix == 'c') { clan = db.Clans.FirstOrDefault(x => x.ClanID == id); } if (clan != null) { context.Append(context.Html.PrintClan(clan)); context.Append(remainder); return(ender); } // can't tag a battle by its name SpringBattle bat = null; if (prefix == 'b') { bat = db.SpringBattles.FirstOrDefault(x => x.SpringBattleID == id); } if (bat != null) { context.Append(context.Html.PrintBattle(bat)); context.Append(remainder); return(ender); } context.Append("@"); return(self.Next); }