protected override void GetDisplayContent(DiscordTarget target, out List <Tuple <string, DiscordLinkEmbed> > tagAndContent) { tagAndContent = new List <Tuple <string, DiscordLinkEmbed> >(); PlayerListChannelLink playerListLink = target as PlayerListChannelLink; if (playerListLink == null) { return; } string tag = BaseTag; string title = "Players"; string content = $"\n{MessageBuilder.Shared.GetPlayerList(playerListLink.UseLoggedInTime)}"; if (playerListLink.UsePlayerCount == true) { title = MessageBuilder.Shared.GetPlayerCount() + " Players Online"; } DiscordLinkEmbed embed = new DiscordLinkEmbed() .WithTitle(title) .WithDescription(content) .WithFooter(MessageBuilder.Discord.GetStandardEmbedFooter()); tagAndContent.Add(new Tuple <string, DiscordLinkEmbed>(tag, embed)); }
protected override void GetDisplayContent(DiscordTarget target, out List <Tuple <string, DiscordLinkEmbed> > tagAndContent) { tagAndContent = new List <Tuple <string, DiscordLinkEmbed> >(); ServerInfoChannel serverInfoChannel = target as ServerInfoChannel; if (serverInfoChannel == null) { return; } DiscordLinkEmbed content = MessageBuilder.Discord.GetServerInfo(GetServerInfoFlagForChannel(serverInfoChannel)); tagAndContent.Add(new Tuple <string, DiscordLinkEmbed>(BaseTag, content)); }
protected override void GetDisplayContent(DiscordTarget target, out List <Tuple <string, DiscordLinkEmbed> > tagAndContent) { tagAndContent = new List <Tuple <string, DiscordLinkEmbed> >(); List <string> trackedTrades = DLStorage.WorldData.PlayerTrackedTrades[(target as UserLink).Member.Id]; foreach (string trade in trackedTrades) { string result = SharedCommands.Trades(trade, out string matchedName, out bool isItem, out StoreOfferList groupedBuyOffers, out StoreOfferList groupedSellOffers); if (!string.IsNullOrEmpty(result)) { continue; // There was an error } DiscordLinkEmbed embedContent; MessageBuilder.Discord.FormatTrades(matchedName, isItem, groupedBuyOffers, groupedSellOffers, out embedContent); tagAndContent.Add(new Tuple <string, DiscordLinkEmbed>($"{BaseTag} [{matchedName}]", embedContent)); } }
public TargetDisplayData(DiscordTarget target) { this.Target = target; this.MessageIDs = new List <ulong>(); }
protected abstract void GetDisplayContent(DiscordTarget target, out List <Tuple <string, DiscordLinkEmbed> > tagAndContent);
protected sealed override async Task UpdateInternal(DiscordLink plugin, DLEventType trigger, object data) { // Avoid hitting the rate limitation by not allowig events that can be fired often to pass straight through. if ((trigger & HighFrequencyTriggerFlags) == trigger) { if (_HighFrequencyEventTimer == null) { _HighFrequencyEventTimer = new Timer(this.TriggerTimedUpdate, null, HighFrequencyEventDelayMS, Timeout.Infinite); } return; } if (_dirty || _targetDisplays.Count <= 0) { await FindMessages(plugin); if (_dirty || _targetDisplays.Count <= 0) { return; // If something went wrong, we should just retry later } } bool createdOrDestroyedMessage = false; List <string> matchedTags = new List <string>(); List <DiscordMessage> unmatchedMessages = new List <DiscordMessage>(); foreach (TargetDisplayData channelDisplayData in _targetDisplays) { DiscordTarget target = channelDisplayData.Target; ChannelLink channelLink = target as ChannelLink; UserLink userLink = target as UserLink; if (channelLink == null && userLink == null) { continue; } DiscordChannel targetChannel = null; if (channelLink != null) { // Get the channel and verify permissions DiscordGuild discordGuild = plugin.GuildByNameOrId(channelLink.DiscordGuild); if (discordGuild == null) { continue; } targetChannel = discordGuild.ChannelByNameOrId(channelLink.DiscordChannel); if (targetChannel == null) { continue; } if (!DiscordUtil.ChannelHasPermission(targetChannel, Permissions.ReadMessageHistory)) { continue; } } else if (userLink != null) { targetChannel = await userLink.Member.CreateDmChannelAsync(); } GetDisplayContent(target, out List <Tuple <string, DiscordLinkEmbed> > tagsAndContent); foreach (ulong messageID in channelDisplayData.MessageIDs) { DiscordMessage message = await DiscordUtil.GetMessageAsync(targetChannel, messageID); if (message == null) { _dirty = true; return; // We cannot know which messages are wrong and duplicates may be created if we continue. } if (!message.Content.StartsWith(BaseTag)) { continue; // The message belongs to a different display } bool found = false; foreach (var tagAndContent in tagsAndContent) { if (message.Content.Contains(tagAndContent.Item1)) { _ = DiscordUtil.ModifyAsync(message, tagAndContent.Item1, tagAndContent.Item2); matchedTags.Add(tagAndContent.Item1); found = true; ++_opsCount; break; } } if (!found) { unmatchedMessages.Add(message); } } // Delete the messages that are no longer relevant foreach (DiscordMessage message in unmatchedMessages) { DiscordUtil.DeleteAsync(message).Wait(); createdOrDestroyedMessage = true; ++_opsCount; } unmatchedMessages.Clear(); // Send the messages that didn't already exist foreach (var tagAndContent in tagsAndContent) { if (!matchedTags.Contains(tagAndContent.Item1)) { DiscordUtil.SendAsync(targetChannel, tagAndContent.Item1, tagAndContent.Item2).Wait(); createdOrDestroyedMessage = true; ++_opsCount; } } matchedTags.Clear(); } if (createdOrDestroyedMessage) { await FindMessages(plugin); } LastUpdateTime = DateTime.Now; }
protected override void GetDisplayContent(DiscordTarget target, out List <Tuple <string, DiscordLinkEmbed> > tagAndContent) { tagAndContent = new List <Tuple <string, DiscordLinkEmbed> >(); DiscordLinkEmbed embed = new DiscordLinkEmbed(); List <WorkParty> workParties = Registrars.Get <WorkParty>().All <WorkParty>().NonNull().Where(x => x.State == ProposableState.Active).ToList(); foreach (WorkParty workParty in workParties) { string tag = $"{BaseTag} [{workParty.Id}]"; embed.WithTitle(MessageUtil.StripTags(workParty.Name)); embed.WithFooter(MessageBuilder.Discord.GetStandardEmbedFooter()); // Workers string workersDesc = string.Empty; foreach (Laborer laborer in workParty.Laborers) { if (laborer.Citizen == null) { continue; } string creator = (laborer.Citizen == workParty.Creator) ? "Creator" : string.Empty; workersDesc += $"{laborer.Citizen.Name} ({creator})\n"; } if (string.IsNullOrWhiteSpace(workersDesc)) { workersDesc += "--- No Workers Registered ---"; } embed.AddField("Workers", workersDesc); // Work foreach (Work work in workParty.Work) { string workDesc = string.Empty; string workType = string.Empty; List <string> workEntries = new List <string>(); switch (work) { case LaborWork laborWork: { if (!string.IsNullOrEmpty(laborWork.ShortDescriptionRemainingWork)) { workType = $"Labor for {laborWork.Order.Recipe.RecipeName}"; workEntries.Add(MessageUtil.StripTags(laborWork.ShortDescriptionRemainingWork)); } break; } case WorkOrderWork orderWork: { workType = $"Materials for {orderWork.Order.Recipe.RecipeName}"; foreach (TagStack stack in orderWork.Order.MissingIngredients) { string itemName = string.Empty; if (stack.Item != null) { itemName = stack.Item.DisplayName; } else if (stack.StackObject != null) { itemName = stack.StackObject.DisplayName; } workEntries.Add($"{itemName} ({stack.Quantity})"); } break; } default: break; } if (workEntries.Count > 0) { foreach (string material in workEntries) { workDesc += $"- {material}\n"; } if (!string.IsNullOrWhiteSpace(workDesc)) { string percentDone = (work.PercentDone * 100.0f).ToString("N1", CultureInfo.InvariantCulture).Replace(".0", ""); embed.AddField($"\n {workType} (Weight: {work.Weight.ToString("F1")}) ({percentDone}% completed) \n", workDesc); } } } // Payment string paymentDesc = string.Empty; foreach (Payment payment in workParty.Payment) { string desc = string.Empty; switch (payment) { case CurrencyPayment currencyPayment: { float currencyAmountLeft = currencyPayment.Amount - currencyPayment.AmountPaid; if (currencyAmountLeft > 0.0f) { desc = $"Receive **{currencyAmountLeft.ToString("F1")} {currencyPayment.Currency.Name}**" + (currencyPayment.PayType == PayType.SplitByWorkPercent ? ", split based on work performed" : ", split evenly") + (currencyPayment.PayAsYouGo ? ", paid as work is performed." : ", paid when the project finishes."); } break; } case GrantTitlePayment titlePayment: { desc = $"Receive title `{MessageUtil.StripTags(titlePayment.Title.Name)}` if work contributed is at least *{titlePayment.MinContributedPercent.ToString("F1")}%*."; break; } case KnowledgeSharePayment knowledgePayment: { if (knowledgePayment.Skills.Entries.Count > 0) { desc = $"Receive knowledge of `{MessageUtil.StripTags(knowledgePayment.ShortDescription())}` if work contributed is at least *{knowledgePayment.MinContributedPercent.ToString("F1")}%*."; } break; } case ReputationPayment reputationPayment: { float reputationAmountLeft = reputationPayment.Amount - reputationPayment.AmountPaid; desc = $"Receive **{reputationAmountLeft.ToString("F1")} reputation** from *{workParty.Creator.Name}*" + (reputationPayment.PayType == PayType.SplitByWorkPercent ? ", split based on work performed" : ", split evenly") + (reputationPayment.PayAsYouGo ? ", paid as work is performed." : ", paid when the project finishes."); break; } default: break; } if (!string.IsNullOrEmpty(desc)) { paymentDesc += $"- {desc}\n"; } } if (!string.IsNullOrWhiteSpace(paymentDesc)) { embed.AddField("Payment", paymentDesc); } if (embed.Fields.Count > 0) { tagAndContent.Add(new Tuple <string, DiscordLinkEmbed>(tag, new DiscordLinkEmbed(embed))); } embed.ClearFields(); } }
protected override void GetDisplayContent(DiscordTarget target, out List <Tuple <string, DiscordLinkEmbed> > tagAndContent) { tagAndContent = new List <Tuple <string, DiscordLinkEmbed> >(); DiscordLinkEmbed embed = new DiscordLinkEmbed(); embed.WithFooter(MessageBuilder.Discord.GetStandardEmbedFooter()); foreach (Election election in EcoUtil.ActiveElections) { string tag = $"{BaseTag} [{election.Id}]"; embed.WithTitle(MessageUtil.StripTags(election.Name)); // Proposer name embed.AddField("Proposer", election.Creator.Name); // Time left embed.AddField("Time Left", TimeFormatter.FormatSpan(election.TimeLeft)); // Process embed.AddField("Process", MessageUtil.StripTags(election.Process.Name)); // Choices if (!election.BooleanElection && election.Choices.Count > 0) { string choiceDesc = string.Empty; foreach (ElectionChoice choice in election.Choices) { choiceDesc += $"{choice.Name}\n"; } embed.AddField("Choices", choiceDesc); } // Votes string voteDesc = string.Empty; if (!election.Process.AnonymousVoting) { foreach (RunoffVote vote in election.Votes) { string topChoiceName = null; int topChoiceID = vote.RankedVotes.FirstOrDefault(); foreach (ElectionChoice choice in election.Choices) { if (choice.ID == topChoiceID) { topChoiceName = choice.Name; break; } } voteDesc += $"{vote.Voter.Name} : {topChoiceName}\n"; } } else { voteDesc = "--- Anonymous Voting ---"; } if (string.IsNullOrEmpty(voteDesc)) { voteDesc = "--- No Votes Recorded ---"; } embed.AddField($"Votes ({election.TotalVotes})", voteDesc); if (embed.Fields.Count > 0) { tagAndContent.Add(new Tuple <string, DiscordLinkEmbed>(tag, new DiscordLinkEmbed(embed))); } embed.ClearFields(); } }
protected override void GetDisplayContent(DiscordTarget target, out List <Tuple <string, DiscordLinkEmbed> > tagAndContent) { tagAndContent = new List <Tuple <string, DiscordLinkEmbed> >(); IEnumerable <Currency> currencies = CurrencyManager.Currencies; var currencyTradesMap = DLStorage.WorldData.CurrencyToTradeCountMap; CurrencyChannelLink currencyLink = target as CurrencyChannelLink; if (currencyLink == null) { return; } void AddCurrencyEntry(Currency currency, List <Tuple <string, DiscordLinkEmbed> > tagAndContent) { DiscordLinkEmbed embed = new DiscordLinkEmbed(); embed.WithFooter(MessageBuilder.Discord.GetStandardEmbedFooter()); // Find and sort relevant accounts IEnumerable <BankAccount> accounts = BankAccountManager.Obj.Accounts.Where(acc => acc.GetCurrencyHoldingVal(currency) >= 1).OrderByDescending(acc => acc.GetCurrencyHoldingVal(currency)); var currencyEnumerator = accounts.GetEnumerator(); string topAccounts = string.Empty; for (int i = 0; i < currencyLink.MaxTopCurrencyHolderCount && currencyEnumerator.MoveNext(); ++i) { // Some bank accounts (e.g treasury) have no creator // Unbacked currencies has their creator owning infinity float currencyAmount = currencyEnumerator.Current.GetCurrencyHoldingVal(currency); if (currencyEnumerator.Current.Creator == null || currencyAmount == float.PositiveInfinity) { --i; continue; } topAccounts += $"**{currencyEnumerator.Current.GetCurrencyHoldingVal(currency):n0}** - {MessageUtil.StripTags(currencyEnumerator.Current.Name)} *({currencyEnumerator.Current.Creator.Name})*\n"; } // Fetch data int tradesCount = currencyTradesMap.Keys.Contains(currency.Id) ? currencyTradesMap[currency.Id] : 0; string backededItemName = currency.Backed ? $"{currency.BackingItem.DisplayName}" : "Personal"; // Build message string circulationDesc = $"**Total in circulation**: {currency.Circulation:n0}\n"; string tradesCountDesc = currencyLink.UseTradeCount ? $"**Total trades**: {tradesCount}\n" : string.Empty; string backedItemDesc = currencyLink.UseBackingInfo ? $"**Backing**: {backededItemName}\n" : string.Empty; string coinsPerItemDesc = (currencyLink.UseBackingInfo && currency.Backed) ? $"**Coins per item**: {currency.CoinsPerItem}\n" : string.Empty; string topAccountsDesc = $"**Top accounts**\n{topAccounts}"; embed.AddField(MessageUtil.StripTags(currency.Name), $"{circulationDesc}{tradesCountDesc}{backedItemDesc}{coinsPerItemDesc}\n{topAccountsDesc}"); tagAndContent.Add(new Tuple <string, DiscordLinkEmbed>($"{BaseTag} [{currency.Id}]", embed)); } // Figure out which displays to enable based on config bool mintedExists = currencies.Any(c => c.Backed); bool useMinted = currencyLink.UseMintedCurrency == CurrencyTypeDisplayCondition.Always || (mintedExists && currencyLink.UseMintedCurrency == CurrencyTypeDisplayCondition.MintedExists) || (!mintedExists && currencyLink.UseMintedCurrency == CurrencyTypeDisplayCondition.NoMintedExists); bool usePersonal = currencyLink.UsePersonalCurrency == CurrencyTypeDisplayCondition.Always || (mintedExists && currencyLink.UsePersonalCurrency == CurrencyTypeDisplayCondition.MintedExists) || (!mintedExists && currencyLink.UsePersonalCurrency == CurrencyTypeDisplayCondition.NoMintedExists); if (useMinted) { IEnumerable <Currency> mintedCurrencies = currencies.Where(c => c.Backed).OrderByDescending(c => currencyTradesMap.Keys.Contains(c.Id) ? currencyTradesMap[c.Id] : 0); var currencyEnumerator = mintedCurrencies.GetEnumerator(); for (int i = 0; i < currencyLink.MaxMintedCount && currencyEnumerator.MoveNext(); ++i) { AddCurrencyEntry(currencyEnumerator.Current, tagAndContent); } } if (usePersonal) { IEnumerable <Currency> personalCurrencies = currencies.Where(c => !c.Backed).OrderByDescending(c => currencyTradesMap.Keys.Contains(c.Id) ? currencyTradesMap[c.Id] : 0); var currencyEnumerator = personalCurrencies.GetEnumerator(); for (int i = 0; i < currencyLink.MaxPersonalCount && currencyEnumerator.MoveNext(); ++i) { AddCurrencyEntry(currencyEnumerator.Current, tagAndContent); } } }