public bool CanEdit(Account acc) { if (acc == null) return false; if (this.ForumThread.IsLocked) return false; if (this.AuthorAccountID == acc.AccountID || acc.IsZeroKAdmin || ( this.ForumThread.ForumCategory.ForumMode == ForumMode.Wiki && acc.CanEditWiki()) && ForumThread.ForumPosts.First().ForumPostID== ForumPostID) return true; else return false; }
public bool CanAccept(Account account) { if (account == null) return false; if (!account.HasFactionRight(x => x.RightDiplomacy)) return false; if (TreatyState == TreatyState.Proposed && AcceptingFactionID == account.FactionID) return true; return false; }
public static void PublishAccountData(this ProtocolExtension proto, Account acc) { var tas = proto.tas; if (acc != null && tas.ExistingUsers.ContainsKey(acc.Name)) { var data = new Dictionary<string, string> { { ProtocolExtension.Keys.Level.ToString(), acc.Level.ToString() }, { ProtocolExtension.Keys.EffectiveElo.ToString(), ((int)acc.EffectiveElo).ToString() }, { ProtocolExtension.Keys.Faction.ToString(), acc.Faction != null ? acc.Faction.Shortcut : "" }, { ProtocolExtension.Keys.Clan.ToString(), acc.Clan != null ? acc.Clan.Shortcut : "" }, { ProtocolExtension.Keys.Avatar.ToString(), acc.Avatar }, { ProtocolExtension.Keys.SpringieLevel.ToString(), acc.GetEffectiveSpringieLevel().ToString() }, }; if (acc.SteamID != null) data.Add(ProtocolExtension.Keys.SteamID.ToString(), acc.SteamID.ToString()); if (!string.IsNullOrEmpty(acc.SteamName) && acc.SteamName != acc.Name) data.Add(ProtocolExtension.Keys.DisplayName.ToString(), acc.SteamName); if (acc.IsZeroKAdmin) data.Add(ProtocolExtension.Keys.ZkAdmin.ToString(), "1"); if (acc.PunishmentsByAccountID.Any(x => !x.IsExpired && x.BanMute)) data.Add(ProtocolExtension.Keys.BanMute.ToString(), "1"); tas.Extensions.Publish(acc.Name, data); // if (acc.PunishmentsByAccountID.Any(x => x.BanExpires > DateTime.UtcNow && x.BanLobby)) tas.AdminKickFromLobby(acc.Name, "Banned"); var penalty = acc.PunishmentsByAccountID.FirstOrDefault(x => x.BanExpires > DateTime.UtcNow && x.BanLobby); if (penalty != null) tas.AdminKickFromLobby(acc.Name, string.Format("Banned until {0}, reason: {1}", penalty.BanExpires, penalty.Reason)); } }
static void Main(string[] args) { var db = new ZkDataContext(); var dict = db.Accounts.ToDictionary(x => x.AccountID); var path = args.Length > 0 ? args[0] : @"accounts.txt"; using (var r = new StreamReader(path)) { string line; while ((line = r.ReadLine()) != null) { Account ac = null; try { var parts = line.Split(' '); if (parts.Length < 9) { Trace.TraceError("Faulty line: ", line); continue; } var name = parts[0]; var pass = parts[1]; var flags = parts[2]; //var cookie = int.Parse(parts[3]); var lastLogin = ConvertTimestamp(double.Parse(parts[4]) / 1000); var lastIP = parts[5]; var registered = ConvertTimestamp(double.Parse(parts[6]) / 1000); var country = parts[7]; var id = int.Parse(parts[8]); Account de = null; dict.TryGetValue(id, out de); Console.WriteLine(string.Format("{0} {1}", id, name)); if (de == null || name != de.Name || pass != de.Password || registered != de.FirstLogin ) { if (de == null) { ac = new Account(); db.Accounts.InsertOnSubmit(ac); } else ac = db.Accounts.SingleOrDefault(x => x.LobbyID == id); ac.LobbyID = id; ac.Name = name; //ac.Flags = flags; ac.Password = pass; //ac.UserCookie = cookie; if (lastLogin.HasValue) ac.LastLogin = lastLogin.Value; //ac.LastIP = lastIP; if (registered.HasValue) ac.FirstLogin = registered.Value; if (ac.LastLogin == DateTime.MinValue) ac.LastLogin = registered ?? DateTime.UtcNow; //ac.Created = registered; ac.Country = country; Console.Write(" CHANGED!"); db.SubmitChanges(); } } catch (Exception e) { Console.WriteLine("Problem importing line: {0}: {1}", line, e); db = new ZkDataContext(); } } } }
public List<string> GetDefaultChannels(Account acc) { var ret = new List<string>() { "zk", GlobalConst.ModeratorChannel, GlobalConst.Top20Channel }; if (acc.Clan != null) ret.Add(acc.Clan.GetClanChannel()); if (acc.Faction != null) ret.Add(acc.Faction.Shortcut); return ret.Where(x => CanJoin(acc, x)).ToList(); }
public bool CanJoin(Account account) { if (account == null) return true; if (account.ClanID != null) return false; if (account.FactionID != null && account.FactionID != FactionID) return false; if (GlobalConst.MaxClanSkilledSize.HasValue && Accounts.Count() >= GlobalConst.MaxClanSkilledSize) return false; else return true; }
bool CanJoin(Account acc, string channel) { if (channel == GlobalConst.ModeratorChannel) return acc.IsZeroKAdmin; else if (channel == "zkerror") return acc.IsZeroKAdmin; else if (channel == GlobalConst.Top20Channel) return IsTop20(acc.AccountID); else if (clanChannels.ContainsKey(channel)) return acc.ClanID == clanChannels[channel].ClanID; else if (factionChannels.ContainsKey(channel)) return acc.Level >= GlobalConst.FactionChannelMinLevel && acc.FactionID == factionChannels[channel].FactionID; return true; }
public List<string> GetDefaultChannels(Account acc) { if (acc.IsBot) return new List<string>() { "bots" }; var ret = new List<string>() { "zk", GlobalConst.ModeratorChannel, GlobalConst.Top20Channel }; if (acc.Clan != null) ret.Add(acc.Clan.GetClanChannel()); if (acc.Faction != null && GlobalConst.PlanetWarsMode != PlanetWarsModes.AllOffline) ret.Add(acc.Faction.Shortcut); return ret.Where(x => CanJoin(acc, x)).ToList(); }
public bool CanCancel(Account account) { if (account == null) return false; if (!account.HasFactionRight(x => x.RightDiplomacy)) return false; if (TurnsRemaining == null || TreatyState == TreatyState.Proposed) { if (ProposingFactionID == account.FactionID || AcceptingFactionID == account.FactionID) return true; // can canel } return false; }
private static void LogIP(ZkDataContext db, Account acc, string ip) { if (IsLanIP(ip)) return; var entry = acc.AccountIPs.FirstOrDefault(x => x.IP == ip); if (entry == null) { entry = new AccountIP { AccountID = acc.AccountID, IP = ip, FirstLogin = DateTime.UtcNow }; db.AccountIPs.InsertOnSubmit(entry); } entry.LoginCount++; entry.LastLogin = DateTime.UtcNow; }
private static void LogUserID(ZkDataContext db, Account acc, long user_id) { if (user_id != 0) { var entry = acc.AccountUserIDs.FirstOrDefault(x => x.UserID == user_id); if (entry == null) { entry = new AccountUserID { AccountID = acc.AccountID, UserID = user_id, FirstLogin = DateTime.UtcNow }; db.AccountUserIDs.InsertOnSubmit(entry); } entry.LoginCount++; entry.LastLogin = DateTime.UtcNow; } }
private LoginCheckerResponse BlockLogin(string reason, Account acc, string ip, long user_id) { LogIpFailure(ip); var str = $"Login denied for {acc.Name} IP:{ip} ID:{user_id} reason: {reason}"; Talk(str); Trace.TraceInformation(str); return new LoginCheckerResponse(LoginResponse.Code.Banned, reason); }
private bool HasVpn(string ip, Account acc, ZkDataContext db) { // check user IP against http://dnsbl.tornevall.org // does not catch all smurfs // mostly false positives, do not use var reversedIP = string.Join(".", ip.Split('.').Reverse().ToArray()); try { var resolved = Dns.GetHostEntry(string.Format("{0}.dnsbl.tornevall.org", reversedIP)).AddressList; if (resolved.Length > 0) { Talk(string.Format("User {0} {3} has IP {1} on dnsbl.tornevall.org ({2} result/s)", acc.Name, ip, resolved.Length, string.Format("{1}/Users/Detail/{0}", acc.AccountID, GlobalConst.BaseSiteUrl))); return true; } } catch (SocketException sockEx) { // not in database, do nothing } try { //for (int i = 0; i <= 1; i++) { for (var i = 1; i <= 1; i++) { var whois = new Whois(); var data = whois.QueryByIp(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(); //Trace.TraceInformation($"VPN check for USER {acc.Name}\nnetname: {data["netname"]}\norgname: {data["org-name"]}\ndescr: {data["descr"]}\nabuse-mailbox: {data["abuse-mailbox"]}", false); if (blockedHosts.Any(x => data["abuse-mailbox"].Contains(x)) || blockedHosts.Any(x => data["notify"].Contains(x))) return true; foreach (var 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)) return true; // this can throw a SocketException, so make sure we block login already if we ought to try { var hostname = Dns.GetHostEntry(ip)?.HostName; if (blockedHosts.Any(hostname.Contains)) return true; } catch (SocketException) { } } } catch (Exception ex) { Trace.TraceError("VPN check error for user {0}: {1}", acc.Name, ex); } return false; }
static void SpecPlayerOnCondition(PlayerTeam player, Account account, string userMessage, ZkLobbyServer.ZkLobbyServer server) { player.IsSpectator = true; server.GhostPm(account.Name, userMessage); }
public static void UpdateUserFromAccount(User user, Account acc) { user.Name = acc.Name; user.DisplayName = acc.SteamName; user.Avatar = acc.Avatar; user.Level = acc.Level; user.EffectiveMmElo = (int)acc.EffectiveMmElo; user.RawMmElo = (int)acc.EloMm; user.CompetitiveRank = acc.CompetitiveRank; user.SteamID = (ulong?)acc.SteamID; user.IsAdmin = acc.IsZeroKAdmin; user.IsBot = acc.IsBot; user.Country = acc.Country; user.Faction = acc.Faction != null ? acc.Faction.Shortcut : null; user.Clan = acc.Clan != null ? acc.Clan.Shortcut : null; user.AccountID = acc.AccountID; Interlocked.Increment(ref user.SyncVersion); user.BanMute = Punishment.GetActivePunishment(acc.AccountID, user.IpAddress, 0, x => x.BanMute) != null; user.BanSpecChat = Punishment.GetActivePunishment(acc.AccountID, user.IpAddress, 0, x => x.BanSpecChat) != null; }
private static bool ValidateSiteAuthToken(Account acc, string token) { return acc.VerifyPassword(token); }
public static MvcHtmlString AccountAvatar(this HtmlHelper helper, Account account) { if (account.IsDeleted) return null; return new MvcHtmlString(string.Format("<img src='/img/avatars/{0}.png' class='avatar'>", account.Avatar)); }
public bool CanVoteRecall(Account targetAccount, RoleType roleType) { if (roleType.IsVoteable && targetAccount.FactionID == FactionID && (!roleType.IsClanOnly || targetAccount.ClanID == ClanID)) return true; else return false; }
public static void SendLobbyMessage(Account account, string text) { Global.Nightwatch.Auth.SendLobbyMessage(account, text); }
public void SendLobbyMessage(Account account, string text) { User ex; if (client.ExistingUsers.TryGetValue(account.Name, out ex)) client.Say(SayPlace.User, account.Name, text, false); else { var message = new LobbyMessage { SourceLobbyID = client.MyUser != null ? client.MyUser.AccountID : 0, SourceName = client.UserName, Created = DateTime.UtcNow, Message = text, TargetName = account.Name, TargetLobbyID = account.AccountID }; using (var db = new ZkDataContext()) { db.LobbyMessages.InsertOnSubmit(message); db.SubmitChanges(); } } }
public static MvcHtmlString PrintDropships(this HtmlHelper helper, Account account) { if (account != null && account.Faction != null) { var ownShips = account.GetDropshipsAvailable(); var factionShips = account.Faction.Dropships; return new MvcHtmlString( string.Format( "<span nicetitle='Dropships available to you/owned by faction'><img src='{0}' class='icon20'/>{1} / {2}</span>", account.Faction.GetShipImageUrl(), Math.Floor(ownShips), Math.Floor(factionShips))); } else return null; }
public static MvcHtmlString PrintContributorStar(this HtmlHelper helper, Account account, bool large = false) { var star = ""; var contribs = account.ContributionsByAccountID.ToList(); var total = 0; foreach (var contrib in contribs) total += contrib.KudosValue; if (total >= GlobalConst.KudosForGold) star = "star_yellow"; else if (total >= GlobalConst.KudosForSilver) star = "star_white"; else if (total >= GlobalConst.KudosForBronze) star = "star_brown"; else return new MvcHtmlString(""); if (large == false) star = star + "_small"; return new MvcHtmlString(string.Format("<a href='/Contributions' target='_blank' ><img src='/img/stars/{0}.png' alt='Donator star'/></a>", star)); }
public static void ProgressCampaign(ZkDataContext db, Account acc, Mission mission, bool completeNext = false, string missionVars = "") { CampaignPlanet planet = db.CampaignPlanets.FirstOrDefault(p => p.MissionID == mission.MissionID); if (planet != null) { AccountCampaignProgress progress = acc.AccountCampaignProgress.FirstOrDefault(x => x.PlanetID == planet.PlanetID && x.CampaignID == planet.CampaignID); bool alreadyCompleted = false; int accountID = acc.AccountID; int campID = planet.CampaignID; Campaign camp = planet.Campaign; List<CampaignPlanet> unlockedPlanets = new List<CampaignPlanet>(); List<CampaignJournal> unlockedJournals = new List<CampaignJournal>(); // start with processing the mission vars, if there are any byte[] missionVarsAsByteArray = System.Convert.FromBase64String(missionVars); string missionVarsDecoded = System.Text.Encoding.UTF8.GetString(missionVarsAsByteArray); foreach (string kvpRaw in missionVarsDecoded.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) { string kvpRaw2 = kvpRaw.Trim(); string key = "", value = ""; string[] kvpSplit = kvpRaw2.Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries); if (kvpSplit.Length == 2) { key = kvpSplit[0].Trim(); value = kvpSplit[1].Trim(); } else { throw new Exception("Invalid key-value pair in decoded mission vars: " + missionVarsDecoded); } if (!(string.IsNullOrEmpty(key) || string.IsNullOrEmpty(value))) { CampaignVar cv = camp.CampaignVars.First(x => x.KeyString == key); AccountCampaignVar acv = acc.AccountCampaignVars.FirstOrDefault(x => x.CampaignID == campID && x.VarID == cv.VarID); if (acv == null) { db.AccountCampaignVars.InsertOnSubmit(new AccountCampaignVar() { AccountID = accountID, CampaignID = campID, VarID = cv.VarID, Value = value }); } else acv.Value = value; } } //reload DB - this allows the vars submitted this session to be used by the following code db.SaveChanges(); db = new ZkDataContext(); acc = db.Accounts.First(x => x.AccountID == accountID); // now we unlock planets and journal entries // first mark this planet as completed - but only if it's already unlocked if (progress != null) { alreadyCompleted = progress.IsCompleted; } else if (planet.StartsUnlocked) { progress = new AccountCampaignProgress() { AccountID = accountID, CampaignID = campID, PlanetID = planet.PlanetID, IsCompleted = false, IsUnlocked = true }; db.AccountCampaignProgress.InsertOnSubmit(progress); } if (progress != null && planet.IsUnlocked(accountID)) { progress.IsCompleted = true; // unlock planets made available by completing this one var links = camp.CampaignLinks.Where(x => x.UnlockingPlanetID == planet.PlanetID); foreach (CampaignLink link in links) { CampaignPlanet toUnlock = link.PlanetToUnlock; bool proceed = true; var requiredVars = toUnlock.CampaignPlanetVars; if (requiredVars.Count() == 0) proceed = true; else { foreach (CampaignPlanetVar variable in requiredVars) { AccountCampaignVar accountVar = acc.AccountCampaignVars.FirstOrDefault(x => x.CampaignID == campID && x.VarID == variable.RequiredVarID); if (!(accountVar != null && accountVar.Value == variable.RequiredValue)) { proceed = false; break; // failed to meet var requirement, stop here } } } if (proceed) // met requirements for unlocking planet { AccountCampaignProgress progress2 = toUnlock.AccountCampaignProgress.FirstOrDefault(x => x.CampaignID == campID && x.AccountID == accountID); if (progress2 == null) { progress2 = new AccountCampaignProgress() { AccountID = accountID, CampaignID = campID, PlanetID = toUnlock.PlanetID, IsCompleted = completeNext, IsUnlocked = true }; db.AccountCampaignProgress.InsertOnSubmit(progress2); unlockedPlanets.Add(toUnlock); } else if (!progress2.IsUnlocked) { progress2.IsUnlocked = true; unlockedPlanets.Add(toUnlock); } } } } // unlock journals var journalsWithVars = db.CampaignJournals.Where(x => x.CampaignID == campID && x.CampaignJournalVars.Any()); foreach (CampaignJournal journal in journalsWithVars) { bool proceed = true; var requiredVars = journal.CampaignJournalVars.Where(x => x.CampaignID == campID).ToList(); foreach (CampaignJournalVar variable in requiredVars) { AccountCampaignVar accountVar = acc.AccountCampaignVars.FirstOrDefault(x => x.CampaignID == campID && x.VarID == variable.RequiredVarID); if (!(accountVar != null && accountVar.Value == variable.RequiredValue)) { proceed = false; break; // failed to meet var requirement, stop here } } if (proceed) // met requirements for unlocking journal { AccountCampaignJournalProgress jp = journal.AccountCampaignJournalProgress.FirstOrDefault(x => x.AccountID == accountID); if (jp == null) { jp = new AccountCampaignJournalProgress() { AccountID = accountID, CampaignID = campID, JournalID = journal.JournalID, IsUnlocked = true }; db.AccountCampaignJournalProgress.InsertOnSubmit(jp); unlockedJournals.Add(journal); } else if (!jp.IsUnlocked) { jp.IsUnlocked = true; unlockedJournals.Add(journal); } } } if (!alreadyCompleted) { System.Console.WriteLine("Planet completed: {0}", planet); foreach (CampaignJournal journal in db.CampaignJournals.Where(x => x.CampaignID == campID && x.CampaignPlanet.PlanetID == planet.PlanetID && x.UnlockOnPlanetCompletion)) { unlockedJournals.Add(journal); } } foreach (CampaignPlanet unlocked in unlockedPlanets) { System.Console.WriteLine("Planet unlocked: {0}", unlocked); foreach (CampaignJournal journal in db.CampaignJournals.Where(x => x.CampaignID == campID && x.CampaignPlanet.PlanetID == unlocked.PlanetID && x.UnlockOnPlanetUnlock)) { unlockedJournals.Add(journal); } } foreach (CampaignJournal uj in unlockedJournals) { System.Console.WriteLine("{1} - Journal entry unlocked: {0}", uj, uj.CampaignPlanet); } db.SaveChanges(); } }
static void SpecPlayerOnCondition(PlayerTeam player, Account account, string userMessage) { player.IsSpectator = true; AuthServiceClient.SendLobbyMessage(account, userMessage); }
public static MvcHtmlString PrintMetal(this HtmlHelper helper, Account account) { if (account != null && account.Faction != null) { var ownMetal = account.GetMetalAvailable(); var factionMetal = Math.Floor(account.Faction.Metal); return new MvcHtmlString( string.Format( "<span style='color:#00FFFF' nicetitle='Metal available to you/owned by faction'><img src='{0}' width='20' height='20'/>{1} / {2}</span>", GlobalConst.MetalIcon, Math.Floor(ownMetal), Math.Floor(factionMetal))); } else return null; }
public static MvcHtmlString PrintAccount(this HtmlHelper helper, Account account, bool colorize = true, bool ignoreDeleted = false) { if (account == null) return new MvcHtmlString("Nobody"); else if (account.IsDeleted && !ignoreDeleted) return new MvcHtmlString("{redacted}"); else { var clanStr = ""; var url = Global.UrlHelper(); if (account.Clan != null) { clanStr = string.Format("<a href='{1}' nicetitle='$clan${2}'><img src='{0}' width='16'/></a>", account.Clan.GetImageUrl(), url.Action("Detail", "Clans", new { id = account.ClanID }), account.ClanID); } else if (account.Faction != null) clanStr = string.Format("<img src='{0}' width='16'/>", account.Faction.GetImageUrl()); var dudeStr = ""; if (account.IsZeroKAdmin) dudeStr = "<img src='/img/police.png' class='icon16' alt='Admin' />"; else if (account.EffectiveElo < 1400) dudeStr = "<img src='/img/smurf.png' class='icon16' alt='Newbie' />"; else if (account.EffectiveElo < 1600) dudeStr = "<img src='/img/user.png' class='icon16' alt='Dude' />"; else if (account.EffectiveElo < 1800) dudeStr = "<img src='/img/soldier.png' class='icon16' alt='Soldier' />"; else dudeStr = "<img src='/img/napoleon.png' class='icon16' alt='Napoleon' />"; var clampedLevel = account.Level/10 + 1; if (clampedLevel < 1) clampedLevel = 1; if (clampedLevel > 9) clampedLevel = 9; string color = Faction.FactionColor(account.Faction, Global.FactionID); if (String.IsNullOrEmpty(color)) color = "#B0D0C0"; return new MvcHtmlString( string.Format( "<img src='/img/flags/{0}.png' class='flag' height='11' width='16' alt='{0}'/><img src='/img/ranks/{1}.png' class='icon16' alt='rank' />{5}{6}<a href='/Users/Detail/{2}' style='color:{3}' nicetitle='$user${2}'>{4}</a>", account.Country != "??" ? account.Country : "unknown", clampedLevel, account.AccountID, colorize ? color : "", account.Name, clanStr, dudeStr)); } }
public bool CanRecall(Account targetAccount, RoleType roleType) { if (targetAccount.AccountID != AccountID && targetAccount.FactionID == FactionID && (!roleType.IsClanOnly || targetAccount.ClanID == ClanID)) { return AccountRolesByAccountID.Any( x => x.RoleType.RoleTypeHierarchiesByMasterRoleTypeID.Any(y => y.CanRecall && y.SlaveRoleTypeID == roleType.RoleTypeID)); } else return false; }
public static MvcHtmlString PrintWarps(this HtmlHelper helper, Account account) { if (account != null && account.Faction != null) { var ownWarps = account.GetWarpAvailable(); var factionWarps = account.Faction.Warps; return new MvcHtmlString( string.Format( "<span nicetitle='Warp cores available to you/owned by faction'><img src='{0}' class='icon20'/>{1} / {2}</span>", GlobalConst.WarpIcon, Math.Floor(ownWarps), Math.Floor(factionWarps))); } else return null; }
public static IEnumerable<Poll> ValidPolls(Account acc, ZkDataContext db = null) { if (db == null) db = new ZkDataContext(); var clanID = acc?.ClanID; var facID = acc?.FactionID; return db.Polls.Where( x => (x.ExpireBy == null || x.ExpireBy > DateTime.UtcNow) && (x.RestrictClanID == null || x.RestrictClanID == clanID) && (x.RestrictFactionID == null || x.RestrictFactionID == facID)); }
public static MvcHtmlString PrintTotalPostRating(this HtmlHelper helper, Account account) { return new MvcHtmlString(string.Format("{0} / {1}", string.Format("<font color='LawnGreen'>+{0}</font>", account.ForumTotalUpvotes), string.Format("<font color='Tomato'>-{0}</font>", account.ForumTotalDownvotes) )); }