diff --git a/Aaru.Core/Statistics.cs b/Aaru.Core/Statistics.cs
index 5027ef225..abd39a542 100644
--- a/Aaru.Core/Statistics.cs
+++ b/Aaru.Core/Statistics.cs
@@ -37,7 +37,7 @@ using System.Linq;
using System.Net;
using System.Text;
using System.Text.Json;
-using System.Threading;
+using System.Threading.Tasks;
using Aaru.CommonTypes.Interop;
using Aaru.CommonTypes.Metadata;
using Aaru.Console;
@@ -93,13 +93,13 @@ public static class Statistics
}
/// Saves statistics to disk
- public static void SaveStats()
+ public static async Task SaveStats()
{
try
{
- using var ctx = AaruContext.Create(Settings.Settings.LocalDbPath);
+ await using var ctx = AaruContext.Create(Settings.Settings.LocalDbPath);
- ctx.SaveChanges();
+ await ctx.SaveChangesAsync();
}
catch(SqliteException ex)
{
@@ -107,562 +107,232 @@ public static class Statistics
AaruConsole.WriteException(ex);
}
- if(Settings.Settings.Current.Stats is { ShareStats: true }) SubmitStats();
+ if(Settings.Settings.Current.Stats is { ShareStats: true }) await SubmitStats();
}
/// Submits statistics to Aaru.Server
- static void SubmitStats()
+ static async Task SubmitStats()
{
- var submitThread = new Thread(() =>
+ await using var ctx = AaruContext.Create(Settings.Settings.LocalDbPath);
+
+ try
{
- using var ctx = AaruContext.Create(Settings.Settings.LocalDbPath);
+ if(_submitStatsLock) return;
- try
+ _submitStatsLock = true;
+
+ if(ctx.Commands.Any(c => !c.Synchronized) ||
+ ctx.Filesystems.Any(c => !c.Synchronized) ||
+ ctx.Filters.Any(c => !c.Synchronized) ||
+ ctx.MediaFormats.Any(c => !c.Synchronized) ||
+ ctx.Partitions.Any(c => !c.Synchronized) ||
+ ctx.Medias.Any(c => !c.Synchronized) ||
+ ctx.SeenDevices.Any(c => !c.Synchronized) ||
+ ctx.OperatingSystems.Any(c => !c.Synchronized) ||
+ ctx.Versions.Any(c => !c.Synchronized) ||
+ ctx.RemoteApplications.Any(c => !c.Synchronized) ||
+ ctx.RemoteArchitectures.Any(c => !c.Synchronized) ||
+ ctx.RemoteOperatingSystems.Any(c => !c.Synchronized))
{
- if(_submitStatsLock) return;
+ var dto = new StatsDto();
- _submitStatsLock = true;
-
- if(ctx.Commands.Any(c => !c.Synchronized) ||
- ctx.Filesystems.Any(c => !c.Synchronized) ||
- ctx.Filters.Any(c => !c.Synchronized) ||
- ctx.MediaFormats.Any(c => !c.Synchronized) ||
- ctx.Partitions.Any(c => !c.Synchronized) ||
- ctx.Medias.Any(c => !c.Synchronized) ||
- ctx.SeenDevices.Any(c => !c.Synchronized) ||
- ctx.OperatingSystems.Any(c => !c.Synchronized) ||
- ctx.Versions.Any(c => !c.Synchronized) ||
- ctx.RemoteApplications.Any(c => !c.Synchronized) ||
- ctx.RemoteArchitectures.Any(c => !c.Synchronized) ||
- ctx.RemoteOperatingSystems.Any(c => !c.Synchronized))
+ if(ctx.Commands.Any(c => !c.Synchronized))
{
- var dto = new StatsDto();
+ dto.Commands = [];
- if(ctx.Commands.Any(c => !c.Synchronized))
+ foreach(string nvs in ctx.Commands.Where(c => !c.Synchronized).Select(c => c.Name).Distinct())
{
- dto.Commands = [];
-
- foreach(string nvs in ctx.Commands.Where(c => !c.Synchronized).Select(c => c.Name).Distinct())
+ dto.Commands.Add(new NameValueStats
{
- dto.Commands.Add(new NameValueStats
+ name = nvs,
+ Value = ctx.Commands.LongCount(c => !c.Synchronized && c.Name == nvs)
+ });
+ }
+ }
+
+ if(ctx.Filesystems.Any(c => !c.Synchronized))
+ {
+ dto.Filesystems = [];
+
+ foreach(string nvs in ctx.Filesystems.Where(c => !c.Synchronized).Select(c => c.Name).Distinct())
+ {
+ dto.Filesystems.Add(new NameValueStats
+ {
+ name = nvs,
+ Value = ctx.Filesystems.LongCount(c => !c.Synchronized && c.Name == nvs)
+ });
+ }
+ }
+
+ if(ctx.Filters.Any(c => !c.Synchronized))
+ {
+ dto.Filters = [];
+
+ foreach(string nvs in ctx.Filters.Where(c => !c.Synchronized).Select(c => c.Name).Distinct())
+ {
+ dto.Filters.Add(new NameValueStats
+ {
+ name = nvs,
+ Value = ctx.Filters.LongCount(c => !c.Synchronized && c.Name == nvs)
+ });
+ }
+ }
+
+ if(ctx.MediaFormats.Any(c => !c.Synchronized))
+ {
+ dto.MediaFormats = [];
+
+ foreach(string nvs in ctx.MediaFormats.Where(c => !c.Synchronized).Select(c => c.Name).Distinct())
+ {
+ dto.MediaFormats.Add(new NameValueStats
+ {
+ name = nvs,
+ Value = ctx.MediaFormats.LongCount(c => !c.Synchronized && c.Name == nvs)
+ });
+ }
+ }
+
+ if(ctx.Partitions.Any(c => !c.Synchronized))
+ {
+ dto.Partitions = [];
+
+ foreach(string nvs in ctx.Partitions.Where(c => !c.Synchronized).Select(c => c.Name).Distinct())
+ {
+ dto.Partitions.Add(new NameValueStats
+ {
+ name = nvs,
+ Value = ctx.Partitions.LongCount(c => !c.Synchronized && c.Name == nvs)
+ });
+ }
+ }
+
+ if(ctx.Versions.Any(c => !c.Synchronized))
+ {
+ dto.Versions = [];
+
+ foreach(string nvs in ctx.Versions.Where(c => !c.Synchronized).Select(c => c.Name).Distinct())
+ {
+ dto.Versions.Add(new NameValueStats
+ {
+ name = nvs,
+ Value = ctx.Versions.LongCount(c => !c.Synchronized && c.Name == nvs)
+ });
+ }
+ }
+
+ if(ctx.Medias.Any(c => !c.Synchronized))
+ {
+ dto.Medias = [];
+
+ foreach(string media in ctx.Medias.Where(c => !c.Synchronized).Select(c => c.Type).Distinct())
+ {
+ if(ctx.Medias.Any(c => !c.Synchronized && c.Type == media && c.Real))
+ {
+ dto.Medias.Add(new MediaStats
{
- name = nvs,
- Value = ctx.Commands.LongCount(c => !c.Synchronized && c.Name == nvs)
+ real = true,
+ MediaType = media,
+ Value = ctx.Medias.LongCount(c => !c.Synchronized && c.Type == media && c.Real)
+ });
+ }
+
+ if(ctx.Medias.Any(c => !c.Synchronized && c.Type == media && !c.Real))
+ {
+ dto.Medias.Add(new MediaStats
+ {
+ real = false,
+ MediaType = media,
+ Value = ctx.Medias.LongCount(c => !c.Synchronized && c.Type == media && !c.Real)
});
}
}
+ }
- if(ctx.Filesystems.Any(c => !c.Synchronized))
+ if(ctx.SeenDevices.Any(c => !c.Synchronized))
+ {
+ dto.Devices = [];
+
+ foreach(DeviceStat device in ctx.SeenDevices.Where(c => !c.Synchronized))
{
- dto.Filesystems = [];
-
- foreach(string nvs in ctx.Filesystems.Where(c => !c.Synchronized)
- .Select(c => c.Name)
- .Distinct())
+ dto.Devices.Add(new DeviceStats
{
- dto.Filesystems.Add(new NameValueStats
+ Bus = device.Bus,
+ Manufacturer = device.Manufacturer,
+ ManufacturerSpecified = device.Manufacturer is not null,
+ Model = device.Model,
+ Revision = device.Revision
+ });
+ }
+ }
+
+ if(ctx.OperatingSystems.Any(c => !c.Synchronized))
+ {
+ dto.OperatingSystems = [];
+
+ foreach(string osName in ctx.OperatingSystems.Where(c => !c.Synchronized)
+ .Select(c => c.Name)
+ .Distinct())
+ {
+ foreach(string osVersion in ctx.OperatingSystems.Where(c => !c.Synchronized && c.Name == osName)
+ .Select(c => c.Version)
+ .Distinct())
+ {
+ dto.OperatingSystems.Add(new OsStats
{
- name = nvs,
- Value = ctx.Filesystems.LongCount(c => !c.Synchronized && c.Name == nvs)
+ name = osName,
+ version = osVersion,
+ Value = ctx.OperatingSystems.LongCount(c => !c.Synchronized &&
+ c.Name == osName &&
+ c.Version == osVersion)
});
}
}
+ }
- if(ctx.Filters.Any(c => !c.Synchronized))
+ if(ctx.RemoteApplications.Any(c => !c.Synchronized))
+ {
+ dto.RemoteApplications = [];
+
+ foreach(string remoteAppName in ctx.RemoteApplications.Where(c => !c.Synchronized)
+ .Select(c => c.Name)
+ .Distinct())
{
- dto.Filters = [];
-
- foreach(string nvs in ctx.Filters.Where(c => !c.Synchronized).Select(c => c.Name).Distinct())
+ foreach(string remoteAppVersion in ctx.RemoteApplications
+ .Where(c => !c.Synchronized && c.Name == remoteAppName)
+ .Select(c => c.Version)
+ .Distinct())
{
- dto.Filters.Add(new NameValueStats
+ dto.RemoteApplications.Add(new OsStats
{
- name = nvs,
- Value = ctx.Filters.LongCount(c => !c.Synchronized && c.Name == nvs)
+ name = remoteAppName,
+ version = remoteAppVersion,
+ Value = ctx.RemoteApplications.LongCount(c => !c.Synchronized &&
+ c.Name == remoteAppName &&
+ c.Version == remoteAppVersion)
});
}
}
+ }
- if(ctx.MediaFormats.Any(c => !c.Synchronized))
+ if(ctx.RemoteArchitectures.Any(c => !c.Synchronized))
+ {
+ dto.RemoteArchitectures = [];
+
+ foreach(string nvs in ctx.RemoteArchitectures.Where(c => !c.Synchronized)
+ .Select(c => c.Name)
+ .Distinct())
{
- dto.MediaFormats = [];
-
- foreach(string nvs in ctx.MediaFormats.Where(c => !c.Synchronized)
- .Select(c => c.Name)
- .Distinct())
+ dto.RemoteArchitectures.Add(new NameValueStats
{
- dto.MediaFormats.Add(new NameValueStats
- {
- name = nvs,
- Value = ctx.MediaFormats.LongCount(c => !c.Synchronized && c.Name == nvs)
- });
- }
+ name = nvs,
+ Value = ctx.RemoteArchitectures.LongCount(c => !c.Synchronized && c.Name == nvs)
+ });
}
+ }
- if(ctx.Partitions.Any(c => !c.Synchronized))
- {
- dto.Partitions = [];
-
- foreach(string nvs in ctx.Partitions.Where(c => !c.Synchronized).Select(c => c.Name).Distinct())
- {
- dto.Partitions.Add(new NameValueStats
- {
- name = nvs,
- Value = ctx.Partitions.LongCount(c => !c.Synchronized && c.Name == nvs)
- });
- }
- }
-
- if(ctx.Versions.Any(c => !c.Synchronized))
- {
- dto.Versions = [];
-
- foreach(string nvs in ctx.Versions.Where(c => !c.Synchronized).Select(c => c.Name).Distinct())
- {
- dto.Versions.Add(new NameValueStats
- {
- name = nvs,
- Value = ctx.Versions.LongCount(c => !c.Synchronized && c.Name == nvs)
- });
- }
- }
-
- if(ctx.Medias.Any(c => !c.Synchronized))
- {
- dto.Medias = [];
-
- foreach(string media in ctx.Medias.Where(c => !c.Synchronized).Select(c => c.Type).Distinct())
- {
- if(ctx.Medias.Any(c => !c.Synchronized && c.Type == media && c.Real))
- {
- dto.Medias.Add(new MediaStats
- {
- real = true,
- MediaType = media,
- Value = ctx.Medias.LongCount(c => !c.Synchronized && c.Type == media && c.Real)
- });
- }
-
- if(ctx.Medias.Any(c => !c.Synchronized && c.Type == media && !c.Real))
- {
- dto.Medias.Add(new MediaStats
- {
- real = false,
- MediaType = media,
- Value = ctx.Medias.LongCount(c => !c.Synchronized && c.Type == media && !c.Real)
- });
- }
- }
- }
-
- if(ctx.SeenDevices.Any(c => !c.Synchronized))
- {
- dto.Devices = [];
-
- foreach(DeviceStat device in ctx.SeenDevices.Where(c => !c.Synchronized))
- {
- dto.Devices.Add(new DeviceStats
- {
- Bus = device.Bus,
- Manufacturer = device.Manufacturer,
- ManufacturerSpecified = device.Manufacturer is not null,
- Model = device.Model,
- Revision = device.Revision
- });
- }
- }
-
- if(ctx.OperatingSystems.Any(c => !c.Synchronized))
- {
- dto.OperatingSystems = [];
-
- foreach(string osName in ctx.OperatingSystems.Where(c => !c.Synchronized)
- .Select(c => c.Name)
- .Distinct())
- {
- foreach(string osVersion in ctx.OperatingSystems
- .Where(c => !c.Synchronized && c.Name == osName)
- .Select(c => c.Version)
- .Distinct())
- {
- dto.OperatingSystems.Add(new OsStats
- {
- name = osName,
- version = osVersion,
- Value = ctx.OperatingSystems.LongCount(c => !c.Synchronized &&
- c.Name == osName &&
- c.Version == osVersion)
- });
- }
- }
- }
-
- if(ctx.RemoteApplications.Any(c => !c.Synchronized))
- {
- dto.RemoteApplications = [];
-
- foreach(string remoteAppName in ctx.RemoteApplications.Where(c => !c.Synchronized)
- .Select(c => c.Name)
- .Distinct())
- {
- foreach(string remoteAppVersion in ctx.RemoteApplications
- .Where(c => !c.Synchronized &&
- c.Name == remoteAppName)
- .Select(c => c.Version)
- .Distinct())
- {
- dto.RemoteApplications.Add(new OsStats
- {
- name = remoteAppName,
- version = remoteAppVersion,
- Value = ctx.RemoteApplications.LongCount(c => !c.Synchronized &&
- c.Name == remoteAppName &&
- c.Version == remoteAppVersion)
- });
- }
- }
- }
-
- if(ctx.RemoteArchitectures.Any(c => !c.Synchronized))
- {
- dto.RemoteArchitectures = [];
-
- foreach(string nvs in ctx.RemoteArchitectures.Where(c => !c.Synchronized)
- .Select(c => c.Name)
- .Distinct())
- {
- dto.RemoteArchitectures.Add(new NameValueStats
- {
- name = nvs,
- Value = ctx.RemoteArchitectures.LongCount(c => !c.Synchronized && c.Name == nvs)
- });
- }
- }
-
- if(ctx.RemoteOperatingSystems.Any(c => !c.Synchronized))
- {
- dto.RemoteOperatingSystems = [];
-
- foreach(string remoteOsName in ctx.RemoteOperatingSystems.Where(c => !c.Synchronized)
- .Select(c => c.Name)
- .Distinct())
- {
- foreach(string remoteOsVersion in ctx.RemoteOperatingSystems
- .Where(c => !c.Synchronized && c.Name == remoteOsName)
- .Select(c => c.Version)
- .Distinct())
- {
- dto.RemoteOperatingSystems.Add(new OsStats
- {
- name = remoteOsName,
- version = remoteOsVersion,
- Value = ctx.RemoteOperatingSystems.LongCount(c => !c.Synchronized &&
- c.Name == remoteOsName &&
- c.Version == remoteOsVersion)
- });
- }
- }
- }
-
-#if DEBUG
- System.Console.WriteLine(Localization.Core.Uploading_statistics);
-#else
- Aaru.Console.AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Core.Uploading_statistics);
-#endif
- string json = JsonSerializer.Serialize(dto, typeof(StatsDto), StatsDtoContext.Default);
-
- byte[] jsonBytes = Encoding.UTF8.GetBytes(json);
- var request = WebRequest.Create("https://www.aaru.app/api/uploadstatsv2");
-
- ((HttpWebRequest)request).UserAgent = $"Aaru {typeof(Version).Assembly.GetName().Version}";
-
- request.Method = "POST";
- request.ContentLength = jsonBytes.Length;
- request.ContentType = "application/json";
- Stream reqStream = request.GetRequestStream();
- reqStream.Write(jsonBytes, 0, jsonBytes.Length);
-
- //jsonStream.CopyTo(reqStream);
- reqStream.Close();
- WebResponse response = request.GetResponse();
-
- if(((HttpWebResponse)response).StatusCode != HttpStatusCode.OK) return;
-
- Stream data = response.GetResponseStream();
- var reader = new StreamReader(data ?? throw new InvalidOperationException());
-
- string result = reader.ReadToEnd();
- data.Close();
- response.Close();
-
- if(result != "ok") return;
-
- if(ctx.Commands.Any(c => !c.Synchronized))
- {
- foreach(string nvs in ctx.Commands.Where(c => !c.Synchronized).Select(c => c.Name).Distinct())
- {
- Command existing = ctx.Commands.FirstOrDefault(c => c.Synchronized && c.Name == nvs) ??
- new Command
- {
- Name = nvs,
- Synchronized = true
- };
-
- existing.Count += (ulong)ctx.Commands.LongCount(c => !c.Synchronized && c.Name == nvs);
- ctx.Commands.Update(existing);
- ctx.Commands.RemoveRange(ctx.Commands.Where(c => !c.Synchronized && c.Name == nvs));
- }
- }
-
- if(ctx.Filesystems.Any(c => !c.Synchronized))
- {
- foreach(string nvs in ctx.Filesystems.Where(c => !c.Synchronized)
- .Select(c => c.Name)
- .Distinct())
- {
- Filesystem existing =
- ctx.Filesystems.FirstOrDefault(c => c.Synchronized && c.Name == nvs) ??
- new Filesystem
- {
- Name = nvs,
- Synchronized = true
- };
-
- existing.Count += (ulong)ctx.Filesystems.LongCount(c => !c.Synchronized && c.Name == nvs);
-
- ctx.Filesystems.Update(existing);
-
- ctx.Filesystems.RemoveRange(ctx.Filesystems.Where(c => !c.Synchronized && c.Name == nvs));
- }
- }
-
- if(ctx.Filters.Any(c => !c.Synchronized))
- {
- foreach(string nvs in ctx.Filters.Where(c => !c.Synchronized).Select(c => c.Name).Distinct())
- {
- Filter existing = ctx.Filters.FirstOrDefault(c => c.Synchronized && c.Name == nvs) ??
- new Filter
- {
- Name = nvs,
- Synchronized = true
- };
-
- existing.Count += (ulong)ctx.Filters.LongCount(c => !c.Synchronized && c.Name == nvs);
- ctx.Filters.Update(existing);
- ctx.Filters.RemoveRange(ctx.Filters.Where(c => !c.Synchronized && c.Name == nvs));
- }
- }
-
- if(ctx.MediaFormats.Any(c => !c.Synchronized))
- {
- foreach(string nvs in ctx.MediaFormats.Where(c => !c.Synchronized)
- .Select(c => c.Name)
- .Distinct())
- {
- MediaFormat existing =
- ctx.MediaFormats.FirstOrDefault(c => c.Synchronized && c.Name == nvs) ??
- new MediaFormat
- {
- Name = nvs,
- Synchronized = true
- };
-
- existing.Count += (ulong)ctx.MediaFormats.LongCount(c => !c.Synchronized && c.Name == nvs);
-
- ctx.MediaFormats.Update(existing);
-
- ctx.MediaFormats.RemoveRange(ctx.MediaFormats.Where(c => !c.Synchronized && c.Name == nvs));
- }
- }
-
- if(ctx.Partitions.Any(c => !c.Synchronized))
- {
- foreach(string nvs in ctx.Partitions.Where(c => !c.Synchronized).Select(c => c.Name).Distinct())
- {
- Partition existing = ctx.Partitions.FirstOrDefault(c => c.Synchronized && c.Name == nvs) ??
- new Partition
- {
- Name = nvs,
- Synchronized = true
- };
-
- existing.Count += (ulong)ctx.Partitions.LongCount(c => !c.Synchronized && c.Name == nvs);
-
- ctx.Partitions.Update(existing);
- ctx.Partitions.RemoveRange(ctx.Partitions.Where(c => !c.Synchronized && c.Name == nvs));
- }
- }
-
- if(ctx.Versions.Any(c => !c.Synchronized))
- {
- foreach(string nvs in ctx.Versions.Where(c => !c.Synchronized).Select(c => c.Name).Distinct())
- {
- Version existing = ctx.Versions.FirstOrDefault(c => c.Synchronized && c.Name == nvs) ??
- new Version
- {
- Name = nvs,
- Synchronized = true
- };
-
- existing.Count += (ulong)ctx.Versions.LongCount(c => !c.Synchronized && c.Name == nvs);
- ctx.Versions.Update(existing);
- ctx.Versions.RemoveRange(ctx.Versions.Where(c => !c.Synchronized && c.Name == nvs));
- }
- }
-
- if(ctx.Medias.Any(c => !c.Synchronized))
- {
- foreach(string media in ctx.Medias.Where(c => !c.Synchronized).Select(c => c.Type).Distinct())
- {
- if(ctx.Medias.Any(c => !c.Synchronized && c.Type == media && c.Real))
- {
- Database.Models.Media existing =
- ctx.Medias.FirstOrDefault(c => c.Synchronized && c.Type == media && c.Real) ??
- new Database.Models.Media
- {
- Synchronized = true,
- Type = media,
- Real = true
- };
-
- existing.Count +=
- (ulong)ctx.Medias.LongCount(c => !c.Synchronized && c.Type == media && c.Real);
-
- ctx.Medias.Update(existing);
-
- ctx.Medias.RemoveRange(ctx.Medias.Where(c => !c.Synchronized &&
- c.Type == media &&
- c.Real));
- }
-
- if(!ctx.Medias.Any(c => !c.Synchronized && c.Type == media && !c.Real)) continue;
-
- {
- Database.Models.Media existing =
- ctx.Medias.FirstOrDefault(c => c.Synchronized && c.Type == media && !c.Real) ??
- new Database.Models.Media
- {
- Synchronized = true,
- Type = media,
- Real = false
- };
-
- existing.Count +=
- (ulong)ctx.Medias.LongCount(c => !c.Synchronized && c.Type == media && !c.Real);
-
- ctx.Medias.Update(existing);
-
- ctx.Medias.RemoveRange(ctx.Medias.Where(c => !c.Synchronized &&
- c.Type == media &&
- !c.Real));
- }
- }
- }
-
- if(ctx.SeenDevices.Any(c => !c.Synchronized))
- {
- foreach(DeviceStat device in ctx.SeenDevices.Where(c => !c.Synchronized))
- {
- device.Synchronized = true;
- ctx.Update(device);
- }
- }
-
- if(ctx.OperatingSystems.Any(c => !c.Synchronized))
- {
- foreach(string osName in ctx.OperatingSystems.Where(c => !c.Synchronized)
- .Select(c => c.Name)
- .Distinct())
- {
- foreach(string osVersion in ctx.OperatingSystems
- .Where(c => !c.Synchronized && c.Name == osName)
- .Select(c => c.Version)
- .Distinct())
- {
- OperatingSystem existing =
- ctx.OperatingSystems.FirstOrDefault(c => c.Synchronized &&
- c.Name == osName &&
- c.Version == osVersion) ??
- new OperatingSystem
- {
- Synchronized = true,
- Version = osVersion,
- Name = osName
- };
-
- existing.Count +=
- (ulong)ctx.OperatingSystems.LongCount(c => !c.Synchronized &&
- c.Name == osName &&
- c.Version == osVersion);
-
- ctx.OperatingSystems.Update(existing);
-
- ctx.OperatingSystems.RemoveRange(ctx.OperatingSystems.Where(c => !c.Synchronized &&
- c.Name == osName &&
- c.Version == osVersion));
- }
- }
- }
-
- if(ctx.RemoteApplications.Any(c => !c.Synchronized))
- {
- foreach(string remoteAppName in ctx.RemoteApplications.Where(c => !c.Synchronized)
- .Select(c => c.Name)
- .Distinct())
- {
- foreach(string remoteAppVersion in ctx.RemoteApplications
- .Where(c => !c.Synchronized &&
- c.Name == remoteAppName)
- .Select(c => c.Version)
- .Distinct())
- {
- RemoteApplication existing =
- ctx.RemoteApplications.FirstOrDefault(c => c.Synchronized &&
- c.Name == remoteAppName &&
- c.Version == remoteAppVersion) ??
- new RemoteApplication
- {
- Synchronized = true,
- Version = remoteAppVersion,
- Name = remoteAppName
- };
-
- existing.Count +=
- (ulong)ctx.RemoteApplications.LongCount(c => !c.Synchronized &&
- c.Name == remoteAppName &&
- c.Version == remoteAppVersion);
-
- ctx.RemoteApplications.Update(existing);
-
- ctx.RemoteApplications.RemoveRange(ctx.RemoteApplications.Where(c => !c.Synchronized &&
- c.Name == remoteAppName &&
- c.Version == remoteAppVersion));
- }
- }
- }
-
- if(ctx.RemoteArchitectures.Any(c => !c.Synchronized))
- {
- foreach(string nvs in ctx.RemoteArchitectures.Where(c => !c.Synchronized)
- .Select(c => c.Name)
- .Distinct())
- {
- RemoteArchitecture existing =
- ctx.RemoteArchitectures.FirstOrDefault(c => c.Synchronized && c.Name == nvs) ??
- new RemoteArchitecture
- {
- Name = nvs,
- Synchronized = true
- };
-
- existing.Count +=
- (ulong)ctx.RemoteArchitectures.LongCount(c => !c.Synchronized && c.Name == nvs);
-
- ctx.RemoteArchitectures.Update(existing);
-
- ctx.RemoteArchitectures.RemoveRange(ctx.RemoteArchitectures.Where(c => !c.Synchronized &&
- c.Name == nvs));
- }
- }
+ if(ctx.RemoteOperatingSystems.Any(c => !c.Synchronized))
+ {
+ dto.RemoteOperatingSystems = [];
foreach(string remoteOsName in ctx.RemoteOperatingSystems.Where(c => !c.Synchronized)
.Select(c => c.Name)
@@ -673,57 +343,365 @@ public static class Statistics
.Select(c => c.Version)
.Distinct())
{
- RemoteOperatingSystem existing =
- ctx.RemoteOperatingSystems.FirstOrDefault(c => c.Synchronized &&
- c.Name == remoteOsName &&
- c.Version == remoteOsVersion) ??
- new RemoteOperatingSystem
+ dto.RemoteOperatingSystems.Add(new OsStats
+ {
+ name = remoteOsName,
+ version = remoteOsVersion,
+ Value = ctx.RemoteOperatingSystems.LongCount(c => !c.Synchronized &&
+ c.Name == remoteOsName &&
+ c.Version == remoteOsVersion)
+ });
+ }
+ }
+ }
+
+#if DEBUG
+ System.Console.WriteLine(Localization.Core.Uploading_statistics);
+#else
+ Aaru.Console.AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Core.Uploading_statistics);
+#endif
+ string json = JsonSerializer.Serialize(dto, typeof(StatsDto), StatsDtoContext.Default);
+
+ byte[] jsonBytes = Encoding.UTF8.GetBytes(json);
+ var request = WebRequest.Create("https://www.aaru.app/api/uploadstatsv2");
+
+ ((HttpWebRequest)request).UserAgent = $"Aaru {typeof(Version).Assembly.GetName().Version}";
+
+ request.Method = "POST";
+ request.ContentLength = jsonBytes.Length;
+ request.ContentType = "application/json";
+ Stream reqStream = await request.GetRequestStreamAsync();
+ await reqStream.WriteAsync(jsonBytes, 0, jsonBytes.Length);
+
+ //jsonStream.CopyTo(reqStream);
+ reqStream.Close();
+ WebResponse response = await request.GetResponseAsync();
+
+ if(((HttpWebResponse)response).StatusCode != HttpStatusCode.OK) return;
+
+ Stream data = response.GetResponseStream();
+ var reader = new StreamReader(data ?? throw new InvalidOperationException());
+
+ string result = await reader.ReadToEndAsync();
+ data.Close();
+ response.Close();
+
+ if(result != "ok") return;
+
+ if(ctx.Commands.Any(c => !c.Synchronized))
+ {
+ foreach(string nvs in ctx.Commands.Where(c => !c.Synchronized).Select(c => c.Name).Distinct())
+ {
+ Command existing = ctx.Commands.FirstOrDefault(c => c.Synchronized && c.Name == nvs) ??
+ new Command
+ {
+ Name = nvs,
+ Synchronized = true
+ };
+
+ existing.Count += (ulong)ctx.Commands.LongCount(c => !c.Synchronized && c.Name == nvs);
+ ctx.Commands.Update(existing);
+ ctx.Commands.RemoveRange(ctx.Commands.Where(c => !c.Synchronized && c.Name == nvs));
+ }
+ }
+
+ if(ctx.Filesystems.Any(c => !c.Synchronized))
+ {
+ foreach(string nvs in ctx.Filesystems.Where(c => !c.Synchronized).Select(c => c.Name).Distinct())
+ {
+ Filesystem existing = ctx.Filesystems.FirstOrDefault(c => c.Synchronized && c.Name == nvs) ??
+ new Filesystem
+ {
+ Name = nvs,
+ Synchronized = true
+ };
+
+ existing.Count += (ulong)ctx.Filesystems.LongCount(c => !c.Synchronized && c.Name == nvs);
+
+ ctx.Filesystems.Update(existing);
+
+ ctx.Filesystems.RemoveRange(ctx.Filesystems.Where(c => !c.Synchronized && c.Name == nvs));
+ }
+ }
+
+ if(ctx.Filters.Any(c => !c.Synchronized))
+ {
+ foreach(string nvs in ctx.Filters.Where(c => !c.Synchronized).Select(c => c.Name).Distinct())
+ {
+ Filter existing = ctx.Filters.FirstOrDefault(c => c.Synchronized && c.Name == nvs) ??
+ new Filter
+ {
+ Name = nvs,
+ Synchronized = true
+ };
+
+ existing.Count += (ulong)ctx.Filters.LongCount(c => !c.Synchronized && c.Name == nvs);
+ ctx.Filters.Update(existing);
+ ctx.Filters.RemoveRange(ctx.Filters.Where(c => !c.Synchronized && c.Name == nvs));
+ }
+ }
+
+ if(ctx.MediaFormats.Any(c => !c.Synchronized))
+ {
+ foreach(string nvs in ctx.MediaFormats.Where(c => !c.Synchronized).Select(c => c.Name).Distinct())
+ {
+ MediaFormat existing = ctx.MediaFormats.FirstOrDefault(c => c.Synchronized && c.Name == nvs) ??
+ new MediaFormat
+ {
+ Name = nvs,
+ Synchronized = true
+ };
+
+ existing.Count += (ulong)ctx.MediaFormats.LongCount(c => !c.Synchronized && c.Name == nvs);
+
+ ctx.MediaFormats.Update(existing);
+
+ ctx.MediaFormats.RemoveRange(ctx.MediaFormats.Where(c => !c.Synchronized && c.Name == nvs));
+ }
+ }
+
+ if(ctx.Partitions.Any(c => !c.Synchronized))
+ {
+ foreach(string nvs in ctx.Partitions.Where(c => !c.Synchronized).Select(c => c.Name).Distinct())
+ {
+ Partition existing = ctx.Partitions.FirstOrDefault(c => c.Synchronized && c.Name == nvs) ??
+ new Partition
+ {
+ Name = nvs,
+ Synchronized = true
+ };
+
+ existing.Count += (ulong)ctx.Partitions.LongCount(c => !c.Synchronized && c.Name == nvs);
+
+ ctx.Partitions.Update(existing);
+ ctx.Partitions.RemoveRange(ctx.Partitions.Where(c => !c.Synchronized && c.Name == nvs));
+ }
+ }
+
+ if(ctx.Versions.Any(c => !c.Synchronized))
+ {
+ foreach(string nvs in ctx.Versions.Where(c => !c.Synchronized).Select(c => c.Name).Distinct())
+ {
+ Version existing = ctx.Versions.FirstOrDefault(c => c.Synchronized && c.Name == nvs) ??
+ new Version
+ {
+ Name = nvs,
+ Synchronized = true
+ };
+
+ existing.Count += (ulong)ctx.Versions.LongCount(c => !c.Synchronized && c.Name == nvs);
+ ctx.Versions.Update(existing);
+ ctx.Versions.RemoveRange(ctx.Versions.Where(c => !c.Synchronized && c.Name == nvs));
+ }
+ }
+
+ if(ctx.Medias.Any(c => !c.Synchronized))
+ {
+ foreach(string media in ctx.Medias.Where(c => !c.Synchronized).Select(c => c.Type).Distinct())
+ {
+ if(ctx.Medias.Any(c => !c.Synchronized && c.Type == media && c.Real))
+ {
+ Database.Models.Media existing =
+ ctx.Medias.FirstOrDefault(c => c.Synchronized && c.Type == media && c.Real) ??
+ new Database.Models.Media
{
Synchronized = true,
- Version = remoteOsVersion,
- Name = remoteOsName
+ Type = media,
+ Real = true
};
existing.Count +=
- (ulong)ctx.RemoteOperatingSystems.LongCount(c => !c.Synchronized &&
- c.Name == remoteOsName &&
- c.Version == remoteOsVersion);
+ (ulong)ctx.Medias.LongCount(c => !c.Synchronized && c.Type == media && c.Real);
- ctx.RemoteOperatingSystems.Update(existing);
+ ctx.Medias.Update(existing);
- ctx.RemoteOperatingSystems.RemoveRange(ctx.RemoteOperatingSystems.Where(c =>
- !c.Synchronized &&
- c.Name == remoteOsName &&
- c.Version == remoteOsVersion));
+ ctx.Medias.RemoveRange(ctx.Medias.Where(c => !c.Synchronized && c.Type == media && c.Real));
+ }
+
+ if(!ctx.Medias.Any(c => !c.Synchronized && c.Type == media && !c.Real)) continue;
+
+ {
+ Database.Models.Media existing =
+ ctx.Medias.FirstOrDefault(c => c.Synchronized && c.Type == media && !c.Real) ??
+ new Database.Models.Media
+ {
+ Synchronized = true,
+ Type = media,
+ Real = false
+ };
+
+ existing.Count +=
+ (ulong)ctx.Medias.LongCount(c => !c.Synchronized && c.Type == media && !c.Real);
+
+ ctx.Medias.Update(existing);
+
+ ctx.Medias.RemoveRange(ctx.Medias.Where(c => !c.Synchronized &&
+ c.Type == media &&
+ !c.Real));
}
}
-
- ctx.SaveChanges();
}
- }
- catch(WebException)
- {
- // Can't connect to the server, do nothing
- }
- catch(DbUpdateConcurrencyException)
- {
- // Ignore db concurrency errors
- }
- // ReSharper disable once RedundantCatchClause
- catch
- {
+ if(ctx.SeenDevices.Any(c => !c.Synchronized))
+ {
+ foreach(DeviceStat device in ctx.SeenDevices.Where(c => !c.Synchronized))
+ {
+ device.Synchronized = true;
+ ctx.Update(device);
+ }
+ }
+
+ if(ctx.OperatingSystems.Any(c => !c.Synchronized))
+ {
+ foreach(string osName in ctx.OperatingSystems.Where(c => !c.Synchronized)
+ .Select(c => c.Name)
+ .Distinct())
+ {
+ foreach(string osVersion in ctx.OperatingSystems.Where(c => !c.Synchronized && c.Name == osName)
+ .Select(c => c.Version)
+ .Distinct())
+ {
+ OperatingSystem existing =
+ ctx.OperatingSystems.FirstOrDefault(c => c.Synchronized &&
+ c.Name == osName &&
+ c.Version == osVersion) ??
+ new OperatingSystem
+ {
+ Synchronized = true,
+ Version = osVersion,
+ Name = osName
+ };
+
+ existing.Count +=
+ (ulong)ctx.OperatingSystems.LongCount(c => !c.Synchronized &&
+ c.Name == osName &&
+ c.Version == osVersion);
+
+ ctx.OperatingSystems.Update(existing);
+
+ ctx.OperatingSystems.RemoveRange(ctx.OperatingSystems.Where(c => !c.Synchronized &&
+ c.Name == osName &&
+ c.Version == osVersion));
+ }
+ }
+ }
+
+ if(ctx.RemoteApplications.Any(c => !c.Synchronized))
+ {
+ foreach(string remoteAppName in ctx.RemoteApplications.Where(c => !c.Synchronized)
+ .Select(c => c.Name)
+ .Distinct())
+ {
+ foreach(string remoteAppVersion in ctx.RemoteApplications
+ .Where(c => !c.Synchronized && c.Name == remoteAppName)
+ .Select(c => c.Version)
+ .Distinct())
+ {
+ RemoteApplication existing =
+ ctx.RemoteApplications.FirstOrDefault(c => c.Synchronized &&
+ c.Name == remoteAppName &&
+ c.Version == remoteAppVersion) ??
+ new RemoteApplication
+ {
+ Synchronized = true,
+ Version = remoteAppVersion,
+ Name = remoteAppName
+ };
+
+ existing.Count +=
+ (ulong)ctx.RemoteApplications.LongCount(c => !c.Synchronized &&
+ c.Name == remoteAppName &&
+ c.Version == remoteAppVersion);
+
+ ctx.RemoteApplications.Update(existing);
+
+ ctx.RemoteApplications.RemoveRange(ctx.RemoteApplications.Where(c => !c.Synchronized &&
+ c.Name == remoteAppName &&
+ c.Version == remoteAppVersion));
+ }
+ }
+ }
+
+ if(ctx.RemoteArchitectures.Any(c => !c.Synchronized))
+ {
+ foreach(string nvs in ctx.RemoteArchitectures.Where(c => !c.Synchronized)
+ .Select(c => c.Name)
+ .Distinct())
+ {
+ RemoteArchitecture existing =
+ ctx.RemoteArchitectures.FirstOrDefault(c => c.Synchronized && c.Name == nvs) ??
+ new RemoteArchitecture
+ {
+ Name = nvs,
+ Synchronized = true
+ };
+
+ existing.Count +=
+ (ulong)ctx.RemoteArchitectures.LongCount(c => !c.Synchronized && c.Name == nvs);
+
+ ctx.RemoteArchitectures.Update(existing);
+
+ ctx.RemoteArchitectures.RemoveRange(ctx.RemoteArchitectures.Where(c => !c.Synchronized &&
+ c.Name == nvs));
+ }
+ }
+
+ foreach(string remoteOsName in ctx.RemoteOperatingSystems.Where(c => !c.Synchronized)
+ .Select(c => c.Name)
+ .Distinct())
+ {
+ foreach(string remoteOsVersion in ctx.RemoteOperatingSystems
+ .Where(c => !c.Synchronized && c.Name == remoteOsName)
+ .Select(c => c.Version)
+ .Distinct())
+ {
+ RemoteOperatingSystem existing =
+ ctx.RemoteOperatingSystems.FirstOrDefault(c => c.Synchronized &&
+ c.Name == remoteOsName &&
+ c.Version == remoteOsVersion) ??
+ new RemoteOperatingSystem
+ {
+ Synchronized = true,
+ Version = remoteOsVersion,
+ Name = remoteOsName
+ };
+
+ existing.Count +=
+ (ulong)ctx.RemoteOperatingSystems.LongCount(c => !c.Synchronized &&
+ c.Name == remoteOsName &&
+ c.Version == remoteOsVersion);
+
+ ctx.RemoteOperatingSystems.Update(existing);
+
+ ctx.RemoteOperatingSystems.RemoveRange(ctx.RemoteOperatingSystems.Where(c => !c.Synchronized &&
+ c.Name == remoteOsName &&
+ c.Version == remoteOsVersion));
+ }
+ }
+
+ await ctx.SaveChangesAsync();
+ }
+ }
+ catch(WebException)
+ {
+ // Can't connect to the server, do nothing
+ }
+ catch(DbUpdateConcurrencyException)
+ {
+ // Ignore db concurrency errors
+ }
+
+ // ReSharper disable once RedundantCatchClause
+ catch
+ {
#if DEBUG
- _submitStatsLock = false;
-
- if(Debugger.IsAttached) throw;
-#endif
- }
-
_submitStatsLock = false;
- });
- submitThread.Start();
+ if(Debugger.IsAttached) throw;
+#endif
+ }
+
+ _submitStatsLock = false;
}
/// Adds the execution of a command to statistics
diff --git a/Aaru.Gui/ViewModels/Windows/SplashWindowViewModel.cs b/Aaru.Gui/ViewModels/Windows/SplashWindowViewModel.cs
index a939d53bd..1655f58c8 100644
--- a/Aaru.Gui/ViewModels/Windows/SplashWindowViewModel.cs
+++ b/Aaru.Gui/ViewModels/Windows/SplashWindowViewModel.cs
@@ -148,8 +148,8 @@ public sealed class SplashWindowViewModel(SplashWindow view) : ViewModelBase
foreach(string migration in ctx.Database.GetPendingMigrations())
{
- ctx.Database
#pragma warning disable EF1002
+ ctx.Database
.ExecuteSqlRaw($"INSERT INTO \"__EFMigrationsHistory\" (MigrationId, ProductVersion) VALUES ('{
migration}', '0.0.0')");
#pragma warning restore EF1002
@@ -294,9 +294,9 @@ public sealed class SplashWindowViewModel(SplashWindow view) : ViewModelBase
Message = UI.Saving_statistics;
AaruConsole.WriteLine(UI.Saving_statistics);
- Task.Run(() =>
+ Task.Run(async () =>
{
- Statistics.SaveStats();
+ await Statistics.SaveStats();
Dispatcher.UIThread.Post(LoadMainWindow);
});
diff --git a/Aaru/Main.cs b/Aaru/Main.cs
index cf60e17fb..723c5e809 100644
--- a/Aaru/Main.cs
+++ b/Aaru/Main.cs
@@ -37,6 +37,7 @@ using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
+using System.Threading.Tasks;
using Aaru.Commands;
using Aaru.Commands.Archive;
using Aaru.Commands.Database;
@@ -62,7 +63,7 @@ class MainClass
static string _assemblyTitle;
static AssemblyInformationalVersionAttribute _assemblyVersion;
- public static int Main([NotNull] string[] args)
+ public static async Task Main([NotNull] string[] args)
{
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
{
@@ -113,14 +114,17 @@ class MainClass
try
{
ctx = AaruContext.Create(Settings.Settings.LocalDbPath, false);
- ctx.Database.Migrate();
+ await ctx.Database.MigrateAsync();
}
catch(NotSupportedException)
{
try
{
- ctx?.Database.CloseConnection();
- ctx?.Dispose();
+ if(ctx is not null)
+ {
+ await ctx.Database.CloseConnectionAsync();
+ await ctx.DisposeAsync();
+ }
}
catch(Exception)
{
@@ -129,21 +133,21 @@ class MainClass
File.Delete(Settings.Settings.LocalDbPath);
ctx = AaruContext.Create(Settings.Settings.LocalDbPath);
- ctx.Database.EnsureCreated();
+ await ctx.Database.EnsureCreatedAsync();
- ctx.Database
- .ExecuteSqlRaw("CREATE TABLE IF NOT EXISTS \"__EFMigrationsHistory\" (\"MigrationId\" TEXT PRIMARY KEY, \"ProductVersion\" TEXT)");
+ await ctx.Database
+ .ExecuteSqlRawAsync("CREATE TABLE IF NOT EXISTS \"__EFMigrationsHistory\" (\"MigrationId\" TEXT PRIMARY KEY, \"ProductVersion\" TEXT)");
- foreach(string migration in ctx.Database.GetPendingMigrations())
+ foreach(string migration in await ctx.Database.GetPendingMigrationsAsync())
{
- ctx.Database
#pragma warning disable EF1002
- .ExecuteSqlRaw($"INSERT INTO \"__EFMigrationsHistory\" (MigrationId, ProductVersion) VALUES ('{
- migration}', '0.0.0')");
+ await ctx.Database
+ .ExecuteSqlRawAsync($"INSERT INTO \"__EFMigrationsHistory\" (MigrationId, ProductVersion) VALUES ('{
+ migration}', '0.0.0')");
#pragma warning restore EF1002
}
- ctx.SaveChanges();
+ await ctx.SaveChangesAsync();
}
// Remove duplicates
@@ -170,7 +174,7 @@ class MainClass
// Remove nulls
ctx.RemoveRange(ctx.SeenDevices.Where(d => d.Manufacturer == null && d.Model == null && d.Revision == null));
- ctx.SaveChanges();
+ await ctx.SaveChangesAsync();
var mainDbUpdate = false;
@@ -182,7 +186,7 @@ class MainClass
var mainContext = AaruContext.Create(Settings.Settings.MainDbPath, false);
- if(mainContext.Database.GetPendingMigrations().Any())
+ if((await mainContext.Database.GetPendingMigrationsAsync()).Any())
{
AaruConsole.WriteLine(UI.New_database_version_updating);
@@ -198,8 +202,8 @@ class MainClass
return (int)ErrorNumber.CannotRemoveDatabase;
}
- mainContext.Database.CloseConnection();
- mainContext.Dispose();
+ await mainContext.Database.CloseConnectionAsync();
+ await mainContext.DisposeAsync();
UpdateCommand.DoUpdate(true);
}
@@ -244,9 +248,9 @@ class MainClass
rootCommand.AddCommand(new ListNamespacesCommand());
rootCommand.AddCommand(new RemoteCommand());
- int ret = rootCommand.Invoke(args);
+ int ret = await rootCommand.InvokeAsync(args);
- Statistics.SaveStats();
+ await Statistics.SaveStats();
if(!rootCommand.Parse(args).RootCommandResult.GetValueForOption(pauseOption)) return ret;