Exemple #1
0
        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));
        }
Exemple #3
0
        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));
            }
        }
Exemple #4
0
 public TargetDisplayData(DiscordTarget target)
 {
     this.Target     = target;
     this.MessageIDs = new List <ulong>();
 }
Exemple #5
0
 protected abstract void GetDisplayContent(DiscordTarget target, out List <Tuple <string, DiscordLinkEmbed> > tagAndContent);
Exemple #6
0
        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();
            }
        }
Exemple #9
0
        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);
                }
            }
        }