mirror of
https://github.com/chylex/TweetDuck.git
synced 2025-04-10 09:15:43 +02:00
320 lines
14 KiB
C#
320 lines
14 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Management;
|
|
using System.Text.RegularExpressions;
|
|
using System.Windows.Forms;
|
|
using Microsoft.Win32;
|
|
using TweetDuck.Browser;
|
|
using TweetDuck.Configuration;
|
|
using TweetLib.Core;
|
|
using TweetLib.Core.Features.Notifications;
|
|
using TweetLib.Core.Features.Plugins;
|
|
using TweetLib.Core.Features.Plugins.Enums;
|
|
using TweetLib.Core.Utils;
|
|
|
|
namespace TweetDuck.Management.Analytics {
|
|
static class AnalyticsReportGenerator {
|
|
public static AnalyticsReport Create(AnalyticsFile file, ExternalInfo info, PluginManager plugins) {
|
|
Dictionary<string, string> editLayoutDesign = EditLayoutDesignPluginData;
|
|
|
|
return new AnalyticsReport {
|
|
{ "App Version" , Program.VersionTag },
|
|
{ "App Type" , Program.IsPortable ? "portable" : "installed" },
|
|
{ "App Dev Tools" , Bool(UserConfig.DevToolsInContextMenu) },
|
|
0,
|
|
{ "System Name" , SystemName },
|
|
{ "System Edition" , SystemEdition },
|
|
{ "System Environment" , Environment.Is64BitOperatingSystem ? "64-bit" : "32-bit" },
|
|
{ "System Build" , SystemBuild },
|
|
{ "System Locale" , Lib.Culture.Name.ToLower() },
|
|
0,
|
|
{ "RAM" , Exact(RamSize) },
|
|
{ "GPU" , GpuVendor },
|
|
0,
|
|
{ "Screen Count" , Exact(Screen.AllScreens.Length) },
|
|
{ "Screen Resolution" , info.Resolution ?? "(unknown)" },
|
|
{ "Screen DPI" , info.DPI != null ? Exact(info.DPI.Value) : "(unknown)" },
|
|
0,
|
|
{ "Hardware Acceleration" , Bool(SysConfig.HardwareAcceleration) },
|
|
{ "Clear Cache Automatically" , Bool(SysConfig.ClearCacheAutomatically) },
|
|
{ "Clear Cache Threshold" , Exact(SysConfig.ClearCacheThreshold) },
|
|
0,
|
|
{ "Expand Links" , Bool(UserConfig.ExpandLinksOnHover) },
|
|
{ "Search In First Column" , Bool(UserConfig.OpenSearchInFirstColumn) },
|
|
{ "Keep Like Follow Dialogs Open" , Bool(UserConfig.KeepLikeFollowDialogsOpen) },
|
|
{ "Best Image Quality" , Bool(UserConfig.BestImageQuality) },
|
|
{ "Animated Images" , Bool(UserConfig.EnableAnimatedImages) },
|
|
0,
|
|
{ "Smooth Scrolling" , Bool(UserConfig.EnableSmoothScrolling) },
|
|
{ "Custom Browser" , CustomBrowser },
|
|
{ "Zoom" , Exact(UserConfig.ZoomLevel) },
|
|
0,
|
|
{ "Spell Check" , Bool(UserConfig.EnableSpellCheck) },
|
|
{ "Spell Check Language" , UserConfig.SpellCheckLanguage.ToLower() },
|
|
{ "Translation Target Language" , UserConfig.TranslationTarget },
|
|
0,
|
|
{ "Updates" , Bool(UserConfig.EnableUpdateCheck) },
|
|
{ "Update Dismissed" , Bool(!string.IsNullOrEmpty(UserConfig.DismissedUpdate)) },
|
|
0,
|
|
{ "Tray" , TrayMode },
|
|
{ "Tray Highlight" , Bool(UserConfig.EnableTrayHighlight) },
|
|
0,
|
|
{ "Notification Position" , NotificationPosition },
|
|
{ "Notification Size" , NotificationSize },
|
|
{ "Notification Timer" , NotificationTimer },
|
|
{ "Notification Timer Speed" , RoundUp(UserConfig.NotificationDurationValue, 5) },
|
|
{ "Notification Scroll Speed" , Exact(UserConfig.NotificationScrollSpeed) },
|
|
{ "Notification Column Title" , Bool(UserConfig.DisplayNotificationColumn) },
|
|
{ "Notification Media Previews" , Bool(UserConfig.NotificationMediaPreviews) },
|
|
{ "Notification Link Skip" , Bool(UserConfig.NotificationSkipOnLinkClick) },
|
|
{ "Notification Non-Intrusive" , Bool(UserConfig.NotificationNonIntrusiveMode) },
|
|
{ "Notification Idle Pause" , Exact(UserConfig.NotificationIdlePauseSeconds) },
|
|
{ "Custom Sound Notification" , string.IsNullOrEmpty(UserConfig.NotificationSoundPath) ? "off" : Path.GetExtension(UserConfig.NotificationSoundPath) },
|
|
{ "Custom Sound Notification Volume" , RoundUp(UserConfig.NotificationSoundVolume, 5) },
|
|
0,
|
|
{ "Program Arguments" , List(ProgramArguments) },
|
|
{ "Custom CEF Arguments" , RoundUp((UserConfig.CustomCefArgs ?? string.Empty).Length, 10) },
|
|
{ "Custom Browser CSS" , RoundUp((UserConfig.CustomBrowserCSS ?? string.Empty).Length, 50) },
|
|
{ "Custom Notification CSS" , RoundUp((UserConfig.CustomNotificationCSS ?? string.Empty).Length, 50) },
|
|
0,
|
|
{ "Plugins All" , List(plugins.Plugins.Select(Plugin)) },
|
|
{ "Plugins Enabled" , List(plugins.Plugins.Where(plugins.Config.IsEnabled).Select(Plugin)) },
|
|
0,
|
|
{ "Theme" , Dict(editLayoutDesign, "_theme", "light/def") },
|
|
{ "Column Width" , Dict(editLayoutDesign, "columnWidth", "310px/def") },
|
|
{ "Font Size" , Dict(editLayoutDesign, "fontSize", "12px/def") },
|
|
{ "Large Quote Font" , Dict(editLayoutDesign, "increaseQuoteTextSize", "false/def") },
|
|
{ "Small Compose Font" , Dict(editLayoutDesign, "smallComposeTextSize", "false/def") },
|
|
{ "Avatar Radius" , Dict(editLayoutDesign, "avatarRadius", "2/def") },
|
|
{ "Hide Tweet Actions" , Dict(editLayoutDesign, "hideTweetActions", "true/def") },
|
|
{ "Move Tweet Actions" , Dict(editLayoutDesign, "moveTweetActionsToRight", "true/def") },
|
|
{ "Theme Color Tweaks" , Dict(editLayoutDesign, "themeColorTweaks", "true/def") },
|
|
{ "Revert Icons" , Dict(editLayoutDesign, "revertIcons", "true/def") },
|
|
{ "Optimize Animations" , Dict(editLayoutDesign, "optimizeAnimations", "true/def") },
|
|
{ "Reply Account Mode" , ReplyAccountConfigFromPlugin },
|
|
{ "Template Count" , Exact(TemplateCountFromPlugin) },
|
|
0,
|
|
{ "Opened Options" , LogRound(file.OpenOptions, 4) },
|
|
{ "Opened Plugins" , LogRound(file.OpenPlugins, 4) },
|
|
{ "Opened About" , LogRound(file.OpenAbout, 4) },
|
|
{ "Opened Guide" , LogRound(file.OpenGuide, 4) },
|
|
{ "Desktop Notifications" , LogRound(file.DesktopNotifications, 5) },
|
|
{ "Sound Notifications" , LogRound(file.SoundNotifications, 5) },
|
|
{ "Notification Mutes" , LogRound(file.NotificationMutes, 2) },
|
|
{ "Browser Context Menus" , LogRound(file.BrowserContextMenus, 2) },
|
|
{ "Browser Extra Mouse Buttons" , LogRound(file.BrowserExtraMouseButtons, 2) },
|
|
{ "Notification Context Menus" , LogRound(file.NotificationContextMenus, 2) },
|
|
{ "Notification Extra Mouse Buttons" , LogRound(file.NotificationExtraMouseButtons, 2) },
|
|
{ "Notification Keyboard Shortcuts" , LogRound(file.NotificationKeyboardShortcuts, 2) },
|
|
{ "Browser Reloads" , LogRound(file.BrowserReloads, 2) },
|
|
{ "Copied Usernames" , LogRound(file.CopiedUsernames, 2) },
|
|
{ "Viewed Images" , LogRound(file.ViewedImages, 2) },
|
|
{ "Downloaded Images" , LogRound(file.DownloadedImages, 2) },
|
|
{ "Downloaded Videos" , LogRound(file.DownloadedVideos, 2) },
|
|
{ "Used ROT13" , LogRound(file.UsedROT13, 2) },
|
|
{ "Tweet Screenshots" , LogRound(file.TweetScreenshots, 2) },
|
|
{ "Tweet Details" , LogRound(file.TweetDetails, 2) },
|
|
{ "Video Plays" , LogRound(file.VideoPlays, 4) }
|
|
}.FinalizeReport();
|
|
}
|
|
|
|
private static UserConfig UserConfig => Program.Config.User;
|
|
private static SystemConfig SysConfig => Program.Config.System;
|
|
|
|
private static string Bool(bool value) => value ? "on" : "off";
|
|
private static string Exact(int value) => value.ToString();
|
|
private static string RoundUp(int value, int multiple) => (multiple * (int) Math.Ceiling((double) value / multiple)).ToString();
|
|
private static string LogRound(int value, int logBase) => (value <= 0 ? 0 : (int) Math.Pow(logBase, Math.Floor(Math.Log(value, logBase)))).ToString();
|
|
private static string Plugin(Plugin plugin) => plugin.Group.GetIdentifierPrefixShort() + plugin.Identifier.Substring(plugin.Group.GetIdentifierPrefix().Length);
|
|
private static string Dict(Dictionary<string, string> dict, string key, string def = "(unknown)") => dict.TryGetValue(key, out string value) ? value : def;
|
|
private static string List(IEnumerable<string> list) => string.Join("|", list.DefaultIfEmpty("(none)"));
|
|
|
|
private static string SystemName { get; }
|
|
private static string SystemEdition { get; }
|
|
private static string SystemBuild { get; }
|
|
private static int RamSize { get; }
|
|
private static string GpuVendor { get; }
|
|
private static string[] ProgramArguments { get; }
|
|
|
|
static AnalyticsReportGenerator() {
|
|
string osName, osEdition, osBuild;
|
|
|
|
try {
|
|
using RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", false);
|
|
|
|
// ReSharper disable once PossibleNullReferenceException
|
|
osName = key.GetValue("ProductName") as string;
|
|
osBuild = key.GetValue("CurrentBuild") as string;
|
|
osEdition = null;
|
|
|
|
if (osName != null) {
|
|
Match match = Regex.Match(osName, @"^(.*?\d+(?:\.\d+)?) (.*)$");
|
|
|
|
if (match.Success) {
|
|
osName = match.Groups[1].Value;
|
|
osEdition = match.Groups[2].Value;
|
|
}
|
|
}
|
|
} catch {
|
|
osName = osEdition = osBuild = null;
|
|
}
|
|
|
|
SystemName = osName ?? "Windows (unknown)";
|
|
SystemEdition = osEdition ?? "(unknown)";
|
|
SystemBuild = osBuild ?? "(unknown)";
|
|
|
|
try {
|
|
using ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT Capacity FROM Win32_PhysicalMemory");
|
|
|
|
foreach (ManagementBaseObject obj in searcher.Get()) {
|
|
RamSize += (int) ((ulong) obj["Capacity"] / (1024L * 1024L));
|
|
}
|
|
} catch {
|
|
RamSize = 0;
|
|
}
|
|
|
|
string gpu = null;
|
|
|
|
try {
|
|
using ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT Caption FROM Win32_VideoController");
|
|
|
|
foreach (ManagementBaseObject obj in searcher.Get()) {
|
|
string vendor = obj["Caption"] as string;
|
|
|
|
if (!string.IsNullOrEmpty(vendor)) {
|
|
gpu = vendor;
|
|
}
|
|
}
|
|
} catch {
|
|
// rip
|
|
}
|
|
|
|
GpuVendor = gpu ?? "(unknown)";
|
|
|
|
Dictionary<string, string> args = new Dictionary<string, string>();
|
|
Arguments.GetCurrentClean().ToDictionary(args);
|
|
ProgramArguments = args.Keys.Select(key => key.TrimStart('-')).ToArray();
|
|
}
|
|
|
|
private static string CustomBrowser {
|
|
get { return Path.GetFileName(UserConfig.BrowserPath) ?? string.Empty; }
|
|
}
|
|
|
|
private static string TrayMode {
|
|
get => UserConfig.TrayBehavior switch {
|
|
TrayIcon.Behavior.DisplayOnly => "icon",
|
|
TrayIcon.Behavior.MinimizeToTray => "minimize",
|
|
TrayIcon.Behavior.CloseToTray => "close",
|
|
TrayIcon.Behavior.Combined => "combined",
|
|
_ => "off"
|
|
};
|
|
}
|
|
|
|
private static string NotificationPosition {
|
|
get => UserConfig.NotificationPosition switch {
|
|
DesktopNotification.Position.TopLeft => "top left",
|
|
DesktopNotification.Position.TopRight => "top right",
|
|
DesktopNotification.Position.BottomLeft => "bottom left",
|
|
DesktopNotification.Position.BottomRight => "bottom right",
|
|
_ => "custom"
|
|
};
|
|
}
|
|
|
|
private static string NotificationSize {
|
|
get => UserConfig.NotificationSize switch {
|
|
DesktopNotification.Size.Auto => "auto",
|
|
_ => RoundUp(UserConfig.CustomNotificationSize.Width, 20) + "x" + RoundUp(UserConfig.CustomNotificationSize.Height, 20)
|
|
};
|
|
}
|
|
|
|
private static string NotificationTimer {
|
|
get {
|
|
if (!UserConfig.DisplayNotificationTimer) {
|
|
return "off";
|
|
}
|
|
else {
|
|
return UserConfig.NotificationTimerCountDown ? "count down" : "count up";
|
|
}
|
|
}
|
|
}
|
|
|
|
private static Dictionary<string, string> EditLayoutDesignPluginData {
|
|
get {
|
|
Dictionary<string, string> dict = new Dictionary<string, string>();
|
|
|
|
try {
|
|
string data = File.ReadAllText(Path.Combine(Program.PluginDataPath, "official", "edit-design", "config.json"));
|
|
|
|
foreach (Match match in Regex.Matches(data, "\"(\\w+?)\":(.*?)[,}]")) {
|
|
dict[match.Groups[1].Value] = match.Groups[2].Value.Trim('"');
|
|
}
|
|
} catch {
|
|
// rip
|
|
}
|
|
|
|
return dict;
|
|
}
|
|
}
|
|
|
|
private static int TemplateCountFromPlugin {
|
|
get {
|
|
try {
|
|
string data = File.ReadAllText(Path.Combine(Program.PluginDataPath, "official", "templates", "config.json"));
|
|
return Math.Min(StringUtils.CountOccurrences(data, "{\"name\":"), StringUtils.CountOccurrences(data, ",\"contents\":"));
|
|
} catch {
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static string ReplyAccountConfigFromPlugin {
|
|
get {
|
|
try {
|
|
string data = File.ReadAllText(Path.Combine(Program.PluginDataPath, "official", "reply-account", "configuration.js")).Replace(" ", "");
|
|
|
|
Match matchType = Regex.Match(data, "defaultAccount:\"([#@])(.*?)\"(?:,|$)");
|
|
Match matchAdvanced = Regex.Match(data, "useAdvancedSelector:(.*?)(?:,|$)", RegexOptions.Multiline);
|
|
|
|
if (!matchType.Success) {
|
|
return data.Contains("defaultAccount:\"\"") ? "(legacy)" : "(unknown)";
|
|
}
|
|
|
|
string accType = matchType.Groups[1].Value == "#" ? matchType.Groups[2].Value : "account";
|
|
return matchAdvanced.Success && !matchAdvanced.Value.Contains("false") ? "advanced/" + accType : accType;
|
|
} catch {
|
|
return "(unknown)";
|
|
}
|
|
}
|
|
}
|
|
|
|
public class ExternalInfo {
|
|
public static ExternalInfo From(Form form) {
|
|
if (form == null) {
|
|
return new ExternalInfo();
|
|
}
|
|
else {
|
|
Screen screen = Screen.FromControl(form); // works on multi-monitor setups even in tray
|
|
int dpi;
|
|
|
|
using (Graphics graphics = form.CreateGraphics()) {
|
|
dpi = (int) graphics.DpiY;
|
|
}
|
|
|
|
return new ExternalInfo {
|
|
Resolution = screen.Bounds.Width + "x" + screen.Bounds.Height,
|
|
DPI = dpi
|
|
};
|
|
}
|
|
}
|
|
|
|
public string Resolution { get; private set; }
|
|
public int? DPI { get; private set; }
|
|
|
|
private ExternalInfo() {}
|
|
}
|
|
}
|
|
}
|