Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
d6658d8cdc | ||
|
5f3cee0a99 | ||
|
10733c1d80 | ||
|
102c918d63 | ||
|
f042c4adb3 | ||
|
aa104a9660 | ||
|
1d4667d6e0 | ||
|
104738edee | ||
|
2b13cd746e | ||
|
53cd921941 | ||
|
675455a990 | ||
|
1d6231789c | ||
|
41b09152d3 |
|
@ -1,9 +1,9 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio Version 16
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 16.0.33927.289
|
VisualStudioVersion = 17.8.34219.65
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Partypacker", "Partypacker\Partypacker.csproj", "{FE06B383-0C7A-4A35-B208-66133110BB32}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Partypacker", "Partypacker\Partypacker.csproj", "{BCB1E673-FE06-4360-895D-07FE682C720D}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
@ -11,15 +11,15 @@ Global
|
||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{FE06B383-0C7A-4A35-B208-66133110BB32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{BCB1E673-FE06-4360-895D-07FE682C720D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{FE06B383-0C7A-4A35-B208-66133110BB32}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{BCB1E673-FE06-4360-895D-07FE682C720D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{FE06B383-0C7A-4A35-B208-66133110BB32}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{BCB1E673-FE06-4360-895D-07FE682C720D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{FE06B383-0C7A-4A35-B208-66133110BB32}.Release|Any CPU.Build.0 = Release|Any CPU
|
{BCB1E673-FE06-4360-895D-07FE682C720D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {16591BB0-2EFE-43B1-917D-7CD574AB32C8}
|
SolutionGuid = {F12064C4-E05B-464A-BF11-E0E20C7D2B3F}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
15
Partypacker/App.xaml
Normal file
15
Partypacker/App.xaml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<Application x:Class="Partypacker.App"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:local="clr-namespace:Partypacker"
|
||||||
|
xmlns:adonisUi="clr-namespace:AdonisUI;assembly=AdonisUI"
|
||||||
|
StartupUri="MainWindow.xaml">
|
||||||
|
<Application.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<ResourceDictionary.MergedDictionaries>
|
||||||
|
<ResourceDictionary Source="pack://application:,,,/AdonisUI;component/ColorSchemes/Dark.xaml"/>
|
||||||
|
<ResourceDictionary Source="pack://application:,,,/AdonisUI.ClassicTheme;component/Resources.xaml"/>
|
||||||
|
</ResourceDictionary.MergedDictionaries>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</Application.Resources>
|
||||||
|
</Application>
|
14
Partypacker/App.xaml.cs
Normal file
14
Partypacker/App.xaml.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
using System.Configuration;
|
||||||
|
using System.Data;
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
namespace Partypacker
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for App.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class App : Application
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
10
Partypacker/AssemblyInfo.cs
Normal file
10
Partypacker/AssemblyInfo.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
[assembly: ThemeInfo(
|
||||||
|
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||||
|
//(used if a resource is not found in the page,
|
||||||
|
// or application resource dictionaries)
|
||||||
|
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||||
|
//(used if a resource is not found in the page,
|
||||||
|
// app, or any theme specific resource dictionaries)
|
||||||
|
)]
|
21
Partypacker/Classes.cs
Normal file
21
Partypacker/Classes.cs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
namespace Partypacker
|
||||||
|
{
|
||||||
|
public enum UserRole
|
||||||
|
{
|
||||||
|
User = 100,
|
||||||
|
VerifiedUser = 200,
|
||||||
|
TrackVerifier = 250,
|
||||||
|
Moderator = 300,
|
||||||
|
Administrator = 400
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UserDetailObject
|
||||||
|
{
|
||||||
|
public string ID;
|
||||||
|
public string Username;
|
||||||
|
public string GlobalName;
|
||||||
|
public string Avatar;
|
||||||
|
public bool IsAdmin;
|
||||||
|
public UserRole Role;
|
||||||
|
}
|
||||||
|
}
|
|
@ -47,4 +47,4 @@ namespace Partypacker.Core
|
||||||
|
|
||||||
public RegistryValueKind RegistryValueKind { get; set; }
|
public RegistryValueKind RegistryValueKind { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -17,4 +17,4 @@ namespace Partypacker.Core
|
||||||
.ForEach(x => registryKey
|
.ForEach(x => registryKey
|
||||||
.SetValue(x.Name, x.Value, x.RegistryValueKind));
|
.SetValue(x.Name, x.Value, x.RegistryValueKind));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,19 +1,28 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
namespace Partypacker.Core
|
namespace Partypacker.Core
|
||||||
{
|
{
|
||||||
internal class Server
|
internal class PartypackServer
|
||||||
{
|
{
|
||||||
static string BaseURL =
|
public static string BaseURL =
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
"http://localhost:6677";
|
MainWindow.settings.GetValue("Launcher", "apiurl") ?? "https://partypack.mcthe.dev";
|
||||||
#else
|
#else
|
||||||
"https://api.partypack.mcthe.dev";
|
MainWindow.settings.GetValue("Launcher", "apiurl") ?? "https://partypack.mcthe.dev";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public static string DashboardURL =
|
||||||
|
#if DEBUG
|
||||||
|
MainWindow.settings.GetValue("Launcher", "apiurl") ?? "https://partypack.mcthe.dev";
|
||||||
|
#else
|
||||||
|
MainWindow.settings.GetValue("Launcher", "dashurl") ?? "https://partypack.mcthe.dev";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public static KeyValuePair<bool, string> GET(string URL = "/")
|
public static KeyValuePair<bool, string> GET(string URL = "/")
|
||||||
|
@ -38,7 +47,7 @@ namespace Partypacker.Core
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Console.WriteLine(ex.Message);
|
MessageBox.Show(ex.Message);
|
||||||
return new KeyValuePair<bool, string>(false, string.Empty);
|
return new KeyValuePair<bool, string>(false, string.Empty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,5 +82,5 @@ namespace Partypacker.Core
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -87,4 +87,4 @@ namespace Partypacker
|
||||||
INTERNET_OPTION_SETTINGS_CHANGED = 39
|
INTERNET_OPTION_SETTINGS_CHANGED = 39
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
275
Partypacker/INIFile.cs
Normal file
275
Partypacker/INIFile.cs
Normal file
|
@ -0,0 +1,275 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace Partypacker
|
||||||
|
{
|
||||||
|
public class INIFile
|
||||||
|
{
|
||||||
|
private string _File;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call the constructor creates a new object of the INIFile class to work with INI files.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="file">Name of INI file, which you want to access.</param>
|
||||||
|
/// <param name="createFile">Specifies whether the INI file should be created if it does not exist.</param>
|
||||||
|
public INIFile(string file, bool createFile = false)
|
||||||
|
{
|
||||||
|
if (createFile == true && File.Exists(file) == false)
|
||||||
|
{
|
||||||
|
FileInfo fileInfo = new FileInfo(file);
|
||||||
|
FileStream fileStream = fileInfo.Create();
|
||||||
|
fileStream.Close();
|
||||||
|
}
|
||||||
|
_File = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Public Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes all comments and empty lines from a complete section and returns the sections.
|
||||||
|
/// This method is not case-sensitive.
|
||||||
|
/// The return value does not contain any spaces at the beginning or at the end of a line.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">Name of the requested section.</param>
|
||||||
|
/// <param name="includeComments">Specifies whether comments should also be returned.</param>
|
||||||
|
/// <returns>Returns the whole section.</returns>
|
||||||
|
public List<string> GetSection(string section, bool includeComments = false)
|
||||||
|
{
|
||||||
|
section = CheckSection(section);
|
||||||
|
|
||||||
|
List<string> completeSection = new List<string>();
|
||||||
|
bool sectionStart = false;
|
||||||
|
|
||||||
|
string[] fileArray = File.ReadAllLines(_File);
|
||||||
|
|
||||||
|
foreach (var item in fileArray)
|
||||||
|
{
|
||||||
|
if (item.Length <= 0) continue;
|
||||||
|
|
||||||
|
// Beginning of section.
|
||||||
|
if (item.Replace(" ", "").ToLower() == section)
|
||||||
|
{
|
||||||
|
sectionStart = true;
|
||||||
|
}
|
||||||
|
// Beginning of next section.
|
||||||
|
if (sectionStart == true && item.Replace(" ", "").ToLower() != section && item.Replace(" ", "").Substring(0, 1) == "[" && item.Replace(" ", "").Substring(item.Length - 1, 1) == "]")
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (sectionStart == true)
|
||||||
|
{
|
||||||
|
// Add the entry to the List<string> completeSection, if it is not a comment or an empty entry.
|
||||||
|
if (includeComments == false
|
||||||
|
&& item.Replace(" ", "").Substring(0, 1) != ";" && !string.IsNullOrWhiteSpace(item))
|
||||||
|
{
|
||||||
|
completeSection.Add(ReplaceSpacesAtStartAndEnd(item));
|
||||||
|
}
|
||||||
|
if (includeComments == true && !string.IsNullOrWhiteSpace(item))
|
||||||
|
{
|
||||||
|
completeSection.Add(ReplaceSpacesAtStartAndEnd(item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return completeSection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The method returns a value for the associated key.
|
||||||
|
/// This method is not case-sensitive.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">Name of the requested section.</param>
|
||||||
|
/// <param name="key">Name of the requested key.</param>
|
||||||
|
/// <param name="convertValueToLower">If "true" is passed, the value will be returned in lowercase letters.</param>
|
||||||
|
/// <returns>Returns the value for the specified key in the specified section, if available, otherwise null.</returns>
|
||||||
|
public string GetValue(string section, string key, bool convertValueToLower = false)
|
||||||
|
{
|
||||||
|
section = CheckSection(section);
|
||||||
|
key = key.ToLower();
|
||||||
|
|
||||||
|
List<string> completeSection = GetSection(section);
|
||||||
|
|
||||||
|
foreach (var item in completeSection)
|
||||||
|
{
|
||||||
|
// Continue if entry is no key.
|
||||||
|
if (!item.Contains("=") && item.Contains("[") && item.Contains("]")) continue;
|
||||||
|
|
||||||
|
string[] keyAndValue = item.Split(new string[] { "=" }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
if (keyAndValue[0].ToLower() == key && keyAndValue.Count() > 1)
|
||||||
|
{
|
||||||
|
if (convertValueToLower == true)
|
||||||
|
{
|
||||||
|
keyAndValue[1] = keyAndValue[1].ToLower();
|
||||||
|
}
|
||||||
|
return keyAndValue[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set or add a value of the associated key in the specified section.
|
||||||
|
/// This method is not case-sensitive.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">Name of the section.</param>
|
||||||
|
/// <param name="key">Name of the key.</param>
|
||||||
|
/// <param name="value">Value to save.</param>
|
||||||
|
/// <param name="convertValueToLower">If "true" is passed, the value will be saved in lowercase letters.</param>
|
||||||
|
public void SetValue(string section, string key, string value, bool convertValueToLower = false)
|
||||||
|
{
|
||||||
|
section = CheckSection(section, false);
|
||||||
|
string sectionToLower = section.ToLower();
|
||||||
|
|
||||||
|
bool sectionFound = false;
|
||||||
|
|
||||||
|
List<string> iniFileContent = new List<string>();
|
||||||
|
|
||||||
|
string[] fileLines = File.ReadAllLines(_File);
|
||||||
|
|
||||||
|
// Creates a new INI file if none exists.
|
||||||
|
if (fileLines.Length <= 0)
|
||||||
|
{
|
||||||
|
iniFileContent = AddSection(iniFileContent, section, key, value, convertValueToLower);
|
||||||
|
WriteFile(iniFileContent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < fileLines.Length; i++)
|
||||||
|
{
|
||||||
|
// Possibility 1: The desired section has not (yet) been found.
|
||||||
|
if (fileLines[i].Replace(" ", "").ToLower() != sectionToLower)
|
||||||
|
{
|
||||||
|
iniFileContent.Add(fileLines[i]);
|
||||||
|
// If a section does not exist, the section will be created.
|
||||||
|
if (i == fileLines.Length - 1 && fileLines[i].Replace(" ", "").ToLower() != sectionToLower && sectionFound == false)
|
||||||
|
{
|
||||||
|
iniFileContent.Add(null);
|
||||||
|
iniFileContent = AddSection(iniFileContent, section, key, value, convertValueToLower);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Possibility 2 -> Desired section was found.
|
||||||
|
sectionFound = true;
|
||||||
|
|
||||||
|
// Get the complete section in which the target key may be.
|
||||||
|
List<string> targetSection = GetSection(sectionToLower, true);
|
||||||
|
|
||||||
|
for (int x = 0; x < targetSection.Count; x++)
|
||||||
|
{
|
||||||
|
string[] targetKey = targetSection[x].Split(new string[] { "=" }, StringSplitOptions.None);
|
||||||
|
// When the target key is found.
|
||||||
|
if (targetKey[0].ToLower() == key.ToLower())
|
||||||
|
{
|
||||||
|
if (convertValueToLower == true)
|
||||||
|
{
|
||||||
|
iniFileContent.Add(key + "=" + value.ToLower());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iniFileContent.Add(key + "=" + value);
|
||||||
|
}
|
||||||
|
i = i + x;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iniFileContent.Add(targetSection[x]);
|
||||||
|
// If the target key is not found, it will be created.
|
||||||
|
if (x == targetSection.Count - 1 && targetKey[0].ToLower() != key.ToLower())
|
||||||
|
{
|
||||||
|
if (convertValueToLower == true)
|
||||||
|
{
|
||||||
|
iniFileContent.Add(key + "=" + value.ToLower());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iniFileContent.Add(key + "=" + value);
|
||||||
|
}
|
||||||
|
i = i + x;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteFile(iniFileContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Private Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ensures that a section is always in the following format: [section].
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">Section to be checked for correct format.</param>
|
||||||
|
/// <param name="convertToLower">Specifies whether the section should be vonverted in lower case letters.</param>
|
||||||
|
/// <returns>Returns section in this form: [section].</returns>
|
||||||
|
private string CheckSection(string section, bool convertToLower = true)
|
||||||
|
{
|
||||||
|
if (convertToLower == true)
|
||||||
|
{
|
||||||
|
section = section.ToLower();
|
||||||
|
}
|
||||||
|
if (!section.StartsWith("[") && !section.EndsWith("]"))
|
||||||
|
{
|
||||||
|
section = "[" + section + "]";
|
||||||
|
}
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes leading and trailing spaces from sections, keys and values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">String to be trimmed.</param>
|
||||||
|
/// <returns>Returns the trimmed string.</returns>
|
||||||
|
private string ReplaceSpacesAtStartAndEnd(string item)
|
||||||
|
{
|
||||||
|
// If the string has a key and a value.
|
||||||
|
if (item.Contains("=") && !item.Contains("[") && !item.Contains("]"))
|
||||||
|
{
|
||||||
|
string[] keyAndValue = item.Split(new string[] { "=" }, StringSplitOptions.None);
|
||||||
|
return keyAndValue[0].Trim() + "=" + keyAndValue[1].Trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
return item.Trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a new section with key value pair.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="iniFileContent">List iniFileContent from SetValue.</param>
|
||||||
|
/// <param name="section">Section to be created.</param>
|
||||||
|
/// <param name="key">Key to be added.</param>
|
||||||
|
/// <param name="value">Value to be added.</param>
|
||||||
|
/// <param name="convertValueToLower">Specifies whether the key and value should be saved in lower case letters.</param>
|
||||||
|
/// <returns>Returns the new created section with key value pair.</returns>
|
||||||
|
private List<string> AddSection(List<string> iniFileContent, string section, string key, string value, bool convertValueToLower)
|
||||||
|
{
|
||||||
|
if (convertValueToLower == true)
|
||||||
|
{
|
||||||
|
value = value.ToLower();
|
||||||
|
}
|
||||||
|
|
||||||
|
iniFileContent.Add(section);
|
||||||
|
iniFileContent.Add($"{key}={value}");
|
||||||
|
return iniFileContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteFile(List<string> content)
|
||||||
|
{
|
||||||
|
StreamWriter writer = new StreamWriter(_File);
|
||||||
|
foreach (var item in content)
|
||||||
|
{
|
||||||
|
writer.WriteLine(item);
|
||||||
|
}
|
||||||
|
writer.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
BIN
Partypacker/Icon.png
Normal file
BIN
Partypacker/Icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 325 KiB |
52
Partypacker/MainWindow.xaml
Normal file
52
Partypacker/MainWindow.xaml
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
<Window x:Class="Partypacker.MainWindow"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:local="clr-namespace:Partypacker"
|
||||||
|
xmlns:adonisControls="clr-namespace:AdonisUI.Controls;assembly=AdonisUI"
|
||||||
|
xmlns:adonisExtensions="clr-namespace:AdonisUI.Extensions;assembly=AdonisUI"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
ResizeMode="CanMinimize"
|
||||||
|
Title="Partypack Launcher" Height="450" Width="800">
|
||||||
|
<Window.Style>
|
||||||
|
<Style TargetType="Window" BasedOn="{StaticResource {x:Type Window}}"/>
|
||||||
|
</Window.Style>
|
||||||
|
<Window.Resources>
|
||||||
|
<Style x:Key="NexaBoldFont">
|
||||||
|
<Setter Property="TextElement.FontFamily" Value="#NexaBold"/>
|
||||||
|
</Style>
|
||||||
|
</Window.Resources>
|
||||||
|
|
||||||
|
<Grid>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition Height="30" />
|
||||||
|
<RowDefinition Height="10" />
|
||||||
|
<RowDefinition Height="30" />
|
||||||
|
<RowDefinition Height="10" />
|
||||||
|
<RowDefinition Height="30" />
|
||||||
|
<RowDefinition Height="10" />
|
||||||
|
<RowDefinition Height="30" />
|
||||||
|
<RowDefinition Height="10" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="10" />
|
||||||
|
<ColumnDefinition Width="250" />
|
||||||
|
<ColumnDefinition Width="10"/>
|
||||||
|
<ColumnDefinition />
|
||||||
|
<ColumnDefinition Width="10" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBox PreviewTextInput="TextBox_PreviewTextInput" Grid.Column="3" adonisExtensions:WatermarkExtension.Watermark="Proxy Port (default: 6969)" TextChanged="OnChangePort" Margin="10,10,260,0" Grid.RowSpan="2" Grid.Row="6" />
|
||||||
|
<Button x:Name="LaunchButton" Grid.Row="4" Grid.Column="3" Click="OnLaunch" IsEnabled="False" Margin="10,10,260,0" Grid.RowSpan="2">Launch</Button>
|
||||||
|
<Button x:Name="LoginButton" Grid.Row="2" Grid.Column="3" Click="OnLoginUsingDiscord" Margin="10,10,260,0" Grid.RowSpan="2">Log in using Discord</Button>
|
||||||
|
<Ellipse x:Name="PFPContainer" MouseLeftButtonDown="OnDashboard" RenderOptions.BitmapScalingMode="HighQuality" Margin="0,8,195,211" Grid.Column="1" Stretch="Uniform" Visibility="Hidden">
|
||||||
|
<Ellipse.Fill>
|
||||||
|
<ImageBrush x:Name="ProfilePictureImage" ImageSource="https://cdn.discordapp.com/avatars/419224403415662592/b9486673bd2a484314a1e718c9d9c57b.webp" Stretch="UniformToFill"/>
|
||||||
|
</Ellipse.Fill>
|
||||||
|
</Ellipse>
|
||||||
|
<TextBlock x:Name="UsernameTextBlock" HorizontalAlignment="Left" Margin="43,16,0,0" TextWrapping="Wrap" Text="AveryMadness (@averymadness)" VerticalAlignment="Top" Grid.Column="1" Visibility="Hidden"/>
|
||||||
|
<Image x:Name="Logo" Grid.Column="3" HorizontalAlignment="Left" Height="201" VerticalAlignment="Top" Width="200" Source="/Icon.png" Margin="26,41,0,0" Stretch="Uniform"/>
|
||||||
|
<TextBlock Grid.Column="3" HorizontalAlignment="Left" Margin="44,222,0,0" TextWrapping="Wrap" Text="Partypack" VerticalAlignment="Top" Height="67" Width="182" FontSize="36" Style="{DynamicResource NexaBoldFont}" Grid.RowSpan="2"/>
|
||||||
|
</Grid>
|
||||||
|
</Window>
|
251
Partypacker/MainWindow.xaml.cs
Normal file
251
Partypacker/MainWindow.xaml.cs
Normal file
|
@ -0,0 +1,251 @@
|
||||||
|
using DiscordRPC;
|
||||||
|
using DiscordRPC.Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Partypacker.Core;
|
||||||
|
using Partypacker.Net;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Timers;
|
||||||
|
using System.Transactions;
|
||||||
|
using System.Web;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Threading;
|
||||||
|
using WatsonWebserver;
|
||||||
|
|
||||||
|
namespace Partypacker
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for MainWindow.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class MainWindow : Window
|
||||||
|
{
|
||||||
|
static Proxy Proxx;
|
||||||
|
static string DiscordAuthURL;
|
||||||
|
static int Port = 6969;
|
||||||
|
static string Token;
|
||||||
|
static UserDetailObject UserDetails;
|
||||||
|
static Server sv;
|
||||||
|
public static INIFile settings = new("settings.ini", true);
|
||||||
|
|
||||||
|
public MainWindow()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
InitializeRPC();
|
||||||
|
Application.Current.Exit += OnApplicationExit;
|
||||||
|
Process.GetCurrentProcess().Exited += MainWindow_Exited;
|
||||||
|
|
||||||
|
var DiscordURL = PartypackServer.GET("/api/discord/url");
|
||||||
|
if (!DiscordURL.Key)
|
||||||
|
{
|
||||||
|
MessageBox.Show("Failed to contact the Partypack API. (Is it running?)", "Partypack API Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
Environment.Exit(-1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DiscordAuthURL = DiscordURL.Value;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(settings.GetValue("Launcher", "token")))
|
||||||
|
AutoLogin();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MainWindow_Exited(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Proxx?.StopProxy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnApplicationExit(object sender, ExitEventArgs e) => Proxx?.StopProxy();
|
||||||
|
void OnChangePort(object sender, TextChangedEventArgs e) {
|
||||||
|
if (!int.TryParse(((TextBox)sender).Text, out int P))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Port = P;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDashboard(object sender, MouseButtonEventArgs e) => Process.Start(new ProcessStartInfo { UseShellExecute = true, FileName = PartypackServer.DashboardURL + "/profile"});
|
||||||
|
|
||||||
|
private void UpdateUserUI()
|
||||||
|
{
|
||||||
|
this.Dispatcher.Invoke(() =>
|
||||||
|
{
|
||||||
|
UsernameTextBlock.Text = string.IsNullOrWhiteSpace(UserDetails.GlobalName) ? UserDetails.Username : @$"{UserDetails.GlobalName} (@{UserDetails.Username})";
|
||||||
|
ProfilePictureImage.ImageSource = (ImageSource)new ImageSourceConverter().ConvertFromString(UserDetails.Avatar);
|
||||||
|
UsernameTextBlock.Visibility = Visibility.Visible;
|
||||||
|
PFPContainer.Visibility = Visibility.Visible;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoLogin()
|
||||||
|
{
|
||||||
|
var B64Token = settings.GetValue("Launcher", "token");
|
||||||
|
var NonB64Bytes = Convert.FromHexString(B64Token);
|
||||||
|
var NonB64Str = Encoding.UTF8.GetString(NonB64Bytes);
|
||||||
|
Token = NonB64Str;
|
||||||
|
UserDetails = JsonConvert.DeserializeObject<UserDetailObject>(Encoding.UTF8.GetString(Convert.FromHexString(HttpUtility.UrlDecode(settings.GetValue("Launcher", "user")))));
|
||||||
|
UpdateUserUI();
|
||||||
|
Dispatcher.Invoke(() => LaunchButton.IsEnabled = true);
|
||||||
|
ConvertLoginToLogout();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ConvertLoginToLogout()
|
||||||
|
{
|
||||||
|
Dispatcher.Invoke(() =>
|
||||||
|
{
|
||||||
|
LoginButton.Content = "Log Out";
|
||||||
|
LoginButton.Click -= OnLoginUsingDiscord;
|
||||||
|
LoginButton.Click += OnLogout;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnLogout(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
this.Dispatcher.Invoke(() =>
|
||||||
|
{
|
||||||
|
UsernameTextBlock.Visibility = Visibility.Hidden;
|
||||||
|
PFPContainer.Visibility = Visibility.Hidden;
|
||||||
|
UserDetails = null;
|
||||||
|
Token = "";
|
||||||
|
settings.SetValue("Launcher", "user", "");
|
||||||
|
settings.SetValue("Launcher", "token", "");
|
||||||
|
|
||||||
|
LoginButton.Content = "Log in using Discord";
|
||||||
|
LoginButton.Click += OnLoginUsingDiscord;
|
||||||
|
LoginButton.Click -= OnLogout;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DefaultRoute(HttpContext ctx)
|
||||||
|
{
|
||||||
|
string _Token = ctx.Request.Query.Elements["token"];
|
||||||
|
string _UserDetails = ctx.Request.Query.Elements["user"];
|
||||||
|
|
||||||
|
if (_Token == null || _UserDetails == null)
|
||||||
|
{
|
||||||
|
await ctx.Response.Send($"Invalid request. ({_Token}, {_UserDetails})");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Token = _Token;
|
||||||
|
UserDetails = JsonConvert.DeserializeObject<UserDetailObject>(Encoding.UTF8.GetString(Convert.FromHexString(HttpUtility.UrlDecode(_UserDetails))));
|
||||||
|
settings.SetValue("Launcher", "user", HttpUtility.UrlDecode(_UserDetails));
|
||||||
|
settings.SetValue("Launcher", "token", Convert.ToHexString(Encoding.UTF8.GetBytes(Token)));
|
||||||
|
UpdateUserUI();
|
||||||
|
Dispatcher.Invoke(() =>
|
||||||
|
{
|
||||||
|
LaunchButton.IsEnabled = true;
|
||||||
|
});
|
||||||
|
ConvertLoginToLogout();
|
||||||
|
|
||||||
|
await ctx.Response.Send("All done! You can close this tab now.");
|
||||||
|
sv.Stop();
|
||||||
|
sv = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnLoginUsingDiscord(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Process.Start(new ProcessStartInfo { UseShellExecute = true, FileName = $"{DiscordAuthURL}&state={HttpUtility.UrlEncode(Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new
|
||||||
|
{
|
||||||
|
Client = "PartypackerDesktop"
|
||||||
|
}))))}"});
|
||||||
|
|
||||||
|
if (sv == null)
|
||||||
|
{
|
||||||
|
sv = new Server("127.0.0.1", 14968, false, DefaultRoute);
|
||||||
|
sv.Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WaitingForGameToOpen = true;
|
||||||
|
System.Timers.Timer GameCheckTimer;
|
||||||
|
private void CheckForProcessAndClose(object sender, ElapsedEventArgs e)
|
||||||
|
{
|
||||||
|
Process[] processes = Process.GetProcessesByName("FortniteLauncher");
|
||||||
|
|
||||||
|
if (WaitingForGameToOpen)
|
||||||
|
{
|
||||||
|
if (processes.Length > 0)
|
||||||
|
WaitingForGameToOpen = false;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (processes.Length > 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Dispatcher.Invoke(() =>
|
||||||
|
{
|
||||||
|
LaunchButton.IsEnabled = true;
|
||||||
|
});
|
||||||
|
WaitingForGameToOpen = true;
|
||||||
|
GameCheckTimer.Stop();
|
||||||
|
Proxx?.StopProxy();
|
||||||
|
}
|
||||||
|
|
||||||
|
async void OnLaunch(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Proxx = new Proxy(Port);
|
||||||
|
Proxx.Token = Token;
|
||||||
|
Proxx.StartProxy();
|
||||||
|
|
||||||
|
using (Process p = Process.Start(new ProcessStartInfo { UseShellExecute = true, FileName = "com.epicgames.launcher://apps/fn%3A4fe75bbc5a674f4f9b356b5c90567da5%3AFortnite?action=launch&silent=true" }))
|
||||||
|
{
|
||||||
|
LaunchButton.IsEnabled = false;
|
||||||
|
GameCheckTimer = new System.Timers.Timer();
|
||||||
|
GameCheckTimer.Interval = 5000;
|
||||||
|
GameCheckTimer.Elapsed += CheckForProcessAndClose;
|
||||||
|
GameCheckTimer.Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
|
||||||
|
{
|
||||||
|
Regex regex = new Regex("[^0-9]+");
|
||||||
|
e.Handled = regex.IsMatch(e.Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DiscordRpcClient client;
|
||||||
|
void InitializeRPC()
|
||||||
|
{
|
||||||
|
client = new DiscordRpcClient("1198605718169858088");
|
||||||
|
|
||||||
|
client.Logger = new ConsoleLogger() { Level = LogLevel.Warning };
|
||||||
|
|
||||||
|
client.OnReady += (sender, e) =>
|
||||||
|
{
|
||||||
|
Console.WriteLine("Received Ready from user {0}", e.User.Username);
|
||||||
|
};
|
||||||
|
|
||||||
|
client.OnPresenceUpdate += (sender, e) =>
|
||||||
|
{
|
||||||
|
Console.WriteLine("Received Update! {0}", e.Presence);
|
||||||
|
};
|
||||||
|
|
||||||
|
client.Initialize();
|
||||||
|
|
||||||
|
client.SetPresence(new RichPresence()
|
||||||
|
{
|
||||||
|
Details = "Modding Fortnite Festival",
|
||||||
|
State = "Loading Custom Tracks",
|
||||||
|
Timestamps = new DiscordRPC.Timestamps()
|
||||||
|
{
|
||||||
|
Start = DateTime.UtcNow,
|
||||||
|
},
|
||||||
|
Assets = new Assets()
|
||||||
|
{
|
||||||
|
LargeImageKey = "logo",
|
||||||
|
LargeImageText = "Partypacker - Alpha",
|
||||||
|
//SmallImageKey = "image_small"
|
||||||
|
},
|
||||||
|
Buttons = new DiscordRPC.Button[]
|
||||||
|
{
|
||||||
|
new DiscordRPC.Button() {Label = "Check out Partypack!", Url = "https://partypack.mcthe.dev/"}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
BIN
Partypacker/Nexa Bold.otf
Normal file
BIN
Partypacker/Nexa Bold.otf
Normal file
Binary file not shown.
BIN
Partypacker/PartyPacker.ico
Normal file
BIN
Partypacker/PartyPacker.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 119 KiB |
|
@ -1,27 +1,54 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFramework>net7.0-windows</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ApplicationIcon>icon.ico</ApplicationIcon>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<PackageIcon>icon.ico</PackageIcon>
|
<UseWPF>true</UseWPF>
|
||||||
|
<ApplicationIcon>PartyPacker.ico</ApplicationIcon>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BCMakeCert" Version="2.0.9" />
|
<None Remove="favicon.png" />
|
||||||
<PackageReference Include="FiddlerCore.Trial" Version="5.0.0" />
|
<None Remove="Icon.png" />
|
||||||
<PackageReference Include="Pastel" Version="5.0.0" />
|
<None Remove="Nexa Bold.otf" />
|
||||||
<PackageReference Include="System.ComponentModel.Composition" Version="8.0.0" />
|
|
||||||
<PackageReference Include="Telerik.NetworkConnections" Version="0.2.0" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="icon.ico">
|
<Content Include="PartyPacker.ico" />
|
||||||
<Pack>True</Pack>
|
</ItemGroup>
|
||||||
<PackagePath></PackagePath>
|
|
||||||
</None>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="AdonisUI" Version="1.17.1" />
|
||||||
|
<PackageReference Include="AdonisUI.ClassicTheme" Version="1.17.1" />
|
||||||
|
<PackageReference Include="BCMakeCert" Version="2.0.9" />
|
||||||
|
<PackageReference Include="DiscordRichPresence" Version="1.2.1.24" />
|
||||||
|
<PackageReference Include="FiddlerCore.Trial" Version="5.0.0" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
|
<PackageReference Include="Pastel" Version="5.0.0" />
|
||||||
|
<PackageReference Include="Telerik.NetworkConnections" Version="0.2.0" />
|
||||||
|
<PackageReference Include="Watson" Version="5.1.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Resource Include="Icon.png" />
|
||||||
|
<Resource Include="Nexa Bold.otf" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Update="Properties\Resources.Designer.cs">
|
||||||
|
<DesignTime>True</DesignTime>
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DependentUpon>Resources.resx</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Update="Properties\Resources.resx">
|
||||||
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
|
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||||
|
</EmbeddedResource>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1,118 +0,0 @@
|
||||||
using Partypacker.Core;
|
|
||||||
using Partypacker.Net;
|
|
||||||
using Pastel;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Drawing;
|
|
||||||
using static Partypacker.Win32;
|
|
||||||
|
|
||||||
namespace Partypacker
|
|
||||||
{
|
|
||||||
public static class Program
|
|
||||||
{
|
|
||||||
private static SetConsoleCtrlEventHandler CtrlHandler;
|
|
||||||
private static Proxy Proxx;
|
|
||||||
|
|
||||||
private static void Main(string[] args)
|
|
||||||
{
|
|
||||||
ushort? port = 6969;
|
|
||||||
|
|
||||||
var DiscordLoginLink = Server.GET("/api/discord/url");
|
|
||||||
|
|
||||||
Console.SetWindowSize(75, 20);
|
|
||||||
|
|
||||||
Console.CursorVisible = false;
|
|
||||||
|
|
||||||
Console.WriteLine(@"
|
|
||||||
_____ _ _
|
|
||||||
| __ \ | | | |
|
|
||||||
| |__) |_ _ _ __| |_ _ _ _ __ __ _ ___| | _____ _ __
|
|
||||||
| ___/ _` | '__| __| | | | '_ \ / _` |/ __| |/ / _ \ '__|
|
|
||||||
| | | (_| | | | |_| |_| | |_) | (_| | (__| < __/ |
|
|
||||||
|_| \__,_|_| \__|\__, | .__/ \__,_|\___|_|\_\___|_|
|
|
||||||
__/ | |
|
|
||||||
|___/|_| ".Pastel(Color.IndianRed));
|
|
||||||
Console.WriteLine("-----------------------------------------------------------".Pastel(Color.CadetBlue));
|
|
||||||
|
|
||||||
Console.WriteLine("Welcome to Partypacker - Select an option below:");
|
|
||||||
|
|
||||||
ConsoleKeyInfo ReceivedKeyInput;
|
|
||||||
int SelectedOptionIndex = 0;
|
|
||||||
bool Running = true;
|
|
||||||
SelectableOption[] Options = new SelectableOption[]
|
|
||||||
{
|
|
||||||
new SelectableOption("Launch Fortnite", () =>
|
|
||||||
Run(port, () => Process.Start(new ProcessStartInfo { FileName = "com.epicgames.launcher://apps/fn%3A4fe75bbc5a674f4f9b356b5c90567da5%3AFortnite?action=launch&silent=true", UseShellExecute = true }))),
|
|
||||||
new SelectableOption("Open Dashboard", () => Process.Start(new ProcessStartInfo { FileName = "https://partypack.mcthe.dev", UseShellExecute = true })),
|
|
||||||
new SelectableOption("Log in using Discord", () => Process.Start(new ProcessStartInfo { FileName = DiscordLoginLink.Value, UseShellExecute = true }))
|
|
||||||
};
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
while (Running)
|
|
||||||
{
|
|
||||||
(int left, int top) = Console.GetCursorPosition();
|
|
||||||
for (int i = 0; i < Options.Length; i++)
|
|
||||||
{
|
|
||||||
bool Selected = SelectedOptionIndex == i;
|
|
||||||
SelectableOption Option = Options[i];
|
|
||||||
Console.WriteLine($"{(Selected ? ">".Pastel(Color.LimeGreen) : " ")} {Option.Name.Pastel(Selected ? Color.DarkGreen : Color.Gray)}");
|
|
||||||
}
|
|
||||||
|
|
||||||
ReceivedKeyInput = Console.ReadKey();
|
|
||||||
switch (ReceivedKeyInput.Key)
|
|
||||||
{
|
|
||||||
case ConsoleKey.UpArrow:
|
|
||||||
SelectedOptionIndex--;
|
|
||||||
break;
|
|
||||||
case ConsoleKey.DownArrow:
|
|
||||||
SelectedOptionIndex++;
|
|
||||||
break;
|
|
||||||
case ConsoleKey.Enter:
|
|
||||||
Options[SelectedOptionIndex].OnPress.Invoke();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.SetCursorPosition(left, top);
|
|
||||||
SelectedOptionIndex = Math.Clamp(SelectedOptionIndex, 0, Options.Length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Console.WriteLine(e.Message);
|
|
||||||
Debug.Fail(e.StackTrace);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
OnApplicationExit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void Run(ushort? port, Action Finish)
|
|
||||||
{
|
|
||||||
CtrlHandler = CleanUp;
|
|
||||||
SetConsoleCtrlHandler(CtrlHandler, true);
|
|
||||||
Proxx = port switch
|
|
||||||
{
|
|
||||||
null => new Proxy(),
|
|
||||||
_ => new Proxy((ushort)port)
|
|
||||||
};
|
|
||||||
Proxx.StartProxy();
|
|
||||||
// please make this dynamic later :D
|
|
||||||
Proxx.Token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJJRCI6IjQ1NDk2ODU0MjcyMzU3MTcxNSIsImlhdCI6MTcwNTkyODQ0M30.ogINqFZ_3DBkECbHo87HjW9c6p2imT1CnCvfIR3iGJ4";
|
|
||||||
|
|
||||||
Finish.Invoke();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void OnApplicationExit()
|
|
||||||
{
|
|
||||||
CleanUp(CtrlType.CTRL_C_EVENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool CleanUp(CtrlType ctrlType)
|
|
||||||
{
|
|
||||||
Proxx?.StopProxy();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
63
Partypacker/Properties/Resources.Designer.cs
generated
Normal file
63
Partypacker/Properties/Resources.Designer.cs
generated
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// This code was generated by a tool.
|
||||||
|
// Runtime Version:4.0.30319.42000
|
||||||
|
//
|
||||||
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
|
// the code is regenerated.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace Partypacker.Properties {
|
||||||
|
using System;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||||
|
/// </summary>
|
||||||
|
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||||
|
// class via a tool like ResGen or Visual Studio.
|
||||||
|
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||||
|
// with the /str option, or rebuild your VS project.
|
||||||
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
|
internal class Resources {
|
||||||
|
|
||||||
|
private static global::System.Resources.ResourceManager resourceMan;
|
||||||
|
|
||||||
|
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||||
|
|
||||||
|
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||||
|
internal Resources() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the cached ResourceManager instance used by this class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||||
|
get {
|
||||||
|
if (object.ReferenceEquals(resourceMan, null)) {
|
||||||
|
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Partypacker.Properties.Resources", typeof(Resources).Assembly);
|
||||||
|
resourceMan = temp;
|
||||||
|
}
|
||||||
|
return resourceMan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Overrides the current thread's CurrentUICulture property for all
|
||||||
|
/// resource lookups using this strongly typed resource class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Globalization.CultureInfo Culture {
|
||||||
|
get {
|
||||||
|
return resourceCulture;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
resourceCulture = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
101
Partypacker/Properties/Resources.resx
Normal file
101
Partypacker/Properties/Resources.resx
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 1.3
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">1.3</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1">this is my long string</data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
[base64 mime encoded serialized .NET Framework object]
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>1.3</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
|
@ -47,4 +47,4 @@ namespace Partypacker.Net
|
||||||
rsaCng.Clear();
|
rsaCng.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -32,14 +32,14 @@ namespace Partypacker.Net
|
||||||
|
|
||||||
public Proxy() : this(9999) { } //default port
|
public Proxy() : this(9999) { } //default port
|
||||||
|
|
||||||
public Proxy(ushort port)
|
public Proxy(int port)
|
||||||
{
|
{
|
||||||
appRegistry = new AppRegistry();
|
appRegistry = new AppRegistry();
|
||||||
|
|
||||||
GetDefaultProxySettingsValue();
|
GetDefaultProxySettingsValue();
|
||||||
ConfigureFiddlerSettings(out bool fiddlerCertRegKeysExist);
|
ConfigureFiddlerSettings(out bool fiddlerCertRegKeysExist);
|
||||||
startupSettings = new FiddlerCoreStartupSettingsBuilder()
|
startupSettings = new FiddlerCoreStartupSettingsBuilder()
|
||||||
.ListenOnPort(port)
|
.ListenOnPort((ushort)port)
|
||||||
.RegisterAsSystemProxy()
|
.RegisterAsSystemProxy()
|
||||||
.DecryptSSL()
|
.DecryptSSL()
|
||||||
.OptimizeThreadPool()
|
.OptimizeThreadPool()
|
||||||
|
@ -130,10 +130,18 @@ namespace Partypacker.Net
|
||||||
#region EVENT_HANDLERS
|
#region EVENT_HANDLERS
|
||||||
private void OnBeforeRequest(Session oSession)
|
private void OnBeforeRequest(Session oSession)
|
||||||
{
|
{
|
||||||
|
string BaseURL =
|
||||||
|
#if DEBUG
|
||||||
|
MainWindow.settings.GetValue("Launcher", "apiurl") ?? "https://partypack.mcthe.dev";
|
||||||
|
#else
|
||||||
|
MainWindow.settings.GetValue("Launcher", "apiurl") ?? "https://partypack.mcthe.dev";
|
||||||
|
#endif
|
||||||
|
|
||||||
if (oSession.PathAndQuery.Contains("/content/api/pages/fortnite-game")
|
if (oSession.PathAndQuery.Contains("/content/api/pages/fortnite-game")
|
||||||
|| oSession.HostnameIs("cdn.qstv.on.epicgames.com")
|
|| oSession.HostnameIs("cdn.qstv.on.epicgames.com")
|
||||||
|| oSession.PathAndQuery.Contains("/master.blurl")
|
|| oSession.PathAndQuery.Contains("/master.blurl")
|
||||||
|| oSession.PathAndQuery.Contains("/main.blurl")
|
|| oSession.PathAndQuery.Contains("/main.blurl")
|
||||||
|
|| oSession.fullUrl.StartsWith(BaseURL)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (oSession.HTTPMethodIs("CONNECT"))
|
if (oSession.HTTPMethodIs("CONNECT"))
|
||||||
|
@ -142,13 +150,6 @@ namespace Partypacker.Net
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string BaseURL =
|
|
||||||
#if DEBUG
|
|
||||||
"http://localhost:6677";
|
|
||||||
#else
|
|
||||||
"https://api.partypack.mcthe.dev";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
oSession.RequestHeaders.Add("X-Partypack-Token", Token);
|
oSession.RequestHeaders.Add("X-Partypack-Token", Token);
|
||||||
|
|
||||||
if (oSession.PathAndQuery.Contains("/master.blurl")
|
if (oSession.PathAndQuery.Contains("/master.blurl")
|
||||||
|
@ -157,8 +158,12 @@ namespace Partypacker.Net
|
||||||
else
|
else
|
||||||
oSession.fullUrl = BaseURL + oSession.PathAndQuery;
|
oSession.fullUrl = BaseURL + oSession.PathAndQuery;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
oSession.Ignore();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region CLEANUP
|
#region CLEANUP
|
||||||
private bool ResetProxySettings()
|
private bool ResetProxySettings()
|
||||||
|
@ -189,4 +194,4 @@ namespace Partypacker.Net
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,20 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Partypacker
|
|
||||||
{
|
|
||||||
public class SelectableOption
|
|
||||||
{
|
|
||||||
public string Name;
|
|
||||||
public Action OnPress;
|
|
||||||
|
|
||||||
public SelectableOption(string name, Action onPress)
|
|
||||||
{
|
|
||||||
Name = name;
|
|
||||||
OnPress = onPress;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
6
Partypacker/global.json
Normal file
6
Partypacker/global.json
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"sdk": {
|
||||||
|
"version": "7.0.405",
|
||||||
|
"rollForward": "latestFeature"
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
Before Width: | Height: | Size: 264 KiB |
Loading…
Reference in New Issue
Block a user