Skip to content

Commit

Permalink
Merge pull request #3246 from marticliment/telemetry
Browse files Browse the repository at this point in the history
  • Loading branch information
marticliment authored Feb 4, 2025
2 parents c2caa3d + dde95ef commit bc2282b
Show file tree
Hide file tree
Showing 11 changed files with 209 additions and 77 deletions.
123 changes: 104 additions & 19 deletions src/UniGetUI.Interface.Telemetry/TelemetryHandler.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,35 @@
using System.ComponentModel.Design;
using System.Net;
using UniGetUI.Core.Data;
using UniGetUI.Core.Language;
using UniGetUI.Core.Logging;
using UniGetUI.Core.SettingsEngine;
using UniGetUI.Core.Tools;
using UniGetUI.PackageEngine;
using UniGetUI.PackageEngine.Enums;
using UniGetUI.PackageEngine.Interfaces;

namespace UniGetUI.Interface.Telemetry;

public enum TEL_InstallReferral
{
DIRECT_SEARCH,
FROM_BUNDLE,
FROM_WEB_SHARE,
ALREADY_INSTALLED,
}

public enum TEL_OP_RESULT
{
SUCCESS,
FAILED,
CANCELED
}

public static class TelemetryHandler
{
private const string HOST = "https://marticliment.com/unigetui/statistics";

private const string HOST = "https://marticliment.com/unigetui/statistics";
private static string[] SettingsToSend =
{
"DisableAutoUpdateWingetUI",
Expand All @@ -30,19 +48,15 @@ public static class TelemetryHandler
"SP2" // UniGetUI was started as daemon
};

// -------------------------------------------------------------------------

public static async void Initialize()
{
try
{
if (Settings.Get("DisableTelemetry")) return;
await CoreTools.WaitForInternetConnection();

if (Settings.GetValue("TelemetryClientToken").Length != 64)
{
Settings.SetValue("TelemetryClientToken", CoreTools.RandomString(64));
}

string ID = Settings.GetValue("TelemetryClientToken");
string ID = GetRandomizedId();

int mask = 0x1;
int ManagerMagicValue = 0;
Expand Down Expand Up @@ -102,43 +116,114 @@ public static async void Initialize()
}
}

public static async void PackageInstalled(IPackage package)
// -------------------------------------------------------------------------

public static void InstallPackage(IPackage package, TEL_OP_RESULT status, TEL_InstallReferral source)
=> PackageEndpoint(package, "install", status, source.ToString());

public static void UpdatePackage(IPackage package, TEL_OP_RESULT status)
=> PackageEndpoint(package, "update", status);

public static void DownloadPackage(IPackage package, TEL_OP_RESULT status, TEL_InstallReferral source)
=> PackageEndpoint(package, "download", status, source.ToString());

public static void UninstallPackage(IPackage package, TEL_OP_RESULT status)
=> PackageEndpoint(package, "uninstall", status);

public static void PackageDetails(IPackage package, string eventSource)
=> PackageEndpoint(package, "details", eventSource: eventSource);

public static void SharedPackage(IPackage package, string eventSource)
=> PackageEndpoint(package, "share", eventSource: eventSource);

private static async void PackageEndpoint(IPackage package, string endpoint, TEL_OP_RESULT? result = null, string? eventSource = null)
{
if (result is null && eventSource is null) throw new NullReferenceException("result and eventSource cannot be both null!");

try
{
if (Settings.Get("DisableTelemetry")) return;
await CoreTools.WaitForInternetConnection();
string ID = GetRandomizedId();

var request = new HttpRequestMessage(HttpMethod.Post, $"{HOST}/package/{endpoint}");

request.Headers.Add("clientId", ID);
request.Headers.Add("packageId", package.Id);
request.Headers.Add("managerName", package.Manager.Name);
request.Headers.Add("sourceName", package.Source.Name);
if(result is not null) request.Headers.Add("operationResult", result.ToString());
if(eventSource is not null) request.Headers.Add("eventSource", eventSource);

HttpClient _httpClient = new(CoreData.GenericHttpClientParameters);
HttpResponseMessage response = await _httpClient.SendAsync(request);

if (Settings.GetValue("TelemetryClientToken").Length != 64)
if (response.IsSuccessStatusCode)
{
Logger.Debug($"[Telemetry] Call to /package/{endpoint} succeeded");
}
else
{
Settings.SetValue("TelemetryClientToken", CoreTools.RandomString(64));
Logger.Warn($"[Telemetry] Call to /package/{endpoint} failed with error code {response.StatusCode}");
}
}
catch (Exception ex)
{
Logger.Error($"[Telemetry] Hard crash when calling /package/{endpoint}");
Logger.Error(ex);
}
}


string ID = Settings.GetValue("TelemetryClientToken");
// -------------------------------------------------------------------------

var request = new HttpRequestMessage(HttpMethod.Post, $"{HOST}/install");
public static void ImportBundle(BundleFormatType type)
=> BundlesEndpoint("import", type);

public static void ExportBundle(BundleFormatType type)
=> BundlesEndpoint("export", type);

private static async void BundlesEndpoint(string endpoint, BundleFormatType type)
{
try
{
if (Settings.Get("DisableTelemetry")) return;
await CoreTools.WaitForInternetConnection();
string ID = GetRandomizedId();

var request = new HttpRequestMessage(HttpMethod.Post, $"{HOST}/bundles/{endpoint}");

request.Headers.Add("clientId", ID);
request.Headers.Add("packageId", package.Id);
request.Headers.Add("managerName", package.Manager.Name);
request.Headers.Add("sourceName", package.Source.Name);
request.Headers.Add("bundleType", type.ToString());

HttpClient _httpClient = new(CoreData.GenericHttpClientParameters);
HttpResponseMessage response = await _httpClient.SendAsync(request);

if (response.IsSuccessStatusCode)
{
Logger.Debug("[Telemetry] Call to /install succeeded");
Logger.Debug($"[Telemetry] Call to /bundles/{endpoint} succeeded");
}
else
{
Logger.Warn($"[Telemetry] Call to /install failed with error code {response.StatusCode}");
Logger.Warn($"[Telemetry] Call to /bundles/{endpoint} failed with error code {response.StatusCode}");
}
}
catch (Exception ex)
{
Logger.Error("[Telemetry] Hard crash when calling /install");
Logger.Error($"[Telemetry] Hard crash when calling /bundles/{endpoint}");
Logger.Error(ex);
}
}

private static string GetRandomizedId()
{
string ID = Settings.GetValue("TelemetryClientToken");
if (ID.Length != 64)
{
ID = CoreTools.RandomString(64);
Settings.SetValue("TelemetryClientToken", ID);
}

return ID;
}
}
3 changes: 2 additions & 1 deletion src/UniGetUI.PackageEngine.Enums/Enums.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ public enum DeserializedPackageStatus

public enum BundleFormatType
{
UBUNDLE,
JSON,
YAML,
XML
XML,
}

public enum OperationVeredict
Expand Down
19 changes: 14 additions & 5 deletions src/UniGetUI/AppOperationHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public static void Remove(AbstractOperation op)
* OPERATION CREATION HELPERS
*
*/
public static async Task<AbstractOperation?> AskLocationAndDownload(IPackage? package)
public static async Task<AbstractOperation?> AskLocationAndDownload(IPackage? package, TEL_InstallReferral referral)
{
if (package is null) return null;
try
Expand Down Expand Up @@ -87,6 +87,8 @@ public static void Remove(AbstractOperation op)
if (file is not null)
{
var op = new DownloadOperation(package, file.Path);
op.OperationSucceeded += (_, _) => TelemetryHandler.DownloadPackage(package, TEL_OP_RESULT.SUCCESS, referral);
op.OperationFailed += (_, _) => TelemetryHandler.DownloadPackage(package, TEL_OP_RESULT.FAILED, referral);
Add(op);
return op;
}
Expand All @@ -104,20 +106,23 @@ public static void Remove(AbstractOperation op)
/*
* PACKAGE INSTALLATION
*/
public static async Task<AbstractOperation?> Install(IPackage? package, bool? elevated = null, bool? interactive = null, bool? no_integrity = null, bool ignoreParallel = false, AbstractOperation? req = null)
public static async Task<AbstractOperation?> Install(IPackage? package, TEL_InstallReferral referral,
bool? elevated = null, bool? interactive = null, bool? no_integrity = null, bool ignoreParallel = false,
AbstractOperation? req = null)
{
if (package is null) return null;

var options = await InstallationOptions.FromPackageAsync(package, elevated, interactive, no_integrity);
var op = new InstallPackageOperation(package, options, ignoreParallel, req);
Add(op);
op.OperationSucceeded += (_, _) => TelemetryHandler.PackageInstalled(package);
op.OperationSucceeded += (_, _) => TelemetryHandler.InstallPackage(package, TEL_OP_RESULT.SUCCESS, referral);
op.OperationFailed += (_, _) => TelemetryHandler.InstallPackage(package, TEL_OP_RESULT.FAILED, referral);
return op;
}

public static void Install(IReadOnlyList<IPackage> packages, bool? elevated = null, bool? interactive = null, bool? no_integrity = null)
public static void Install(IReadOnlyList<IPackage> packages, TEL_InstallReferral referral, bool? elevated = null, bool? interactive = null, bool? no_integrity = null)
{
foreach (var package in packages) _ = Install(package, elevated, interactive, no_integrity);
foreach (var package in packages) _ = Install(package, referral, elevated, interactive, no_integrity);
}

/*
Expand All @@ -130,6 +135,8 @@ public static void Install(IReadOnlyList<IPackage> packages, bool? elevated = nu
var options = await InstallationOptions.FromPackageAsync(package, elevated, interactive, no_integrity);
var op = new UpdatePackageOperation(package, options, ignoreParallel, req);
Add(op);
op.OperationSucceeded += (_, _) => TelemetryHandler.UpdatePackage(package, TEL_OP_RESULT.SUCCESS);
op.OperationFailed += (_, _) => TelemetryHandler.UpdatePackage(package, TEL_OP_RESULT.FAILED);
return op;
}

Expand Down Expand Up @@ -165,6 +172,8 @@ public static async void ConfirmAndUninstall(IPackage? package, bool? elevated =
var options = await InstallationOptions.FromPackageAsync(package, elevated, interactive, remove_data: remove_data);
var op = new UninstallPackageOperation(package, options, ignoreParallel, req);
Add(op);
op.OperationSucceeded += (_, _) => TelemetryHandler.UninstallPackage(package, TEL_OP_RESULT.SUCCESS);
op.OperationFailed += (_, _) => TelemetryHandler.UninstallPackage(package, TEL_OP_RESULT.FAILED);
return op;
}

Expand Down
3 changes: 2 additions & 1 deletion src/UniGetUI/Controls/OperationWidgets/OperationControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
using UniGetUI.PackageEngine.Operations;
using System.Collections.ObjectModel;
using System.Diagnostics;
using UniGetUI.Interface.Telemetry;

namespace UniGetUI.Controls.OperationWidgets;

Expand Down Expand Up @@ -543,7 +544,7 @@ public List<BetterMenuItem> GetOperationOptions()
details.IconName = IconType.Info_Round;
details.Click += (_, _) =>
{
DialogHelper.ShowPackageDetails(packageOp.Package, OperationType.None);
DialogHelper.ShowPackageDetails(packageOp.Package, OperationType.None, TEL_InstallReferral.DIRECT_SEARCH);
};
optionsMenu.Add(details);

Expand Down
5 changes: 3 additions & 2 deletions src/UniGetUI/Pages/DialogPages/DialogHelper_Packages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using UniGetUI.Interface;
using UniGetUI.Interface.Dialogs;
using UniGetUI.Interface.Enums;
using UniGetUI.Interface.Telemetry;
using UniGetUI.Interface.Widgets;
using UniGetUI.PackageEngine.Enums;
using UniGetUI.PackageEngine.Interfaces;
Expand Down Expand Up @@ -90,9 +91,9 @@ public static async Task<ContentDialogResult> ShowInstallOptions_ImportedPackage
}


public static async void ShowPackageDetails(IPackage package, OperationType operation)
public static async void ShowPackageDetails(IPackage package, OperationType operation, TEL_InstallReferral referral)
{
PackageDetailsPage DetailsPage = new(package, operation);
PackageDetailsPage DetailsPage = new(package, operation, referral);

ContentDialog DetailsDialog = new()
{
Expand Down
12 changes: 9 additions & 3 deletions src/UniGetUI/Pages/DialogPages/PackageDetailsPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using UniGetUI.PackageEngine.Operations;
using UniGetUI.PackageEngine.PackageClasses;
using UniGetUI.Interface.Enums;
using UniGetUI.Interface.Telemetry;
using UniGetUI.Interface.Widgets;
using UniGetUI.PackageEngine.ManagerClasses.Manager;
using UniGetUI.Pages.DialogPages;
Expand Down Expand Up @@ -54,12 +55,15 @@ private enum LayoutMode
Unset
}

private TEL_InstallReferral InstallReferral;

private LayoutMode __layout_mode = LayoutMode.Unset;
public PackageDetailsPage(IPackage package, OperationType role)
public PackageDetailsPage(IPackage package, OperationType role, TEL_InstallReferral referral)
{
if (role == OperationType.None)
role = OperationType.Install;

InstallReferral = referral;
OperationRole = role;
Package = package;

Expand Down Expand Up @@ -136,6 +140,8 @@ public PackageDetailsPage(IPackage package, OperationType role)
SetUpActionButtonAsUninstall();
}
_ = LoadInformation();

TelemetryHandler.PackageDetails(package, referral.ToString());
}

public void SetUpActionButtonAsInstall()
Expand Down Expand Up @@ -456,7 +462,7 @@ public void DownloadInstallerButton_Click(object sender, RoutedEventArgs e)
{
if (!Package.Manager.Capabilities.CanDownloadInstaller) return;
Close?.Invoke(this, EventArgs.Empty);
_ = MainApp.Operations.AskLocationAndDownload(Package);
_ = MainApp.Operations.AskLocationAndDownload(Package, InstallReferral);
}

public void CloseButton_Click(object sender, RoutedEventArgs e)
Expand Down Expand Up @@ -590,7 +596,7 @@ public async void DoAction(

if (action is OperationType.Install)
{
_ = MainApp.Operations.Install(package, AsAdmin, Interactive, SkipHash);
_ = MainApp.Operations.Install(package, InstallReferral, AsAdmin, Interactive, SkipHash);
}
else if (action is OperationType.Uninstall)
{
Expand Down
Loading

0 comments on commit bc2282b

Please sign in to comment.