Compare commits

..

1 Commits
gui ... master

Author SHA1 Message Date
McMistrzYT
8a9b6e1e31 current stuff 2024-01-22 23:03:20 +01:00
24 changed files with 180 additions and 891 deletions

View File

@ -1,9 +1,9 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.8.34219.65
# Visual Studio Version 16
VisualStudioVersion = 16.0.33927.289
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Partypacker", "Partypacker\Partypacker.csproj", "{BCB1E673-FE06-4360-895D-07FE682C720D}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Partypacker", "Partypacker\Partypacker.csproj", "{FE06B383-0C7A-4A35-B208-66133110BB32}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -11,15 +11,15 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{BCB1E673-FE06-4360-895D-07FE682C720D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BCB1E673-FE06-4360-895D-07FE682C720D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BCB1E673-FE06-4360-895D-07FE682C720D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BCB1E673-FE06-4360-895D-07FE682C720D}.Release|Any CPU.Build.0 = Release|Any CPU
{FE06B383-0C7A-4A35-B208-66133110BB32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FE06B383-0C7A-4A35-B208-66133110BB32}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FE06B383-0C7A-4A35-B208-66133110BB32}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FE06B383-0C7A-4A35-B208-66133110BB32}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F12064C4-E05B-464A-BF11-E0E20C7D2B3F}
SolutionGuid = {16591BB0-2EFE-43B1-917D-7CD574AB32C8}
EndGlobalSection
EndGlobal

View File

@ -1,15 +0,0 @@
<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>

View File

@ -1,14 +0,0 @@
using System.Configuration;
using System.Data;
using System.Windows;
namespace Partypacker
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}

View File

@ -1,10 +0,0 @@
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)
)]

View File

@ -1,21 +0,0 @@
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;
}
}

View File

@ -47,4 +47,4 @@ namespace Partypacker.Core
public RegistryValueKind RegistryValueKind { get; set; }
}
}
}

View File

@ -17,4 +17,4 @@ namespace Partypacker.Core
.ForEach(x => registryKey
.SetValue(x.Name, x.Value, x.RegistryValueKind));
}
}
}

View File

@ -1,28 +1,19 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace Partypacker.Core
{
internal class PartypackServer
internal class Server
{
public static string BaseURL =
static string BaseURL =
#if DEBUG
MainWindow.settings.GetValue("Launcher", "apiurl") ?? "https://partypack.mcthe.dev";
"http://localhost:6677";
#else
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";
"https://api.partypack.mcthe.dev";
#endif
public static KeyValuePair<bool, string> GET(string URL = "/")
@ -47,7 +38,7 @@ namespace Partypacker.Core
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
Console.WriteLine(ex.Message);
return new KeyValuePair<bool, string>(false, string.Empty);
}
}
@ -82,5 +73,5 @@ namespace Partypacker.Core
}
}
}
}

View File

@ -87,4 +87,4 @@ namespace Partypacker
INTERNET_OPTION_SETTINGS_CHANGED = 39
}
}
}
}

View File

@ -1,275 +0,0 @@
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
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 325 KiB

View File

@ -1,52 +0,0 @@
<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>

View File

@ -1,251 +0,0 @@
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/"}
}
});
}
}
}

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

View File

@ -1,54 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net7.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
<ApplicationIcon>PartyPacker.ico</ApplicationIcon>
<Nullable>enable</Nullable>
<ApplicationIcon>icon.ico</ApplicationIcon>
<PackageIcon>icon.ico</PackageIcon>
</PropertyGroup>
<ItemGroup>
<None Remove="favicon.png" />
<None Remove="Icon.png" />
<None Remove="Nexa Bold.otf" />
</ItemGroup>
<ItemGroup>
<Content Include="PartyPacker.ico" />
</ItemGroup>
<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="System.ComponentModel.Composition" Version="8.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>
<None Include="icon.ico">
<Pack>True</Pack>
<PackagePath></PackagePath>
</None>
</ItemGroup>
</Project>

118
Partypacker/Program.cs Normal file
View File

@ -0,0 +1,118 @@
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;
}
}
}

View File

@ -1,63 +0,0 @@
//------------------------------------------------------------------------------
// <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;
}
}
}
}

View File

@ -1,101 +0,0 @@
<?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>

View File

@ -47,4 +47,4 @@ namespace Partypacker.Net
rsaCng.Clear();
}
}
}
}

View File

@ -32,14 +32,14 @@ namespace Partypacker.Net
public Proxy() : this(9999) { } //default port
public Proxy(int port)
public Proxy(ushort port)
{
appRegistry = new AppRegistry();
GetDefaultProxySettingsValue();
ConfigureFiddlerSettings(out bool fiddlerCertRegKeysExist);
startupSettings = new FiddlerCoreStartupSettingsBuilder()
.ListenOnPort((ushort)port)
.ListenOnPort(port)
.RegisterAsSystemProxy()
.DecryptSSL()
.OptimizeThreadPool()
@ -130,18 +130,10 @@ namespace Partypacker.Net
#region EVENT_HANDLERS
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")
|| oSession.HostnameIs("cdn.qstv.on.epicgames.com")
|| oSession.PathAndQuery.Contains("/master.blurl")
|| oSession.PathAndQuery.Contains("/main.blurl")
|| oSession.fullUrl.StartsWith(BaseURL)
)
{
if (oSession.HTTPMethodIs("CONNECT"))
@ -150,6 +142,13 @@ namespace Partypacker.Net
return;
}
string BaseURL =
#if DEBUG
"http://localhost:6677";
#else
"https://api.partypack.mcthe.dev";
#endif
oSession.RequestHeaders.Add("X-Partypack-Token", Token);
if (oSession.PathAndQuery.Contains("/master.blurl")
@ -158,12 +157,8 @@ namespace Partypacker.Net
else
oSession.fullUrl = BaseURL + oSession.PathAndQuery;
}
else
{
oSession.Ignore();
}
}
#endregion
#endregion
#region CLEANUP
private bool ResetProxySettings()
@ -194,4 +189,4 @@ namespace Partypacker.Net
}
#endregion
}
}
}

View File

@ -0,0 +1,20 @@
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;
}
}
}

View File

@ -1,6 +0,0 @@
{
"sdk": {
"version": "7.0.405",
"rollForward": "latestFeature"
}
}

BIN
Partypacker/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB