Beispiel #1
0
        public void ProgressManager_MultipleOperations_Sequential_Test()
        {
            // Create manager
            var manager = new ProgressManager();

            // Create operations
            var operations = manager.CreateOperations(3);

            // Assert initial state after creating operations
            Assert.That(manager.Progress, Is.Zero);
            Assert.That(manager.IsActive, Is.True);
            Assert.That(manager.Operations.Count, Is.EqualTo(operations.Count));

            // Loop through each operation and report progress
            for (var i = 0; i < operations.Count; i++)
            {
                // Assert intermediate state
                Assert.That(manager.Progress, Is.EqualTo(1.0 * i / operations.Count));
                Assert.That(manager.IsActive, Is.True);
                Assert.That(manager.Operations.Count, Is.EqualTo(operations.Count));

                using (var operation = operations[i])
                {
                    operation.Report(0.2);
                    operation.Report(0.5);
                    operation.Report(0.9);
                }
            }

            // Assert final state
            Assert.That(manager.Progress, Is.Zero);
            Assert.That(manager.IsActive, Is.False);
            Assert.That(manager.Operations.Count, Is.Zero);
        }
Beispiel #2
0
        public async void ExportChannels()
        {
            // Get last used token
            var token = _settingsService.LastToken !;

            // Create dialog
            var dialog = _viewModelFactory.CreateExportSetupViewModel(SelectedGuild !, SelectedChannels !);

            // Show dialog, if canceled - return
            if (await _dialogManager.ShowDialogAsync(dialog) != true)
            {
                return;
            }

            // Create a progress operation for each channel to export
            var operations = ProgressManager.CreateOperations(dialog.Channels.Count);

            // Export channels
            var successfulExportCount = 0;

            for (var i = 0; i < dialog.Channels.Count; i++)
            {
                var operation = operations[i];
                var channel   = dialog.Channels[i];

                try
                {
                    await _exportService.ExportChatLogAsync(token, dialog.Guild, channel,
                                                            dialog.OutputPath !, dialog.SelectedFormat, dialog.PartitionLimit,
                                                            dialog.After, dialog.Before, operation);

                    successfulExportCount++;
                }
                catch (HttpErrorStatusCodeException ex) when(ex.StatusCode == HttpStatusCode.Forbidden)
                {
                    Notifications.Enqueue($"You don't have access to channel [{channel.Model.Name}]");
                }
                catch (HttpErrorStatusCodeException ex) when(ex.StatusCode == HttpStatusCode.NotFound)
                {
                    Notifications.Enqueue($"Channel [{channel.Model.Name}] doesn't exist");
                }
                catch (DomainException ex)
                {
                    Notifications.Enqueue(ex.Message);
                }
                finally
                {
                    operation.Dispose();
                }
            }

            // Notify of overall completion
            if (successfulExportCount > 0)
            {
                Notifications.Enqueue($"Successfully exported {successfulExportCount} channel(s)");
            }
        }
Beispiel #3
0
        public void Progress_manager_can_create_multiple_operations_at_once()
        {
            // Arrange
            var manager = new ProgressManager();

            // Act
            var operations = manager.CreateOperations(3);

            // Assert
            operations.Should().HaveCount(3);
        }
Beispiel #4
0
        public void ProgressManager_MultipleOperations_DifferentWeight_Test()
        {
            // Create manager
            var manager = new ProgressManager();

            // Create operations
            var operations = manager.CreateOperations(3, i => i + 1);

            // Assert initial state after creating operations
            Assert.That(manager.Progress, Is.Zero);
            Assert.That(manager.IsActive, Is.True);
            Assert.That(manager.Operations.Count, Is.EqualTo(operations.Count));

            // Report new progress
            const double newProgress = 0.5;

            foreach (var operation in operations)
            {
                operation.Report(newProgress);
            }

            // Assert intermediate state
            Assert.That(manager.Progress, Is.EqualTo(newProgress));
            Assert.That(manager.IsActive, Is.True);
            Assert.That(manager.Operations.Count, Is.EqualTo(operations.Count));

            // Report completion
            foreach (var operation in operations)
            {
                operation.Dispose();
            }

            // Assert final state
            Assert.That(manager.Progress, Is.Zero);
            Assert.That(manager.IsActive, Is.False);
            Assert.That(manager.Operations.Count, Is.Zero);
        }
        public async void ExportChannels()
        {
            // Get last used token
            var token = _settingsService.LastToken;

            // Create dialog
            var dialog = _viewModelFactory.CreateExportSetupViewModel(SelectedGuild, SelectedChannels);

            // Show dialog, if canceled - return
            if (await _dialogManager.ShowDialogAsync(dialog) != true)
            {
                return;
            }

            // Create a progress operation for each channel to export
            var operations = ProgressManager.CreateOperations(dialog.Channels.Count);

            // Export channels
            for (var i = 0; i < dialog.Channels.Count; i++)
            {
                // Get operation and channel
                var operation = operations[i];
                var channel   = dialog.Channels[i];

                try
                {
                    // Generate file path if necessary
                    var filePath = dialog.OutputPath;
                    if (ExportHelper.IsDirectoryPath(filePath))
                    {
                        // Generate default file name
                        var fileName = ExportHelper.GetDefaultExportFileName(dialog.SelectedFormat, dialog.Guild,
                                                                             channel, dialog.From, dialog.To);

                        // Combine paths
                        filePath = Path.Combine(filePath, fileName);
                    }

                    // Get chat log
                    var chatLog = await _dataService.GetChatLogAsync(token, dialog.Guild, channel,
                                                                     dialog.From, dialog.To, operation);

                    // Export
                    _exportService.ExportChatLog(chatLog, filePath, dialog.SelectedFormat,
                                                 dialog.PartitionLimit);

                    // Notify completion
                    Notifications.Enqueue($"Channel [{channel.Model.Name}] successfully exported");
                }
                catch (HttpErrorStatusCodeException ex) when(ex.StatusCode == HttpStatusCode.Forbidden)
                {
                    Notifications.Enqueue($"You don't have access to channel [{channel.Model.Name}]");
                }
                catch (HttpErrorStatusCodeException ex) when(ex.StatusCode == HttpStatusCode.NotFound)
                {
                    Notifications.Enqueue($"Channel [{channel.Model.Name}] doesn't exist");
                }
                finally
                {
                    // Dispose progress operation
                    operation.Dispose();
                }
            }
        }
        protected async ValueTask ExportMultipleAsync(IConsole console, IReadOnlyList <Channel> channels)
        {
            // This uses a separate route from ExportCommandBase because the progress ticker is not thread-safe
            // Ugly code ahead. Will need to refactor.

            if (!string.IsNullOrWhiteSpace(DateFormat))
            {
                SettingsService.DateFormat = DateFormat;
            }

            // Progress
            console.Output.Write($"Exporting {channels.Count} channels... ");
            var ticker = console.CreateProgressTicker();

            // TODO: refactor this after improving Gress
            var progressManager = new ProgressManager();

            progressManager.PropertyChanged += (sender, args) => ticker.Report(progressManager.Progress);

            var operations = progressManager.CreateOperations(channels.Count);

            // Export channels
            using var semaphore = new SemaphoreSlim(ParallelLimit.ClampMin(1));

            var errors = new List <string>();

            await Task.WhenAll(channels.Select(async(channel, i) =>
            {
                var operation = operations[i];
                await semaphore.WaitAsync();

                var guild = await DataService.GetGuildAsync(Token, channel.GuildId);

                try
                {
                    await ExportService.ExportChatLogAsync(Token, guild, channel,
                                                           OutputPath, ExportFormat, PartitionLimit,
                                                           After, Before, operation);
                }
                catch (HttpErrorStatusCodeException ex) when(ex.StatusCode == HttpStatusCode.Forbidden)
                {
                    errors.Add("You don't have access to this channel.");
                }
                catch (HttpErrorStatusCodeException ex) when(ex.StatusCode == HttpStatusCode.NotFound)
                {
                    errors.Add("This channel doesn't exist.");
                }
                catch (DomainException ex)
                {
                    errors.Add(ex.Message);
                }
                finally
                {
                    semaphore.Release();
                    operation.Dispose();
                }
            }));

            ticker.Report(1);
            console.Output.WriteLine();

            foreach (var error in errors)
            {
                console.Error.WriteLine(error);
            }

            console.Output.WriteLine("Done.");
        }