Esempio n. 1
0
        public async Task Execute(IJobExecutionContext context)
        {
            try
            {
                // Log that we're about to begin a check
                await DiscordBot.LoggingChannel.SendMessageAsync("**[BCAT]** Beginning check");

                // Download the latest Topic
                Topic topic = await BcatApi.GetDataTopic(Program.TITLE_ID, Program.PASSPHRASE);

                // Create the target folder name
                string targetFolder = string.Format(Program.LOCAL_OLD_DATA_DIRECTORY, DateTime.Now.ToString(Program.FOLDER_DATE_TIME_FORMAT));

                // Check if this the first run
                if (!Configuration.LoadedConfiguration.FirstRunCompleted)
                {
                    // Log that this is the first run of BCAT
                    await DiscordBot.LoggingChannel.SendMessageAsync("**[BCAT]** First run");

                    // Download all data
                    Dictionary <string, byte[]> downloadedData = await BcatCheckerUtils.DownloadAllData(topic, Program.TITLE_ID, Program.PASSPHRASE, targetFolder);

                    // Loop over all data
                    foreach (KeyValuePair <string, byte[]> pair in downloadedData)
                    {
                        // Get the FileType
                        FileType fileType = FileTypeExtensions.GetTypeFromName(pair.Key);

                        // Check if this is a container
                        if (fileType.IsContainer())
                        {
                            // Create a Container instance
                            Nintendo.SmashUltimate.Bcat.Container container = CreateSmashContainerInstance(fileType, pair.Value);

                            // Add this to the container cache
                            ContainerCache.AddFile(container, Path.GetFileName(pair.Key), pair.Value);
                        }
                        else
                        {
                            // Write this file out to the common file cache
                            File.WriteAllBytes(Path.Combine(Program.LOCAL_COMMON_CACHE_DIRECTORY, Path.GetFileName(pair.Key)), pair.Value);
                        }
                    }

                    // Save the configuration
                    Configuration.LoadedConfiguration.FirstRunCompleted = true;
                    Configuration.LoadedConfiguration.Write();

                    // Write out the topic
                    File.WriteAllBytes(Program.LOCAL_LAST_TOPIC, MessagePackSerializer.Serialize(topic));

                    // Log that we're about to begin a check
                    await DiscordBot.LoggingChannel.SendMessageAsync("**[BCAT]** First run complete");

                    return;
                }

                // Load the old Topic
                Topic oldTopic = MessagePackSerializer.Deserialize <Topic>(File.ReadAllBytes(Program.LOCAL_LAST_TOPIC));

#if DEBUG
                if (!Configuration.LoadedConfiguration.IsProduction)
                {
                    /*foreach (Bcat.Directory dir in oldTopic.Directories)
                     * {
                     *  if (dir.Name == "line_news")
                     *  {
                     *      Data dbgData = dir.Data.FirstOrDefault();
                     *      if (dbgData == null)
                     *      {
                     *          continue;
                     *      }
                     *      dir.Data.Remove(dbgData);
                     *      //dbgData.Digest = "deadbeef";
                     *  }
                     * }*/
                }
#endif

                // Get the differences
                List <KeyValuePair <DifferenceType, string> > differences = BcatCheckerUtils.GetTopicChanges(oldTopic, topic);

                // Check if there aren't any
                if (differences.Count == 0)
                {
                    // Nothing to do here
                    goto finished;
                }

                // Download all data
                Dictionary <string, byte[]> data = await BcatCheckerUtils.DownloadAllData(topic, Program.TITLE_ID, Program.PASSPHRASE, targetFolder);

                // Loop over every difference
                foreach (KeyValuePair <DifferenceType, string> pair in differences)
                {
                    // Log the difference
                    await DiscordBot.LoggingChannel.SendMessageAsync("**[BCAT]** diff: ``" + pair.Value + "`` (" + pair.Key.ToString() + ")");

                    // Get the FileType
                    FileType fileType = FileTypeExtensions.GetTypeFromName(pair.Value);

                    // Declare a variable to hold the method parameters
                    object[] parameters;

                    if (pair.Key == DifferenceType.Added)
                    {
                        // Get the raw file
                        byte[] rawFile = data[pair.Value];

                        // Check if this is a Container
                        if (fileType.IsContainer())
                        {
                            // Create a Container instance
                            Nintendo.SmashUltimate.Bcat.Container addedContainer = CreateSmashContainerInstance(fileType, data[pair.Value]);

                            // Add this to the container cache
                            ContainerCache.AddFile(addedContainer, Path.GetFileName(pair.Value), rawFile);

                            // Set the method parameters
                            parameters = new object[] { addedContainer };
                        }
                        else
                        {
                            // Write this file out to the common file cache
                            File.WriteAllBytes(Path.Combine(Program.LOCAL_COMMON_CACHE_DIRECTORY, Path.GetFileName(pair.Value)), data[pair.Value]);

                            // Set the method parameters
                            parameters = new object[] { rawFile };
                        }
                    }
                    else if (pair.Key == DifferenceType.Changed)
                    {
                        // Get the raw file
                        byte[] rawFile = data[pair.Value];

                        // Check if this is a Container
                        if (fileType.IsContainer())
                        {
                            // Create a Container instance
                            Nintendo.SmashUltimate.Bcat.Container addedContainer = CreateSmashContainerInstance(fileType, data[pair.Value]);

                            // Overwrite this to the container cache
                            Nintendo.SmashUltimate.Bcat.Container previousContainer = ContainerCache.OverwriteFile(addedContainer, Path.GetFileName(pair.Value), rawFile);

                            // Set the method parameters
                            parameters = new object[] { previousContainer, addedContainer };
                        }
                        else
                        {
                            // Construct the commoon cache path
                            string path = Path.Combine(Program.LOCAL_COMMON_CACHE_DIRECTORY, Path.GetFileName(pair.Value));

                            // Load the old file
                            byte[] previousRawFile = File.ReadAllBytes(path);

                            // Write this file out to the common file cache
                            File.WriteAllBytes(path, data[pair.Value]);

                            // Set the method parameters
                            parameters = new object[] { previousRawFile, rawFile };
                        }
                    }
                    else // Removed
                    {
                        // TODO: discord print
                        continue;
                    }

                    // Call every difference handler
                    await BcatCheckerUtils.CallDifferenceHandlers((int)fileType, pair.Key, parameters);
                }

                // Write out the Topic
                File.WriteAllBytes(Program.LOCAL_LAST_TOPIC, MessagePackSerializer.Serialize(topic));

finished:
                await DiscordBot.LoggingChannel.SendMessageAsync("**[BCAT]** Check complete");
            }
            catch (Exception exception)
            {
                // Notify the logging channel
                await DiscordUtil.HandleException(exception, $"in ``BcatCheckerJob``");
            }
        }
Esempio n. 2
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;
        }
Esempio n. 3
0
        private async Task PostAccumulatedTrades()
        {
            foreach (List <CurrencyTrade> accumulatedTrades in _accumulatedTrades.Values)
            {
                if (accumulatedTrades.Count <= 0)
                {
                    continue;
                }

                CurrencyTrade firstTrade = accumulatedTrades[0];

                DiscordEmbedBuilder builder = new DiscordEmbedBuilder();
                string leftName             = firstTrade.Citizen.Name;
                string rightName            = firstTrade.Citizen.Id == firstTrade.Buyer.Id ? firstTrade.Seller.Name : firstTrade.Buyer.Name;
                builder.Title = leftName + " traded with " + rightName;

                string boughtItemsDesc = string.Empty;
                float  boughtTotal     = 0;
                string soldItemsDesc   = string.Empty;
                float  soldTotal       = 0;
                foreach (CurrencyTrade trade in accumulatedTrades)
                {
                    if (trade.BoughtOrSold == Shared.Items.BoughtOrSold.Buying)
                    {
                        boughtItemsDesc += trade.NumberOfItems + " X " + trade.ItemUsed.DisplayName + " * " + trade.CurrencyAmount / trade.NumberOfItems + " = " + trade.CurrencyAmount + "\n";
                        boughtTotal     += trade.CurrencyAmount;
                    }
                    else if (trade.BoughtOrSold == Shared.Items.BoughtOrSold.Selling)
                    {
                        soldItemsDesc += trade.NumberOfItems + " X " + trade.ItemUsed.DisplayName + " * " + trade.CurrencyAmount / trade.NumberOfItems + " = " + trade.CurrencyAmount + "\n";
                        soldTotal     += trade.CurrencyAmount;
                    }
                }

                if (!boughtItemsDesc.IsEmpty())
                {
                    boughtItemsDesc += "\nTotal = " + boughtTotal.ToString("n2");
                    builder.AddField("Bought", boughtItemsDesc);
                }

                if (!soldItemsDesc.IsEmpty())
                {
                    soldItemsDesc += "\nTotal = " + soldTotal.ToString("n2");
                    builder.AddField("Sold", soldItemsDesc);
                }

                float subTotal = soldTotal - boughtTotal;
                char  sign     = (subTotal > 0.0f ? '+' : '-');
                builder.AddField("Total", sign + Math.Abs(subTotal).ToString("n2") + " " + firstTrade.Currency.Name);

                DiscordLink plugin = DiscordLink.Obj;
                if (plugin == null)
                {
                    return;
                }
                foreach (ChannelLink tradeChannel in DLConfig.Data.TradeChannels)
                {
                    if (!tradeChannel.IsValid())
                    {
                        continue;
                    }
                    DiscordGuild discordGuild = plugin.GuildByNameOrId(tradeChannel.DiscordGuild);
                    if (discordGuild == null)
                    {
                        continue;
                    }
                    DiscordChannel discordChannel = discordGuild.ChannelByNameOrId(tradeChannel.DiscordChannel);
                    if (discordChannel == null)
                    {
                        continue;
                    }

                    _ = DiscordUtil.SendAsync(discordChannel, "", builder.Build());
                }
            }
            _accumulatedTrades.Clear();
        }
Esempio n. 4
0
        public async Task Execute(IJobExecutionContext context)
        {
            try
            {
                if (Configuration.LoadedConfiguration.FirstRunCompleted)
                {
                    throw new Exception("Attempting to do first run more than once");
                }

                foreach (KeyValuePair <RomType, BcatPair> bcatPairEntry in Program.BcatPairs)
                {
                    // Log that we're about to begin a check
                    await DiscordBot.LoggingChannel.SendMessageAsync("**[BCAT]** Beginning topic download for " + bcatPairEntry.Key.ToString());

                    // Download the latest Topic
                    Topic topic = await BcatApi.GetDataTopic(bcatPairEntry.Value.TitleId, bcatPairEntry.Value.Passphrase);

                    // Create the target folder name
                    string targetFolder = string.Format(Program.LOCAL_OLD_DATA_DIRECTORY, DateTime.Now.ToString(Program.FOLDER_DATE_TIME_FORMAT), bcatPairEntry.Key.ToString());

                    // Download all data
                    Dictionary <string, byte[]> downloadedData = await BcatCheckerUtils.DownloadAllData(topic, bcatPairEntry.Value.TitleId, bcatPairEntry.Value.Passphrase, targetFolder);

                    // Loop over all data
                    foreach (KeyValuePair <string, byte[]> dataPair in downloadedData)
                    {
                        // Get the FileType
                        FileType fileType = FileTypeExtensions.GetTypeFromFilePath(dataPair.Key);

                        // Populate the FileCache directories based on the FileType
                        string path;
                        switch (fileType)
                        {
                        case FileType.VersusSetting:
                            path = string.Format(FileCache.VERSUS_SETTING_PATH, bcatPairEntry.Key.ToString());
                            break;

                        case FileType.CoopSetting:
                            // Only write the CoopSetting file once
                            if (bcatPairEntry.Key != RomType.NorthAmerica)
                            {
                                continue;
                            }

                            path = FileCache.COOP_SETTING_PATH;

                            break;

                        case FileType.FestivalByaml:
                            // Deserialize the byaml to get the ID
                            dynamic byaml = ByamlLoader.GetByamlDynamic(dataPair.Value);

                            // Generate the path
                            path = string.Format(FileCache.FESTIVAL_SETTING_PATH, bcatPairEntry.Key.ToString(), byaml["FestivalId"]);

                            break;

                        default:
                            continue;
                        }

                        // Create the directories if needed
                        System.IO.Directory.CreateDirectory(Path.GetDirectoryName(path));

                        // Write the file
                        File.WriteAllBytes(path, dataPair.Value);
                    }

                    // Write out the topic
                    File.WriteAllBytes(string.Format(Program.LOCAL_LAST_TOPIC, bcatPairEntry.Key.ToString()), MessagePackSerializer.Serialize(topic));

                    // Set the last data download directory
                    (Configuration.LoadedConfiguration as JelonzoBotConfiguration).LastDownloadPaths[bcatPairEntry.Key] = targetFolder;

                    // Log that the first run is done
                    await DiscordBot.LoggingChannel.SendMessageAsync($"**[BCAT]** First run complete for {bcatPairEntry.Key.ToString()}");
                }

                // Save the configuration
                Configuration.LoadedConfiguration.FirstRunCompleted = true;
                Configuration.LoadedConfiguration.Write();

                // Initialize the FileCache
                FileCache.Initialize();
            }
            catch (Exception exception)
            {
                // Notify the logging channel
                await DiscordUtil.HandleException(exception, $"in ``BcatCheckerJob``");
            }

            await QuartzScheduler.ScheduleJob <BcatCheckerJob>("Normal", Configuration.LoadedConfiguration.JobSchedules["Bcat"]);
        }
        public override async Task <bool> HandleTextMessage(SocketMessage message)
        {
            // Get the guild
            SocketGuild guild = (message.Channel as SocketGuildChannel).Guild;

            // Parse the channel ID
            ulong channelId;

            try
            {
                channelId = MentionUtils.ParseChannel(message.Content);
            }
            catch (ArgumentException)
            {
                await DiscordUtil.SendErrorMessageByLocalizedDescription(guild, this.Channel, "discord.setup.enter_channel.bad_channel");

                return(false);
            }

            // Get the channel
            SocketChannel foundChannel = DiscordBot.GetChannel(channelId);

            // Check if it exists
            if (foundChannel == null)
            {
                await DiscordUtil.SendErrorMessageByLocalizedDescription(guild, this.Channel, "discord.setup.enter_channel.bad_channel");

                return(false);
            }

            // Check this channel's guild
            SocketGuildChannel socketGuildChannel = foundChannel as SocketGuildChannel;

            // Check that this exists and that it is in the user's guild
            if (socketGuildChannel == null || socketGuildChannel.Guild.Id != SetupFlow.Guild.Id)
            {
                await DiscordUtil.SendErrorMessageByLocalizedDescription(guild, this.Channel, "discord.setup.enter_channel.bad_channel");

                return(false);
            }

            // Get the text channel
            SocketTextChannel socketTextChannel = foundChannel as SocketTextChannel;

            // Check if this is a text channel
            if (socketTextChannel == null)
            {
                await DiscordUtil.SendErrorMessageByLocalizedDescription(guild, this.Channel, "discord.setup.enter_channel.bad_channel");

                return(false);
            }

            // Check if this already exists as settings
            if (SetupFlow.GuildSettings.ChannelSettings.Where(p => p.Key == channelId).Count() != 0)
            {
                await DiscordUtil.SendErrorMessageByLocalizedDescription(guild, this.Channel, "discord.setup.enter_channel.already_exists");

                return(false);
            }

            // Get all required permissions
            List <ChannelPermission> requiredPermissions = new ChannelPermissions(Configuration.LoadedConfiguration.DiscordConfig.Permissions).ToList();

            // Get current permissions for this channel
            ChannelPermissions channelPermissions = guild.CurrentUser.GetPermissions(socketTextChannel);

            // Get a list of permissions that the bot does not have
            IEnumerable <ChannelPermission> missingPermissions = requiredPermissions.Where(x => !channelPermissions.Has(x));

            // Check if we are missing any
            if (missingPermissions.Count() > 0)
            {
                // Try to get the default language
                Language language = DiscordUtil.GetDefaultLanguage(guild);

                // Create the description string for the error message
                string description = Localizer.Localize("discord.setup.enter_channel.missing_permissions", language) + "\n\n";

                // Append the permissions
                foreach (ChannelPermission permission in missingPermissions)
                {
                    description += permission.ToString() + "\n";
                }

                // Create an embed
                await DiscordUtil.SendErrorMessageByDescription(guild, this.Channel, description);

                return(false);
            }

            // Set the new message flag
            SetupFlow.ShouldSendNewMessage = true;

            if (SetupFlow.ChannelSettings == null)
            {
                // Create a DynamicSettingsData instance
                SetupFlow.ChannelSettings = new DynamicSettingsData();

                // Set the ID
                SetupFlow.TargetChannelId = channelId;

                // Proceed to language selection
                await SetupFlow.SetPage((int)SetupFlowPage.SelectLanguage);
            }
            else
            {
                // Move the data
                SetupFlow.GuildSettings.ChannelSettings.TryRemove(SetupFlow.TargetChannelId, out DynamicSettingsData data);
                SetupFlow.GuildSettings.ChannelSettings.TryAdd(channelId, data);

                // Set a pre-prompt
                SetupFlow.ModeSelectPrePromptLocalizable = "discord.setup.mode_select.pre_prompt.edits_saved";

                // Change to mode select
                await SetupFlow.SetPage((int)SetupFlowPage.ModeSelect);
            }

            return(false);
        }
Esempio n. 6
0
        public async Task Execute(ulong guildId = 0)
        {
            // Check if we are an admin
            bool isAdmin = DiscordUtil.IsAdministrator(Context.User);

            // Check if a guild is specified
            IGuild guild;

            if (guildId != 0)
            {
                // Check if the user does not permission
                if (!DiscordUtil.IsAdministrator(Context.User))
                {
                    // Return an error
                    await DiscordUtil.SendErrorMessageByLocalizedDescription(Context.Guild, Context.Channel, "discord.error.not_admin");

                    return;
                }
                else
                {
                    // Set the guild
                    guild = DiscordBot.GetGuild(guildId);

                    // Check if it exists
                    if (guild == null)
                    {
                        // Return an error
                        await DiscordUtil.SendErrorMessageByLocalizedDescription(Context.Guild, Context.Channel, "discord.setup.error.guild_not_exist");

                        return;
                    }
                }
            }
            else
            {
                guild = Context.Guild;

                // Check if this is a DM
                if (guild == null)
                {
                    // Return an error
                    await DiscordUtil.SendErrorMessageByLocalizedDescription(Context.Guild, Context.Channel, "discord.setup.error.in_dm");

                    return;
                }
            }

            // Test if the user does not permission
            if (!isAdmin && !((SocketGuildUser)Context.User).GuildPermissions.Has(GuildPermission.ManageGuild))
            {
                // Return an error
                await DiscordUtil.SendErrorMessageByLocalizedDescription(Context.Guild, Context.Channel, "discord.setup.error.no_permission");

                return;
            }

            // Check if there are already setups running
            if (await DiscordBot.IsSetupFlowRunningInGuild(guild))
            {
                // Error
                await DiscordUtil.SendErrorMessageByLocalizedDescription(Context.Guild, Context.Channel, "discord.setup.error.already_running");

                return;
            }

            // Run the setup
            await DiscordBot.ActivateInteractiveFlow(new SetupFlow(Context.User, guild, Context.Channel, new Language[] { Language.EnglishUS }, guildId != 0));
        }
Esempio n. 7
0
        protected override async Task UpdateInternal(DiscordLink plugin, DLEventType trigger, object data)
        {
            if (DLConfig.Data.TradeChannels.Count <= 0)
            {
                return;
            }
            if (!(data is IEnumerable <List <CurrencyTrade> > accumulatedTrades))
            {
                return;
            }


            // Each entry is the summarized trade events for a player and a store
            foreach (List <CurrencyTrade> accumulatedTradeList in accumulatedTrades)
            {
                if (accumulatedTradeList.Count <= 0)
                {
                    continue;
                }

                CurrencyTrade firstTrade = accumulatedTradeList[0];

                DiscordLinkEmbed embed     = new DiscordLinkEmbed();
                string           leftName  = firstTrade.Citizen.Name;
                string           rightName = (firstTrade.WorldObject as WorldObject).Name;
                embed.WithTitle($"{leftName} traded at {MessageUtil.StripTags(rightName)}");

                // Go through all acumulated trade events and create a summary
                string boughtItemsDesc = string.Empty;
                float  boughtTotal     = 0;
                string soldItemsDesc   = string.Empty;
                float  soldTotal       = 0;
                foreach (CurrencyTrade trade in accumulatedTradeList)
                {
                    if (trade.BoughtOrSold == Shared.Items.BoughtOrSold.Buying)
                    {
                        boughtItemsDesc += trade.NumberOfItems + " X " + trade.ItemUsed.DisplayName + " * " + trade.CurrencyAmount / trade.NumberOfItems + " = " + trade.CurrencyAmount + "\n";
                        boughtTotal     += trade.CurrencyAmount;
                    }
                    else if (trade.BoughtOrSold == Shared.Items.BoughtOrSold.Selling)
                    {
                        soldItemsDesc += trade.NumberOfItems + " X " + trade.ItemUsed.DisplayName + " * " + trade.CurrencyAmount / trade.NumberOfItems + " = " + trade.CurrencyAmount + "\n";
                        soldTotal     += trade.CurrencyAmount;
                    }
                }

                if (!boughtItemsDesc.IsEmpty())
                {
                    boughtItemsDesc += "\nTotal = " + boughtTotal.ToString("n2");
                    embed.AddField("Bought", boughtItemsDesc);
                }

                if (!soldItemsDesc.IsEmpty())
                {
                    soldItemsDesc += "\nTotal = " + soldTotal.ToString("n2");
                    embed.AddField("Sold", soldItemsDesc);
                }

                float subTotal = soldTotal - boughtTotal;
                char  sign     = (subTotal > 0.0f ? '+' : '-');
                embed.AddField("Total", sign + Math.Abs(subTotal).ToString("n2") + " " + MessageUtil.StripTags(firstTrade.Currency.Name));

                // Post the trade summary in all trade channels
                foreach (ChannelLink tradeChannel in DLConfig.Data.TradeChannels)
                {
                    if (!tradeChannel.IsValid())
                    {
                        continue;
                    }
                    DiscordGuild discordGuild = plugin.GuildByNameOrId(tradeChannel.DiscordGuild);
                    if (discordGuild == null)
                    {
                        continue;
                    }
                    DiscordChannel discordChannel = discordGuild.ChannelByNameOrId(tradeChannel.DiscordChannel);
                    if (discordChannel == null)
                    {
                        continue;
                    }

                    _ = DiscordUtil.SendAsync(discordChannel, string.Empty, embed);
                    ++_opsCount;
                }
            }
        }
Esempio n. 8
0
        public async Task Execute(IJobExecutionContext context)
        {
            try
            {
                // Log that we're about to begin uploading data
                await DiscordBot.LoggingChannel.SendMessageAsync("**[RomDataUploadJob]** Beginning ROM data upload");

                // Create a list of paths whose cache needs to be cleared
                List <string> clearPaths = new List <string>();

                // Create the MSBT S3 path format string
                string msbtS3BasePath = "/splatoon/blitz_rom/Message/CommonMsg_{0}";

                // Loop over every language
                foreach (Language language in BlitzUtil.SupportedLanguages)
                {
                    // Log the language
                    await DiscordBot.LoggingChannel.SendMessageAsync($"**[RomDataUploadJob]** Uploading {language.ToString()}'s MSBTs");

                    // Get the MsbtHolder
                    MsbtHolder msbtHolder = BlitzLocalizer.MsbtHolders[language];

                    // Loop over every MSBT
                    foreach (KeyValuePair <string, Dictionary <string, string> > pair in msbtHolder.Msbts)
                    {
                        // Construct the path
                        string msbtPath = string.Format(msbtS3BasePath, language.GetSeadCode());

                        // Construct the file name
                        string fileName = $"{pair.Key}.json";

                        // Serialize to JSON
                        string json = JsonConvert.SerializeObject(pair.Value);

                        // Upload to S3
                        S3Api.TransferFile(Encoding.UTF8.GetBytes(json), msbtPath, fileName, "application/json");

                        // Add to the cache list
                        clearPaths.Add($"{msbtPath}/{fileName}");
                    }
                }

                // Log MSBT upload
                await DiscordBot.LoggingChannel.SendMessageAsync("**[RomDataUploadJob]** Uploading Mush");

                // Create the Mush S3 path string
                string mushS3Path = "/splatoon/blitz_rom/Mush";

                // Get every file in Mush
                foreach (string path in RomResourceLoader.GetFilesInDirectory("/Mush"))
                {
                    // Get the BYAML
                    dynamic byaml = ByamlLoader.GetByamlDynamic(path);

                    // Construct the file name
                    string fileName = $"{Path.GetFileNameWithoutExtension(path)}.json";

                    // Serialize to JSON
                    string json = JsonConvert.SerializeObject(byaml);

                    // Upload to S3
                    S3Api.TransferFile(Encoding.UTF8.GetBytes(json), mushS3Path, fileName, "application/json");

                    // Add to the paths to clear
                    clearPaths.Add($"{mushS3Path}/{fileName}");
                }

                // Log CDN cache purge starting
                await DiscordBot.LoggingChannel.SendMessageAsync($"**[RomDataUploadJob]** Requesting CDN cache purge ({clearPaths.Count} of {clearPaths.Count} files left)");

                IEnumerable <string> pathsEnumerable = (IEnumerable <string>)clearPaths;

                while (pathsEnumerable.Any())
                {
                    // Tell DigitalOcean to clear the cache
                    await DoApi.SendRequest(new DoCdnCachePurgeRequest(Configuration.LoadedConfiguration.DoConfig.EndpointId, pathsEnumerable.Take(15).ToList()));

                    // Advance to the next set
                    pathsEnumerable = pathsEnumerable.Skip(15);

                    // Log files left
                    await DiscordBot.LoggingChannel.SendMessageAsync($"**[RomDataUploadJob]** Requesting CDN cache purge ({pathsEnumerable.Count()} of {clearPaths.Count} files left)");
                }

                // Write the app version
                await DiscordBot.LoggingChannel.SendMessageAsync("**[RomDataUploadJob]** Saving new ROM version to configuration");

                (Configuration.LoadedConfiguration as JelonzoBotConfiguration).RomConfig.LastRomVersion = (int)context.JobDetail.JobDataMap["version"];
                Configuration.LoadedConfiguration.Write();

                // Log that it's complete
                await DiscordBot.LoggingChannel.SendMessageAsync("**[RomDataUploadJob]** ROM data upload complete");
            }
            catch (Exception e)
            {
                await DiscordUtil.HandleException(e, "in ``RomDataUploadJob``");
            }
        }
Esempio n. 9
0
        public async Task Execute(IJobExecutionContext context)
        {
            try
            {
                foreach (KeyValuePair <RomType, BcatPair> bcatPairEntry in Program.BcatPairs)
                {
                    // Log that we're about to begin a check
                    await DiscordBot.LoggingChannel.SendMessageAsync("**[BCAT]** Beginning topic download for " + bcatPairEntry.Key.ToString());

                    // Download the latest Topic
                    Topic topic = await BcatApi.GetDataTopic(bcatPairEntry.Value.TitleId, bcatPairEntry.Value.Passphrase);

                    // Create the target folder name
                    string targetFolder = string.Format(Program.LOCAL_OLD_DATA_DIRECTORY, DateTime.Now.ToString(Program.FOLDER_DATE_TIME_FORMAT), bcatPairEntry.Key.ToString());

                    // Format the old Topic path
                    string oldTopicPath = string.Format(Program.LOCAL_LAST_TOPIC, bcatPairEntry.Key.ToString());

                    // Load the old Topic
                    Topic oldTopic = MessagePackSerializer.Deserialize <Topic>(File.ReadAllBytes(oldTopicPath));

    #if DEBUG
                    if (!Configuration.LoadedConfiguration.IsProduction)
                    {
                        /*foreach (Nintendo.Bcat.Directory dir in oldTopic.Directories)
                         * {
                         *  if (dir.Name == "fesdata")
                         *  {
                         *      Data dbgData = dir.Data.Where(x => x.Name == "Festival.byaml").FirstOrDefault();
                         *      dbgData.Digest = "deadbeef";
                         *  }
                         * }*/
                    }
    #endif

                    // Get the differences
                    List <KeyValuePair <DifferenceType, string> > differences = BcatCheckerUtils.GetTopicChanges(oldTopic, topic);

                    // Check if there aren't any
                    if (differences.Count == 0)
                    {
                        // Nothing to do here
                        goto finished;
                    }

                    // Download all data
                    Dictionary <string, byte[]> data = await BcatCheckerUtils.DownloadAllData(topic, bcatPairEntry.Value.TitleId, bcatPairEntry.Value.Passphrase, targetFolder);

                    // Loop over every difference
                    foreach (KeyValuePair <DifferenceType, string> differencePair in differences)
                    {
                        // Log the difference
                        await DiscordBot.LoggingChannel.SendMessageAsync("**[BCAT]** diff: ``" + differencePair.Value + "`` (" + differencePair.Key.ToString() + ")");

                        // Get the FileType
                        FileType fileType = FileTypeExtensions.GetTypeFromFilePath(differencePair.Value);

                        // Create a ByamlSerializer instance
                        ByamlSerializer serializer = new ByamlSerializer(new ByamlSerializerSettings()
                        {
                            ByteOrder    = ByteOrder.LittleEndian,
                            SupportPaths = false,
                            Version      = ByamlVersion.Version1
                        });

                        // Create the difference handler parameters based off the FileType and difference type
                        object[] parameters;

                        if (differencePair.Key != DifferenceType.Removed)
                        {
                            // Get the raw file
                            byte[] rawFile = data[differencePair.Value];

                            // Deserialize the object from byaml if necessary
                            object deserializedObject;
                            using (MemoryStream memoryStream = new MemoryStream(rawFile))
                            {
                                switch (fileType)
                                {
                                case FileType.VersusSetting:
                                    deserializedObject = serializer.Deserialize <VersusSetting>(memoryStream);
                                    break;

                                case FileType.CoopSetting:
                                    deserializedObject = serializer.Deserialize <CoopSetting>(memoryStream);
                                    break;

                                case FileType.FestivalByaml:
                                    deserializedObject = serializer.Deserialize <FestivalSetting>(memoryStream);
                                    break;

                                default:
                                    deserializedObject = data[differencePair.Value];
                                    break;
                                }
                            }

                            if (differencePair.Key == DifferenceType.Added)
                            {
                                parameters = new object[] { bcatPairEntry.Key, data, deserializedObject, rawFile };
                            }
                            else // Changed
                            {
                                // Get the previous file
                                object previousFile;
                                switch (fileType)
                                {
                                case FileType.VersusSetting:
                                    previousFile = FileCache.GetVersusSettingForRomType(bcatPairEntry.Key);
                                    break;

                                case FileType.CoopSetting:
                                    previousFile = FileCache.GetCoopSetting();
                                    break;

                                case FileType.FestivalByaml:
                                    previousFile = FileCache.GetLatestFestivalSettingForRomType(bcatPairEntry.Key);
                                    break;

                                default:
                                    // Construct the previous file path
                                    string previousPath = Path.Combine((Configuration.LoadedConfiguration as JelonzoBotConfiguration).LastDownloadPaths[bcatPairEntry.Key], differencePair.Value.Replace('/', Path.DirectorySeparatorChar));

                                    // Load it
                                    previousFile = File.ReadAllBytes(previousPath);;
                                    break;
                                }

                                // Create the parameters
                                parameters = new object[] { bcatPairEntry.Key, data, previousFile, deserializedObject, rawFile };
                            }
                        }
                        else
                        {
                            parameters = new object[] { bcatPairEntry.Key, data };
                        }

                        // Call every difference handler
                        await BcatCheckerUtils.CallDifferenceHandlers((int)fileType, differencePair.Key, parameters);
                    }

                    // Write out the Topic
                    File.WriteAllBytes(oldTopicPath, MessagePackSerializer.Serialize(topic));

                    // Set the last download path
                    (Configuration.LoadedConfiguration as JelonzoBotConfiguration).LastDownloadPaths[bcatPairEntry.Key] = targetFolder;

finished:
                    await DiscordBot.LoggingChannel.SendMessageAsync("**[BCAT]** Check complete for " + bcatPairEntry.Key.ToString());
                }
            }
            catch (Exception exception)
            {
                // Notify the logging channel
                await DiscordUtil.HandleException(exception, $"in ``BcatCheckerJob``");
            }
        }
Esempio n. 10
0
 private void SubscribeEvents()
 {
     DiscordClient.Ready += () => { readyEvent.Set(); return(Task.CompletedTask); };
     DiscordClient.Log   += m => { Logger.Log(DiscordUtil.ToLoggable(m)); return(Task.CompletedTask); };
 }
        public async Task Execute(IJobExecutionContext context)
        {
            try {
                // Run app-specific boot tasks
                await RunAppSpecificBootTasks();

                // Run one-time tasks
                await DiscordBot.LoggingChannel.SendMessageAsync($"**[BootHousekeepingJob]** Running one-time tasks");

                foreach (Type type in Assembly.GetExecutingAssembly().GetTypes().Where(x => x.IsSubclassOf(typeof(OneTimeTask)) && !x.IsAbstract))
                {
                    // Create a new instance and run it
                    await((OneTimeTask)Activator.CreateInstance(type)).RunImpl();
                }

                await DiscordBot.LoggingChannel.SendMessageAsync($"**[BootHousekeepingJob]** Processing joined/left guilds");

                // Get a list of guilds
                IReadOnlyCollection <SocketGuild> socketGuilds = DiscordBot.GetGuilds();

                // Get all guild IDs that we have settings for
                List <ulong> configurationGuilds = new List <ulong>();
                foreach (GuildSettings guildSettings in Configuration.LoadedConfiguration.DiscordConfig.GuildSettings)
                {
                    configurationGuilds.Add(guildSettings.GuildId);
                }

                // Get all IDs for guilds that we are in
                List <ulong> currentGuilds = new List <ulong>();
                foreach (SocketGuild socketGuild in DiscordBot.GetGuilds())
                {
                    currentGuilds.Add(socketGuild.Id);
                }

                // Get all the guilds we have joined
                IEnumerable <ulong> joinedGuilds = currentGuilds.Except(configurationGuilds);
                foreach (ulong id in joinedGuilds)
                {
                    // TODO: find a better solution instead of spamming the Welcome message
                    //await DiscordUtil.ProcessJoinedGuild(socketGuilds.Where(guild => guild.Id == id).FirstOrDefault());
                }

                // Get all the guilds we have been removed from
                IEnumerable <ulong> removedGuilds = configurationGuilds.Except(currentGuilds);
                foreach (ulong id in removedGuilds)
                {
                    await DiscordUtil.ProcessLeftGuild(id, null);
                }

                await DiscordBot.LoggingChannel.SendMessageAsync($"**[BootHousekeepingJob]** Saving configuration");

                // Save the configuration
                Configuration.LoadedConfiguration.Write();

                // Schedule the RecurringHousekeepingJob
                await QuartzScheduler.ScheduleJob(TypeUtils.GetSubclassOfType <RecurringHousekeepingJob>(), "Normal", Configuration.LoadedConfiguration.JobSchedules["Recurring"]);

                // Schedule jobs
                await SchedulePostBootJobs();
            }
            catch (Exception e)
            {
                await DiscordUtil.HandleException(e, "in ``BootHousekeepingJob``");
            }
        }