diff --git a/OF DL/Extension.props b/OF DL/Extension.props
new file mode 100644
index 0000000..d182524
--- /dev/null
+++ b/OF DL/Extension.props
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/OF DL/Helpers/APIHelper.cs b/OF DL/Helpers/APIHelper.cs
index d82be2f..ed812f8 100644
--- a/OF DL/Helpers/APIHelper.cs
+++ b/OF DL/Helpers/APIHelper.cs
@@ -2873,4 +2873,81 @@ public class APIHelper : IAPIHelper
}
return null;
}
+
+ public async Task?> GetActiveSubscribed(string endpoint, bool includeRestricted, IDownloadConfig config)
+ {
+ Dictionary getParams = new()
+ {
+ { "offset", "0" },
+ { "limit", "50" },
+ { "type", "active" },
+ { "format", "infinite"}
+ };
+
+ return await GetSubscriptions(getParams, endpoint, includeRestricted, config);
+ }
+
+ public async Task?> GetSubscriptions(Dictionary getParams, string endpoint, bool includeRestricted, IDownloadConfig config)
+ {
+ try
+ {
+ Dictionary users = new();
+ Subscriptions subscriptions = new();
+
+ Log.Debug("Calling GetAllSubscrptions");
+
+ string? body = await BuildHeaderAndExecuteRequests(getParams, endpoint, new HttpClient());
+
+ subscriptions = JsonConvert.DeserializeObject(body);
+ if (subscriptions != null && subscriptions.hasMore)
+ {
+ getParams["offset"] = subscriptions.list.Count.ToString();
+
+ while (true)
+ {
+ Subscriptions newSubscriptions = new();
+ string? loopbody = await BuildHeaderAndExecuteRequests(getParams, endpoint, new HttpClient());
+
+ if (!string.IsNullOrEmpty(loopbody) && (!loopbody.Contains("[]") || loopbody.Trim() != "[]"))
+ {
+ newSubscriptions = JsonConvert.DeserializeObject(loopbody, m_JsonSerializerSettings);
+ }
+ else
+ {
+ break;
+ }
+
+ subscriptions.list.AddRange(newSubscriptions.list);
+ if (!newSubscriptions.hasMore)
+ {
+ break;
+ }
+ getParams["offset"] = subscriptions.list.Count.ToString();
+ }
+ }
+
+ foreach (Subscriptions.List subscription in subscriptions.list)
+ {
+ if ((!(subscription.isRestricted ?? false) || ((subscription.isRestricted ?? false) && includeRestricted))
+ && !users.ContainsKey(subscription.username))
+ {
+ users.Add(subscription.username, subscription);
+ }
+ }
+
+ return users;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace);
+ Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace);
+ if (ex.InnerException != null)
+ {
+ Console.WriteLine("\nInner Exception:");
+ Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace);
+ Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace);
+ }
+ }
+ return null;
+ }
}
diff --git a/OF DL/OF DL.csproj b/OF DL/OF DL.csproj
index 20dc207..f14d2e6 100644
--- a/OF DL/OF DL.csproj
+++ b/OF DL/OF DL.csproj
@@ -1,49 +1,50 @@
-
- Exe
- net8.0
- OF_DL
- enable
- enable
- Icon\download.ico
-
+
+ Exe
+ net8.0
+ OF_DL
+ enable
+ enable
+ Icon\download.ico
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
- References\Spectre.Console.dll
-
-
+
+
+ References\Spectre.Console.dll
+
+
-
-
- Always
-
-
- Always
-
-
- Always
-
-
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+
diff --git a/OF DL/Program.cs b/OF DL/Program.cs
index b47be8c..55316fd 100644
--- a/OF DL/Program.cs
+++ b/OF DL/Program.cs
@@ -844,9 +844,17 @@ public class Program
{
DateTime startTime = DateTime.Now;
Dictionary users = new();
- Dictionary activeSubs = await m_ApiHelper.GetActiveSubscriptions("/subscriptions/subscribes", Config.IncludeRestrictedSubscriptions, Config);
-
- Log.Debug("Subscriptions: ");
+ var activeSubbed = await m_ApiHelper.GetActiveSubscribed("/subscriptions/subscribes", Config.IncludeRestrictedSubscriptions, Config);
+ var activeSubs = activeSubbed?.ToDictionary(e => e.Key, e => e.Value.id);
+ {
+ if (Directory.Exists(Config.DownloadPath) && activeSubbed != null)
+ {
+ var reportPath = Path.Combine(Config.DownloadPath, "Report.csv");
+ var report = new Reporting(activeSubbed?.Values);
+ report.GenerateReport(reportPath);
+ }
+ }
+ Log.Debug("Subscriptions: ");
foreach (KeyValuePair activeSub in activeSubs)
{
diff --git a/OF DL/Reporting.cs b/OF DL/Reporting.cs
new file mode 100644
index 0000000..a37bc8d
--- /dev/null
+++ b/OF DL/Reporting.cs
@@ -0,0 +1,106 @@
+using CsvHelper;
+using CsvHelper.Configuration;
+using System.Formats.Asn1;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+
+namespace OF_DL;
+
+internal class Reporting(IEnumerable subscribedUsers)
+{
+ public void GenerateReport(string reportPath)
+ {
+ using var fileStream = File.Open(reportPath, FileMode.Create);
+ using var streamWriter = new StreamWriter(fileStream);
+ using var csvWriter = new CsvWriter(streamWriter, CultureInfo.InvariantCulture);
+
+ csvWriter.Context.RegisterClassMap();
+ csvWriter.WriteRecords(subscribedUsers.Select(user => new UserReportViewModel(user)).OrderByDescending(e => e.category).ThenBy(e => e.currentTotal));
+ }
+}
+
+internal class UserReportViewModel
+{
+ private readonly Entities.Subscriptions.List source;
+
+ public const long YoursId = 817758071L;
+ public const long MineId = 817758033L;
+ public const decimal tax = 0.2m;
+
+ private Lazy _category;
+ private Lazy _currentPrice;
+ private Lazy _nextPrice;
+
+ public UserReportViewModel(Entities.Subscriptions.List source)
+ {
+ this.source = source;
+ _category = new Lazy(GetCategory);
+ _currentPrice = new Lazy(() => decimal.TryParse(source.subscribedByData.price, out var price) ? price : null);
+ _nextPrice = new Lazy(() => decimal.TryParse(source.subscribedByData.regularPrice, out var price) ? price : null);
+ }
+
+ public string name => source.name;
+
+ public string username => source.username;
+
+ public string category => GetCategory();
+
+ public string status => GetStatus();
+
+ public DateTime? until => source.subscribedByData.expiredAt;
+
+ public decimal? currentPrice => _currentPrice.Value;
+
+ public decimal? currentTax => currentPrice * tax;
+
+ public decimal? currentTotal => currentPrice + currentTax;
+
+ public decimal? renewPrice => _nextPrice.Value;
+
+ public decimal? renewTax => renewPrice * tax;
+
+ public decimal? renewTotal => renewPrice + renewTax;
+
+ public string GetCategory()
+ {
+ if (source.listsStates.SingleOrDefault(l => l.id is long intId && intId == YoursId && l.hasUser == true) is { } yours)
+ {
+ return yours.name;
+ }
+ if (source.listsStates.SingleOrDefault(l => l.id is long intId && intId == MineId && l.hasUser == true) is { } mine)
+ {
+ return mine.name;
+ }
+ return "None";
+ }
+
+ public string GetStatus()
+ {
+ if (source.subscribedByData is { } subData)
+ {
+ if (!string.IsNullOrEmpty(subData.status)) return subData.status;
+ return "Subscribed";
+ }
+ return "API Error";
+ }
+
+}
+
+internal class UserReportViewModelClassMap : ClassMap
+{
+ public UserReportViewModelClassMap()
+ {
+ var index = 0;
+ Map(m => m.name).Index(index++).Name("Name");
+ Map(m => m.username).Index(index++).Name("Username");
+ Map(m => m.category).Index(index++).Name("Category");
+ Map(m => m.status).Index(index++).Name("Status");
+ Map(m => m.until).Index(index++).Name("Until");
+ Map(m => m.currentPrice).Index(index++).Name("Price");
+ Map(m => m.currentTax).Index(index++).Name("Tax");
+ Map(m => m.currentTotal).Index(index++).Name("Total");
+ Map(m => m.renewPrice).Index(index++).Name("Price");
+ Map(m => m.renewTax).Index(index++).Name("Tax");
+ Map(m => m.renewTotal).Index(index++).Name("Total");
+ }
+}