Skip to content

Commit

Permalink
Added 'Export account list'
Browse files Browse the repository at this point in the history
- Added 'Export account list' button, to save a .csv with all the saved accounts, as well as other info such as VAC status, Overwatch SR and more.
  • Loading branch information
TCNOco committed Jul 1, 2021
1 parent a866793 commit c33a6ed
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 27 deletions.
43 changes: 32 additions & 11 deletions TcNo-Acc-Switcher-Globals/Globals.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class Globals
#pragma warning disable CA2211 // Non-constant fields should not be visible - This is necessary due to it being a launch parameter.
public static bool VerboseMode;
#pragma warning restore CA2211 // Non-constant fields should not be visible
public static readonly string Version = "2021-06-28_02";
public static readonly string Version = "2021-07-01_00";
public static readonly string[] PlatformList = {"Steam", "Origin", "Ubisoft", "BattleNet", "Epic", "Riot"};

#region LOGGER
Expand Down Expand Up @@ -111,18 +111,32 @@ public static void CurrentDomain_UnhandledException(object sender, UnhandledExce
{
// Set working directory to documents folder
Directory.SetCurrentDirectory(UserDataFolder);

// Log Unhandled Exception
var exceptionStr = e.ExceptionObject.ToString();
Directory.CreateDirectory("CrashLogs");
var filePath = $"CrashLogs\\AccSwitcher-Crashlog-{DateTime.Now:dd-MM-yy_hh-mm-ss.fff}.txt";
using (var sw = File.AppendText(filePath))
try
{
sw.WriteLine(
$"{DateTime.Now.ToString(CultureInfo.InvariantCulture)}({Version})\t{Strings.ErrUnhandledCrash}: {exceptionStr}{Environment.NewLine}{Environment.NewLine}");
}
var exceptionStr = e.ExceptionObject.ToString();
Directory.CreateDirectory("CrashLogs");
var filePath = $"CrashLogs\\AccSwitcher-Crashlog-{DateTime.Now:dd-MM-yy_hh-mm-ss.fff}.txt";
if (File.Exists(filePath))
{
Random r = new();
filePath = $"CrashLogs\\AccSwitcher-Crashlog-{DateTime.Now:dd-MM-yy_hh-mm-ss.fff}{r.Next(0, 100)}.txt";
}

using (var sw = File.AppendText(filePath))
{
sw.WriteLine(
$"{DateTime.Now.ToString(CultureInfo.InvariantCulture)}({Version})\t{Strings.ErrUnhandledCrash}: {exceptionStr}{Environment.NewLine}{Environment.NewLine}");
}

WriteToLog(Strings.ErrUnhandledException + Path.GetFullPath(filePath));
WriteToLog(Strings.ErrSubmitCrashlog);
WriteToLog(Strings.ErrUnhandledException + Path.GetFullPath(filePath));
WriteToLog(Strings.ErrSubmitCrashlog);
}
catch (Exception)
{
// This is just to prevent a complete crash. Sometimes there are multiple errors super close together, that cause it to break and we end up here.
}
}

#endregion
Expand Down Expand Up @@ -237,7 +251,14 @@ public static string GetDataFolderMd5(string path)
var pathBytes = Encoding.UTF8.GetBytes(file[(path.Length + 1)..].ToLower());
md5.TransformBlock(pathBytes, 0, pathBytes.Length, pathBytes, 0);

lastBytes = File.ReadAllBytes(file);
try
{
lastBytes = File.ReadAllBytes(file);
}
catch (IOException)
{
// File is in use
}
}

if (lastBytes != null)
Expand Down
29 changes: 15 additions & 14 deletions TcNo-Acc-Switcher-Server/Data/AppSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ public static AppSettings Instance

[JsonIgnore] public string PlatformContextMenu = @"[
{""Hide platform"": ""hidePlatform()""},
{""Create Desktop Shortcut"": ""createPlatformShortcut()""}
{""Create Desktop Shortcut"": ""createPlatformShortcut()""},
{""Export account list"": ""exportAllAccounts()""}
]";
[JSInvokable]
public static async System.Threading.Tasks.Task HidePlatform(string platform)
Expand Down Expand Up @@ -438,8 +439,9 @@ public async System.Threading.Tasks.Task SwapStylesheet(string swapTo)
try
{
if (LoadStylesheetFromFile()) await AppData.ReloadPage();
else throw new Exception(); // Jump to the error display
}
else GeneralInvocableFuncs.ShowToast("error", "Failed to load stylesheet! See documents folder for details.",
"Stylesheet error", "toastarea");
}
catch (Exception)
{
GeneralInvocableFuncs.ShowToast("error", "Failed to load stylesheet! See documents folder for details.",
Expand Down Expand Up @@ -701,7 +703,7 @@ public void WindowsAccent_Toggle()
[SupportedOSPlatform("windows")]
private void SetAccentColor() => SetAccentColor(false);
[SupportedOSPlatform("windows")]
private void SetAccentColor(bool userInvoked)
private static void SetAccentColor(bool userInvoked)
{
var accent = GetAccentColorHexString();
_instance._stylesheet["selectionBackground"] = accent;
Expand All @@ -728,23 +730,22 @@ private void SetAccentColor(bool userInvoked)
[SupportedOSPlatform("windows")]
public static string GetAccentColorHexString()
{
byte r, g, b, a;
(r, g, b, a) = GetAccentColor();
byte r, g, b;
(r, g, b) = GetAccentColor();
byte[] rgb = {r, g, b};
return '#' + BitConverter.ToString(rgb).Replace("-", string.Empty);
}

[SupportedOSPlatform("windows")]
public static string GetAccentColorIntString()
{
byte r, g, b, a;
(r, g, b, a) = GetAccentColor();
byte[] rgb = { r, g, b };
byte r, g, b;
(r, g, b) = GetAccentColor();
return Convert.ToInt32(r) + ", " + Convert.ToInt32(g) + ", " + Convert.ToInt32(b);
}

[SupportedOSPlatform("windows")]
public static (byte r, byte g, byte b, byte a) GetAccentColor()
public static (byte r, byte g, byte b) GetAccentColor()
{
using var dwmKey = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\DWM", RegistryKeyPermissionCheck.ReadSubTree);
const string keyExMsg = "The \"HKCU\\Software\\Microsoft\\Windows\\DWM\" registry key does not exist.";
Expand All @@ -762,15 +763,15 @@ public static (byte r, byte g, byte b, byte a) GetAccentColor()
}
}

private static (byte r, byte g, byte b, byte a) ParseDWordColor(int color)
private static (byte r, byte g, byte b) ParseDWordColor(int color)
{
byte
a = (byte)((color >> 24) & 0xFF),
byte
//a = (byte)((color >> 24) & 0xFF),
b = (byte)((color >> 16) & 0xFF),
g = (byte)((color >> 8) & 0xFF),
r = (byte)((color >> 0) & 0xFF);

return (r, g, b, a);
return (r, g, b);
}
#endregion

Expand Down
88 changes: 88 additions & 0 deletions TcNo-Acc-Switcher-Server/Pages/General/GeneralInvocableFuncs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.JSInterop;
using Newtonsoft.Json.Linq;
Expand Down Expand Up @@ -318,5 +320,91 @@ public static void GiCreatePlatformShortcut(string platform)
s.Shortcut_Platform(Shortcut.Desktop, platform, platform.ToLowerInvariant());
s.ToggleShortcut(true);
}

[JSInvokable]
public static async Task<string> GiExportAccountList(string platform)
{
Globals.DebugWriteLine(@$"[Func:Pages\General\GeneralInvocableFuncs.GiExportAccountList] platform={platform}");
if (!Directory.Exists(Path.Join("LoginCache", platform)))
{
ShowToast("error", "Open the platform from the list and add a few accounts first",
"No saved accounts", "toastarea");
return "";
}

var s = System.Globalization.CultureInfo.CurrentCulture.TextInfo.ListSeparator; // Different regions use different separators in csv files.

List<string> allAccountsTable = new();
if (platform == "Steam")
{
// Add headings and separator for programs like Excel
allAccountsTable.Add("SEP=,");
allAccountsTable.Add("Account name:,Community name:,SteamID:,VAC status:,Last login:,Saved profile image:");

var userAccounts = SteamSwitcherFuncs.GetSteamUsers(Steam.LoginUsersVdf());
var vacStatusList = new List<SteamSwitcherFuncs.VacStatus>();
var loadedVacCache = SteamSwitcherFuncs.LoadVacInfo(ref vacStatusList);

foreach (var ua in userAccounts)
{
var VacInfo = "";
// Get VAC/Limited info
if (loadedVacCache)
foreach (var vsi in vacStatusList.Where(vsi => vsi.SteamId == ua.SteamId))
{
if (vsi.Vac && vsi.Ltd) VacInfo += "VAC + Limited";
else VacInfo += (vsi.Vac ? "VAC" : "") + (vsi.Ltd ? "Limited" : "");
break;
}
else
{
VacInfo += "N/A";
}

var imagePath = Path.GetFullPath($"{Steam.SteamImagePath + ua.SteamId}.jpg");
allAccountsTable.Add(ua.AccName + s +
ua.Name + s +
ua.SteamId + s +
VacInfo + s +
SteamSwitcherFuncs.UnixTimeStampToDateTime(ua.LastLogin) + s +
(File.Exists(imagePath) ? imagePath : "Missing from disk"));
}
}
else if (platform == "BattleNet")
{
// Add headings and separator for programs like Excel
allAccountsTable.Add("SEP=,");
allAccountsTable.Add("Email:,BattleTag:,Overwatch Support SR:,Overwatch DPS SR:,Overwatch Tank SR:,Saved profile image:");

await BattleNetSwitcherFuncs.LoadProfiles();

foreach (var ba in BattleNet.Accounts)
{
var imagePath = Path.GetFullPath($"wwwroot\\img\\profiles\\battlenet\\{ba.Email}.png");
allAccountsTable.Add(ba.Email + s +
ba.BTag + s +
(ba.OwSupportSr != 0 ? ba.OwSupportSr : "") + s +
(ba.OwDpsSr != 0 ? ba.OwDpsSr : "") + s +
(ba.OwTankSr != 0 ? ba.OwTankSr : "") + s +
(File.Exists(imagePath) ? imagePath : "Missing from disk"));
}
}
else
{
// Platform does not have specific details other than usernames saved.
allAccountsTable.Add("Account name:");
foreach (var accDirectory in Directory.GetDirectories(Path.Join("LoginCache", platform)))
{
allAccountsTable.Add(Path.GetFileName(accDirectory));
}
}

var outputFolder = Path.Join("wwwroot", "Exported");
Directory.CreateDirectory(outputFolder);

var outputFile = Path.Join(outputFolder, platform + ".csv");
await File.WriteAllLinesAsync(outputFile, allAccountsTable).ConfigureAwait(false);
return Path.Join("Exported", platform + ".csv");
}
}
}
31 changes: 31 additions & 0 deletions TcNo-Acc-Switcher-Server/wwwroot/js/WebFuncs.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,37 @@ function createPlatformShortcut() {
DotNet.invokeMethodAsync("TcNo-Acc-Switcher-Server", "GiCreatePlatformShortcut", selectedElem);
}

var exportingAccounts = false;

async function exportAllAccounts() {
if (exportingAccounts) {
window.notification.new({
type: "error",
title: "Error",
message: "Already processing accounts...",
renderTo: "toastarea",
duration: 5000
});
return;
}
exportingAccounts = true;
var promise = DotNet.invokeMethodAsync("TcNo-Acc-Switcher-Server", "GiExportAccountList", selectedElem).then((r) => {
let filename = r.split('/')
saveFile(filename[filename.length - 1], r);
exportingAccounts = false;
});
_ = await promise;
}

function saveFile(fileName, urlFile) {
let a = document.createElement("a");
a.style = "display: none";
document.body.appendChild(a);
a.href = urlFile;
a.download = fileName;
a.click();
a.remove();
}


// Add currently logged in Origin account
Expand Down
6 changes: 4 additions & 2 deletions TcNo-Acc-Switcher-Server/wwwroot/js/interop.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,14 @@ $(function () {
});

function jQueryAppend(jQuerySelector, strToInsert) {
$(jQuerySelector).append(strToInsert);
$(jQuerySelector).append(strToInsert);
};

function jQueryProcessAccListSize() {
let maxHeight = 0;
$(".acc_list_item label").each((_, e) => { maxHeight = Math.max(maxHeight, e.offsetHeight); });
document.getElementById("acc_list").setAttribute("style", `grid-template-rows: repeat(auto-fill, ${maxHeight}px)`);
if (document.getElementById("acc_list"))
document.getElementById("acc_list").setAttribute("style", `grid-template-rows: repeat(auto-fill, ${maxHeight}px)`);
};

// Removes arguments like "?toast_type, &toast_title, &toast_message" from the URL.
Expand Down Expand Up @@ -77,6 +78,7 @@ function updateStatus(status) {
};

function initAccListSortable() {
if (document.getElementsByClassName(".acc_list").length === 0) return;
// Create sortable list
sortable(".acc_list", {
forcePlaceholderSize: true,
Expand Down

0 comments on commit c33a6ed

Please sign in to comment.