public static async Task <int> GetDataLimit(string group, CancellationToken cancellationToken = default) { var(loadedNodes, loadNodesErrMsg) = await Nodes.LoadNodesAsync(cancellationToken); if (loadNodesErrMsg is not null) { Console.WriteLine(loadNodesErrMsg); return(1); } using var nodes = loadedNodes; if (nodes.Groups.TryGetValue(group, out var targetGroup)) { Console.WriteLine($"{"Group",-24}{group,-32}"); if (targetGroup.DataLimitInBytes != 0UL) { Console.WriteLine($"{"Global data limit",-24}{InteractionHelper.HumanReadableDataString1024(targetGroup.DataLimitInBytes),-32}"); } if (targetGroup.PerUserDataLimitInBytes != 0UL) { Console.WriteLine($"{"Per-user data limit",-24}{InteractionHelper.HumanReadableDataString1024(targetGroup.PerUserDataLimitInBytes),-32}"); } var outlineAccessKeyCustomLimits = targetGroup.OutlineAccessKeys?.Where(x => x.DataLimit is not null).Select(x => (x.Name, x.DataLimit !.Bytes)); if (outlineAccessKeyCustomLimits is null || !outlineAccessKeyCustomLimits.Any()) { return(0); } var maxNameLength = outlineAccessKeyCustomLimits.Select(x => x.Name.Length) .DefaultIfEmpty() .Max(); var nameFieldWidth = maxNameLength > 4 ? maxNameLength + 2 : 6; ConsoleHelper.PrintTableBorder(nameFieldWidth, 19); Console.WriteLine($"|{"User".PadRight(nameFieldWidth)}|{"Custom Data Limit",19}|"); ConsoleHelper.PrintTableBorder(nameFieldWidth, 19); foreach ((var username, var dataLimitInBytes) in outlineAccessKeyCustomLimits) { Console.WriteLine($"|{username.PadRight(nameFieldWidth)}|{InteractionHelper.HumanReadableDataString1024(dataLimitInBytes),19}|"); } ConsoleHelper.PrintTableBorder(nameFieldWidth, 19); return(0); } else { Console.WriteLine($"Error: group {group} doesn't exist."); return(-2); } }
public static async Task <int> GetDataLimit(string username, CancellationToken cancellationToken = default) { var(users, loadUsersErrMsg) = await Users.LoadUsersAsync(cancellationToken); if (loadUsersErrMsg is not null) { Console.WriteLine(loadUsersErrMsg); return(1); } if (users.UserDict.TryGetValue(username, out var user)) { Console.WriteLine($"{"User",-24}{username,-32}"); if (user.DataLimitInBytes != 0UL) { Console.WriteLine($"{"Global data limit",-24}{InteractionHelper.HumanReadableDataString1024(user.DataLimitInBytes),-32}"); } if (user.PerGroupDataLimitInBytes != 0UL) { Console.WriteLine($"{"Per-group data limit",-24}{InteractionHelper.HumanReadableDataString1024(user.PerGroupDataLimitInBytes),-32}"); } var customLimits = user.Memberships.Where(x => x.Value.DataLimitInBytes > 0UL).Select(x => (x.Key, x.Value.DataLimitInBytes)); if (!customLimits.Any()) { return(0); } var maxNameLength = customLimits.Select(x => x.Key.Length) .DefaultIfEmpty() .Max(); var nameFieldWidth = maxNameLength > 5 ? maxNameLength + 2 : 7; ConsoleHelper.PrintTableBorder(nameFieldWidth, 19); Console.WriteLine($"|{"Group".PadRight(nameFieldWidth)}|{"Custom Data Limit",19}|"); ConsoleHelper.PrintTableBorder(nameFieldWidth, 19); foreach ((var group, var dataLimitInBytes) in customLimits) { Console.WriteLine($"|{group.PadRight(nameFieldWidth)}|{InteractionHelper.HumanReadableDataString1024(dataLimitInBytes),19}|"); } ConsoleHelper.PrintTableBorder(nameFieldWidth, 19); return(0); } else { Console.WriteLine($"Error: user {username} doesn't exist."); return(-2); } }
public static async Task <int> GetDataUsage(string group, SortBy?sortBy, CancellationToken cancellationToken = default) { var(loadedNodes, loadNodesErrMsg) = await Nodes.LoadNodesAsync(cancellationToken); if (loadNodesErrMsg is not null) { Console.WriteLine(loadNodesErrMsg); return(1); } using var nodes = loadedNodes; var(settings, loadSettingsErrMsg) = await Settings.LoadSettingsAsync(cancellationToken); if (loadSettingsErrMsg is not null) { Console.WriteLine(loadSettingsErrMsg); return(1); } var records = nodes.GetGroupDataUsage(group); if (records is null) { Console.WriteLine($"Error: group {group} doesn't exist."); return(-2); } var maxNameLength = records.Select(x => x.username.Length) .DefaultIfEmpty() .Max(); var nameFieldWidth = maxNameLength > 4 ? maxNameLength + 2 : 6; var sortByInEffect = settings.GroupDataUsageDefaultSortBy; if (sortBy is SortBy currentRunSortBy) { sortByInEffect = currentRunSortBy; } switch (sortByInEffect) { case SortBy.DefaultAscending: break; case SortBy.DefaultDescending: records.Reverse(); break; case SortBy.NameAscending: records = records.OrderBy(x => x.username).ToList(); break; case SortBy.NameDescending: records = records.OrderByDescending(x => x.username).ToList(); break; case SortBy.DataUsedAscending: records = records.OrderBy(x => x.bytesUsed).ToList(); break; case SortBy.DataUsedDescending: records = records.OrderByDescending(x => x.bytesUsed).ToList(); break; case SortBy.DataRemainingAscending: records = records.OrderBy(x => x.bytesRemaining).ToList(); break; case SortBy.DataRemainingDescending: records = records.OrderByDescending(x => x.bytesRemaining).ToList(); break; } Console.WriteLine($"{"Group",-16}{group,-32}"); if (nodes.Groups.TryGetValue(group, out var targetGroup)) { Console.WriteLine($"{"Data used",-16}{InteractionHelper.HumanReadableDataString1024(targetGroup.BytesUsed),-32}"); if (targetGroup.BytesRemaining != 0UL) { Console.WriteLine($"{"Data remaining",-16}{InteractionHelper.HumanReadableDataString1024(targetGroup.BytesRemaining),-32}"); } if (targetGroup.DataLimitInBytes != 0UL) { Console.WriteLine($"{"Data limit",-16}{InteractionHelper.HumanReadableDataString1024(targetGroup.DataLimitInBytes),-32}"); } } if (records.All(x => x.bytesRemaining == 0UL)) // Omit data remaining column if no data. { ConsoleHelper.PrintTableBorder(nameFieldWidth, 11); Console.WriteLine($"|{"User".PadRight(nameFieldWidth)}|{"Data Used",11}|"); ConsoleHelper.PrintTableBorder(nameFieldWidth, 11); foreach (var(username, bytesUsed, _) in records) { Console.WriteLine($"|{username.PadRight(nameFieldWidth)}|{InteractionHelper.HumanReadableDataString1024(bytesUsed),11}|"); } ConsoleHelper.PrintTableBorder(nameFieldWidth, 11); } else { ConsoleHelper.PrintTableBorder(nameFieldWidth, 11, 16); Console.WriteLine($"|{"User".PadRight(nameFieldWidth)}|{"Data Used",11}|{"Data Remaining",16}|"); ConsoleHelper.PrintTableBorder(nameFieldWidth, 11, 16); foreach (var(username, bytesUsed, bytesRemaining) in records) { Console.Write($"|{username.PadRight(nameFieldWidth)}|{InteractionHelper.HumanReadableDataString1024(bytesUsed),11}|"); if (bytesRemaining != 0UL) { Console.WriteLine($"{InteractionHelper.HumanReadableDataString1024(bytesRemaining),16}|"); } else { Console.WriteLine($"{string.Empty,16}|"); } } ConsoleHelper.PrintTableBorder(nameFieldWidth, 11, 16); } return(0); }
public static async Task <int> Generate(SortBy?groupSortBy, SortBy?userSortBy, string?csvOutdir, CancellationToken cancellationToken = default) { var(users, loadUsersErrMsg) = await Users.LoadUsersAsync(cancellationToken); if (loadUsersErrMsg is not null) { Console.WriteLine(loadUsersErrMsg); return(1); } var(loadedNodes, loadNodesErrMsg) = await Nodes.LoadNodesAsync(cancellationToken); if (loadNodesErrMsg is not null) { Console.WriteLine(loadNodesErrMsg); return(1); } using var nodes = loadedNodes; var(settings, loadSettingsErrMsg) = await Settings.LoadSettingsAsync(cancellationToken); if (loadSettingsErrMsg is not null) { Console.WriteLine(loadSettingsErrMsg); return(1); } // collect data var totalBytesUsed = nodes.Groups.Select(x => x.Value.BytesUsed).Aggregate(0UL, (x, y) => x + y); var totalBytesRemaining = nodes.Groups.All(x => x.Value.DataLimitInBytes > 0UL) ? nodes.Groups.Select(x => x.Value.BytesRemaining).Aggregate(0UL, (x, y) => x + y) : 0UL; var recordsByGroup = nodes.GetDataUsageByGroup(); var recordsByUser = users.GetDataUsageByUser(); // calculate column width var maxGroupNameLength = recordsByGroup.Select(x => x.group.Length) .DefaultIfEmpty() .Max(); var groupNameFieldWidth = maxGroupNameLength > 5 ? maxGroupNameLength + 2 : 7; var maxUsernameLength = recordsByUser.Select(x => x.username.Length) .DefaultIfEmpty() .Max(); var usernameFieldWidth = maxUsernameLength > 4 ? maxUsernameLength + 2 : 6; // sort var groupSortByInEffect = groupSortBy ?? settings.GroupDataUsageDefaultSortBy; recordsByGroup = groupSortByInEffect switch { SortBy.DefaultAscending => recordsByGroup, SortBy.DefaultDescending => recordsByGroup.Reverse(), SortBy.NameAscending => recordsByGroup.OrderBy(x => x.group), SortBy.NameDescending => recordsByGroup.OrderByDescending(x => x.group), SortBy.DataUsedAscending => recordsByGroup.OrderBy(x => x.bytesUsed), SortBy.DataUsedDescending => recordsByGroup.OrderByDescending(x => x.bytesUsed), SortBy.DataRemainingAscending => recordsByGroup.OrderBy(x => x.bytesRemaining), SortBy.DataRemainingDescending => recordsByGroup.OrderByDescending(x => x.bytesRemaining), _ => throw new NotImplementedException("This sort method is not implemented!"), }; var userSortByInEffect = userSortBy ?? settings.UserDataUsageDefaultSortBy; recordsByUser = userSortByInEffect switch { SortBy.DefaultAscending => recordsByUser, SortBy.DefaultDescending => recordsByUser.Reverse(), SortBy.NameAscending => recordsByUser.OrderBy(x => x.username), SortBy.NameDescending => recordsByUser.OrderByDescending(x => x.username), SortBy.DataUsedAscending => recordsByUser.OrderBy(x => x.bytesUsed), SortBy.DataUsedDescending => recordsByUser.OrderByDescending(x => x.bytesUsed), SortBy.DataRemainingAscending => recordsByUser.OrderBy(x => x.bytesRemaining), SortBy.DataRemainingDescending => recordsByUser.OrderByDescending(x => x.bytesRemaining), _ => throw new NotImplementedException("This sort method is not implemented!"), }; // total Console.WriteLine("In the last 30 days:"); Console.WriteLine(); if (totalBytesUsed != 0UL) { Console.WriteLine($"{"Total data used",-24}{InteractionHelper.HumanReadableDataString1024(totalBytesUsed)}"); } if (totalBytesRemaining != 0UL) { Console.WriteLine($"{"Total data remaining",-24}{InteractionHelper.HumanReadableDataString1024(totalBytesRemaining)}"); } Console.WriteLine(); // by group Console.WriteLine("Data usage by group"); if (recordsByGroup.All(x => x.bytesRemaining == 0UL)) // Omit data remaining column if no data. { ConsoleHelper.PrintTableBorder(groupNameFieldWidth, 11); Console.WriteLine($"|{"Group".PadRight(groupNameFieldWidth)}|{"Data Used",11}|"); ConsoleHelper.PrintTableBorder(groupNameFieldWidth, 11); foreach (var(group, bytesUsed, _) in recordsByGroup) { Console.Write($"|{group.PadRight(groupNameFieldWidth)}|"); if (bytesUsed != 0UL) { Console.WriteLine($"{InteractionHelper.HumanReadableDataString1024(bytesUsed),11}|"); } else { Console.WriteLine($"{string.Empty,11}|"); } } ConsoleHelper.PrintTableBorder(groupNameFieldWidth, 11); } else { ConsoleHelper.PrintTableBorder(groupNameFieldWidth, 11, 16); Console.WriteLine($"|{"Group".PadRight(groupNameFieldWidth)}|{"Data Used",11}|{"Data Remaining",16}|"); ConsoleHelper.PrintTableBorder(groupNameFieldWidth, 11, 16); foreach (var(group, bytesUsed, bytesRemaining) in recordsByGroup) { Console.Write($"|{group.PadRight(groupNameFieldWidth)}|"); if (bytesUsed != 0UL) { Console.Write($"{InteractionHelper.HumanReadableDataString1024(bytesUsed),11}|"); } else { Console.Write($"{string.Empty,11}|"); } if (bytesRemaining != 0UL) { Console.WriteLine($"{InteractionHelper.HumanReadableDataString1024(bytesRemaining),16}|"); } else { Console.WriteLine($"{string.Empty,16}|"); } } ConsoleHelper.PrintTableBorder(groupNameFieldWidth, 11, 16); } Console.WriteLine(); // by user Console.WriteLine("Data usage by user"); if (recordsByUser.All(x => x.bytesRemaining == 0UL)) // Omit data remaining column if no data. { ConsoleHelper.PrintTableBorder(usernameFieldWidth, 11); Console.WriteLine($"|{"User".PadRight(usernameFieldWidth)}|{"Data Used",11}|"); ConsoleHelper.PrintTableBorder(usernameFieldWidth, 11); foreach (var(username, bytesUsed, _) in recordsByUser) { Console.Write($"|{username.PadRight(usernameFieldWidth)}|"); if (bytesUsed != 0UL) { Console.WriteLine($"{InteractionHelper.HumanReadableDataString1024(bytesUsed),11}|"); } else { Console.WriteLine($"{string.Empty,11}|"); } } ConsoleHelper.PrintTableBorder(usernameFieldWidth, 11); } else { ConsoleHelper.PrintTableBorder(usernameFieldWidth, 11, 16); Console.WriteLine($"|{"User".PadRight(usernameFieldWidth)}|{"Data Used",11}|{"Data Remaining",16}|"); ConsoleHelper.PrintTableBorder(usernameFieldWidth, 11, 16); foreach (var(username, bytesUsed, bytesRemaining) in recordsByUser) { Console.Write($"|{username.PadRight(usernameFieldWidth)}|"); if (bytesUsed != 0UL) { Console.Write($"{InteractionHelper.HumanReadableDataString1024(bytesUsed),11}|"); } else { Console.Write($"{string.Empty,11}|"); } if (bytesRemaining != 0UL) { Console.WriteLine($"{InteractionHelper.HumanReadableDataString1024(bytesRemaining),16}|"); } else { Console.WriteLine($"{string.Empty,16}|"); } } ConsoleHelper.PrintTableBorder(usernameFieldWidth, 11, 16); } // CSV if (!string.IsNullOrEmpty(csvOutdir)) { var(dataUsageByGroup, dataUsageByUser) = ReportHelper.GenerateDataUsageCSV(recordsByGroup, recordsByUser); try { _ = Directory.CreateDirectory(csvOutdir); var writeDataUsageByGroupTask = File.WriteAllTextAsync($"{csvOutdir}/data-usage-by-group.csv", dataUsageByGroup, cancellationToken); var writeDataUsageByUserTask = File.WriteAllTextAsync($"{csvOutdir}/data-usage-by-user.csv", dataUsageByUser, cancellationToken); await Task.WhenAll(writeDataUsageByGroupTask, writeDataUsageByUserTask); Console.WriteLine(); Console.WriteLine($"Written to {csvOutdir}/data-usage-by-group.csv"); Console.WriteLine($"Written to {csvOutdir}/data-usage-by-user.csv"); } catch (Exception ex) { Console.WriteLine($"Error when saving CSV: {ex.Message}"); } } return(0); }