removed csgo rpc cause of bugs that cant be fixed currently
This commit is contained in:
parent
9ba8394820
commit
ee4aebd050
9 changed files with 3 additions and 278 deletions
|
@ -126,7 +126,6 @@ namespace Release_Tool
|
||||||
files.Add(new file(@"WeeXnes_UAC\bin\Release\WeeXnes_UAC.exe", "WeeXnes_UAC.exe"));
|
files.Add(new file(@"WeeXnes_UAC\bin\Release\WeeXnes_UAC.exe", "WeeXnes_UAC.exe"));
|
||||||
files.Add(new file(@"WeeXnes\bin\Release\DiscordRPC.dll", "DiscordRPC.dll"));
|
files.Add(new file(@"WeeXnes\bin\Release\DiscordRPC.dll", "DiscordRPC.dll"));
|
||||||
files.Add(new file(@"WeeXnes\bin\Release\Newtonsoft.Json.dll", "Newtonsoft.Json.dll"));
|
files.Add(new file(@"WeeXnes\bin\Release\Newtonsoft.Json.dll", "Newtonsoft.Json.dll"));
|
||||||
files.Add(new file(@"WeeXnes\bin\Release\CSGSI.dll", "CSGSI.dll"));
|
|
||||||
files.Add(new file(@"Autostart\bin\Release\Autostart.exe", "Autostart.exe"));
|
files.Add(new file(@"Autostart\bin\Release\Autostart.exe", "Autostart.exe"));
|
||||||
files.Add(new file(@"Update\bin\Release\Update.exe", "Update.exe"));
|
files.Add(new file(@"Update\bin\Release\Update.exe", "Update.exe"));
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@ using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using CSGSI;
|
|
||||||
using Nocksoft.IO.ConfigFiles;
|
using Nocksoft.IO.ConfigFiles;
|
||||||
using MessageBox = System.Windows.MessageBox;
|
using MessageBox = System.Windows.MessageBox;
|
||||||
|
|
||||||
|
@ -17,7 +16,7 @@ namespace WeeXnes.Core
|
||||||
public static string encryptionKey = "8zf5#RdyQ]$4x4_";
|
public static string encryptionKey = "8zf5#RdyQ]$4x4_";
|
||||||
public static string AppDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "WeeXnes");
|
public static string AppDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "WeeXnes");
|
||||||
public static string SettingsFileName = "settings.ini";
|
public static string SettingsFileName = "settings.ini";
|
||||||
public static string version = "3.6";
|
public static string version = "3.6.1";
|
||||||
public static bool info_isRpcRunning = false;
|
public static bool info_isRpcRunning = false;
|
||||||
public static bool info_RpcAutoStart;
|
public static bool info_RpcAutoStart;
|
||||||
public static string apiUrl = "http://www.weexnes.com:5169/";
|
public static string apiUrl = "http://www.weexnes.com:5169/";
|
||||||
|
@ -39,8 +38,6 @@ namespace WeeXnes.Core
|
||||||
public static UpdateVar<bool> settings_RpcShowElapsedTime = new UpdateVar<bool>();
|
public static UpdateVar<bool> settings_RpcShowElapsedTime = new UpdateVar<bool>();
|
||||||
public static UpdateVar<string> settings_RpcDefaultClientID = new UpdateVar<string>();
|
public static UpdateVar<string> settings_RpcDefaultClientID = new UpdateVar<string>();
|
||||||
public static UpdateVar<bool> settings_RpcAutoStart = new UpdateVar<bool>();
|
public static UpdateVar<bool> settings_RpcAutoStart = new UpdateVar<bool>();
|
||||||
public static UpdateVar<bool> settings_builtInCSGORpc = new UpdateVar<bool>();
|
|
||||||
public static GameStateListener gameStateListener = new GameStateListener(4169);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -98,7 +95,6 @@ namespace WeeXnes.Core
|
||||||
Globals.settings_RpcDefaultClientID.Value = "605116707035676701";
|
Globals.settings_RpcDefaultClientID.Value = "605116707035676701";
|
||||||
}
|
}
|
||||||
|
|
||||||
Globals.settings_builtInCSGORpc.Value = Convert.ToBoolean(SettingsFile.GetValue("rpc", "csgoPresence"));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,10 +182,6 @@ namespace WeeXnes.Core
|
||||||
{
|
{
|
||||||
SettingsFile.SetValue("rpc","RpcAutoStart", Convert.ToString(Globals.settings_RpcAutoStart.Value));
|
SettingsFile.SetValue("rpc","RpcAutoStart", Convert.ToString(Globals.settings_RpcAutoStart.Value));
|
||||||
};
|
};
|
||||||
Globals.settings_builtInCSGORpc.ValueChanged += () =>
|
|
||||||
{
|
|
||||||
SettingsFile.SetValue("rpc","csgoPresence", Convert.ToString(Globals.settings_builtInCSGORpc.Value));
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ using System.Windows.Navigation;
|
||||||
using System.Windows.Shapes;
|
using System.Windows.Shapes;
|
||||||
using WeeXnes.Core;
|
using WeeXnes.Core;
|
||||||
using WeeXnes.RPC;
|
using WeeXnes.RPC;
|
||||||
using WeeXnes.RPC.CSGO;
|
|
||||||
|
|
||||||
namespace WeeXnes.MVVM.View
|
namespace WeeXnes.MVVM.View
|
||||||
{
|
{
|
||||||
|
@ -102,7 +101,7 @@ namespace WeeXnes.MVVM.View
|
||||||
|
|
||||||
private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
|
private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
|
||||||
{
|
{
|
||||||
CSGORPC csrpc = new CSGORPC("777202324145438812");
|
|
||||||
Globals.info_isRpcRunning = true;
|
Globals.info_isRpcRunning = true;
|
||||||
writeLog(new customEvent("Thread Started", EventType.ProcessStartedEvent));
|
writeLog(new customEvent("Thread Started", EventType.ProcessStartedEvent));
|
||||||
bool runWorker = true;
|
bool runWorker = true;
|
||||||
|
@ -118,18 +117,12 @@ namespace WeeXnes.MVVM.View
|
||||||
{
|
{
|
||||||
game.stop();
|
game.stop();
|
||||||
}
|
}
|
||||||
csrpc.stop();
|
|
||||||
}
|
}
|
||||||
Process[] processes = Process.GetProcesses();
|
Process[] processes = Process.GetProcesses();
|
||||||
foreach (Game game in Games)
|
foreach (Game game in Games)
|
||||||
{
|
{
|
||||||
game.checkState(processes);
|
game.checkState(processes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Globals.settings_builtInCSGORpc.Value)
|
|
||||||
{
|
|
||||||
csrpc.checkState(processes);
|
|
||||||
}
|
|
||||||
Thread.Sleep(delay);
|
Thread.Sleep(delay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,28 +124,6 @@
|
||||||
|
|
||||||
</CheckBox>
|
</CheckBox>
|
||||||
|
|
||||||
<CheckBox VerticalAlignment="Top"
|
|
||||||
VerticalContentAlignment="Center"
|
|
||||||
HorizontalContentAlignment="Center"
|
|
||||||
Name="EnableBuiltInCSGO"
|
|
||||||
Checked="EnableBuiltInCSGO_OnChecked"
|
|
||||||
Unchecked="EnableBuiltInCSGO_OnUnchecked"
|
|
||||||
Margin="10,10,0,0">
|
|
||||||
<TextBlock
|
|
||||||
Text="Enable Built in CSGO DiscordRPC"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
FontSize="15"
|
|
||||||
Foreground="White"/>
|
|
||||||
|
|
||||||
|
|
||||||
</CheckBox>
|
|
||||||
<Button Name="InstallCSGORPC"
|
|
||||||
Style="{StaticResource UniversalMaterialButton}"
|
|
||||||
Content="Install Required File for CSGO DiscordRPC"
|
|
||||||
Background="#2f313b"
|
|
||||||
Height="25"
|
|
||||||
Click="InstallCSGORPC_OnClick"
|
|
||||||
Margin="4,10,4,0"/>
|
|
||||||
|
|
||||||
<Label Content="Default RPC ClientID:"
|
<Label Content="Default RPC ClientID:"
|
||||||
Margin="0,0,0,0"
|
Margin="0,0,0,0"
|
||||||
|
|
|
@ -92,10 +92,6 @@ namespace WeeXnes.MVVM.View
|
||||||
CensorKeysSwitch.IsChecked = true;
|
CensorKeysSwitch.IsChecked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Globals.settings_builtInCSGORpc.Value)
|
|
||||||
{
|
|
||||||
EnableBuiltInCSGO.IsChecked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
tb_DefaultClientID.Text = Globals.settings_RpcDefaultClientID.Value;
|
tb_DefaultClientID.Text = Globals.settings_RpcDefaultClientID.Value;
|
||||||
}
|
}
|
||||||
|
@ -347,36 +343,7 @@ namespace WeeXnes.MVVM.View
|
||||||
Globals.settings_osxStyleControlls.Value = false;
|
Globals.settings_osxStyleControlls.Value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EnableBuiltInCSGO_OnChecked(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
Globals.settings_builtInCSGORpc.Value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void EnableBuiltInCSGO_OnUnchecked(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
Globals.settings_builtInCSGORpc.Value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InstallCSGORPC_OnClick(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
using(var fbd = new FolderBrowserDialog())
|
|
||||||
{
|
|
||||||
DialogResult result = fbd.ShowDialog();
|
|
||||||
|
|
||||||
if (result == DialogResult.OK && !string.IsNullOrWhiteSpace(fbd.SelectedPath))
|
|
||||||
{
|
|
||||||
string subDir = @"csgo\cfg";
|
|
||||||
string filepath = Path.Combine(fbd.SelectedPath, subDir) + "\\gamestate_integration_jrpc.cfg";
|
|
||||||
string content = "\"CSGSI\" { \"uri\" \"http://localhost:4169\" \"timeout\" \"5.0\" \"data\" { \"provider\" \"1\" \"map\" \"1\" \"round\" \"1\" \"player_id\" \"1\" \"player_weapons\" \"1\" \"player_match_stats\" \"1\" \"player_state\" \"1\" } }";
|
|
||||||
if (!File.Exists(filepath))
|
|
||||||
{
|
|
||||||
using (StreamWriter sw = File.CreateText(filepath))
|
|
||||||
{
|
|
||||||
sw.WriteLine(content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -177,10 +177,6 @@ namespace WeeXnes
|
||||||
private void Window_Closing(object sender, CancelEventArgs e)
|
private void Window_Closing(object sender, CancelEventArgs e)
|
||||||
{
|
{
|
||||||
trayIcon.Dispose();
|
trayIcon.Dispose();
|
||||||
if (Globals.gameStateListener.Running)
|
|
||||||
{
|
|
||||||
Globals.gameStateListener.Stop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,195 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using CSGSI;
|
|
||||||
using CSGSI.Nodes;
|
|
||||||
using WeeXnes.Core;
|
|
||||||
using WeeXnes.MVVM.View;
|
|
||||||
using DiscordRPC;
|
|
||||||
using DiscordRPC.Message;
|
|
||||||
using EventType = WeeXnes.Core.EventType;
|
|
||||||
|
|
||||||
namespace WeeXnes.RPC.CSGO
|
|
||||||
{
|
|
||||||
class EventCache
|
|
||||||
{
|
|
||||||
public static string cache1 = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CSGORPC
|
|
||||||
{
|
|
||||||
|
|
||||||
public DiscordRpcClient client { get; set; }
|
|
||||||
public string ProcessName { get; set; }
|
|
||||||
public bool isRunning { get; set; }
|
|
||||||
public CSGORPC(string ClientID)
|
|
||||||
{
|
|
||||||
this.ProcessName = "csgo";
|
|
||||||
this.client = new DiscordRpcClient(ClientID);
|
|
||||||
Globals.gameStateListener.NewGameState += GameStateListenerOnNewGameState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GameStateListenerOnNewGameState(GameState gs)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (gs.Player.Activity == PlayerActivity.Menu)
|
|
||||||
{
|
|
||||||
this.client.UpdateLargeAsset("csgo_icon");
|
|
||||||
this.client.UpdateDetails("In Menu");
|
|
||||||
this.client.UpdateState("");
|
|
||||||
this.client.UpdateSmallAsset("");
|
|
||||||
}
|
|
||||||
else if (gs.Player.Activity == PlayerActivity.Playing)
|
|
||||||
{
|
|
||||||
if (gs.Map.Mode == MapMode.ScrimComp2v2)
|
|
||||||
{
|
|
||||||
this.client.UpdateDetails("Playing Wingman");
|
|
||||||
}
|
|
||||||
else if (gs.Map.Mode == MapMode.GunGameProgressive)
|
|
||||||
{
|
|
||||||
this.client.UpdateDetails("Playing Gun Game");
|
|
||||||
}
|
|
||||||
else if (gs.Map.Mode == MapMode.GunGameTRBomb)
|
|
||||||
{
|
|
||||||
this.client.UpdateDetails("Playing Demolition");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.client.UpdateDetails("Playing " + gs.Map.Mode);
|
|
||||||
}
|
|
||||||
this.client.UpdateState("on " + gs.Map.Name);
|
|
||||||
|
|
||||||
this.client.UpdateLargeAsset(gs.Map.Name);
|
|
||||||
if (gs.Player.Team == PlayerTeam.T)
|
|
||||||
{
|
|
||||||
|
|
||||||
this.client.UpdateLargeAsset(gs.Map.Name, "T: " + gs.Map.TeamT.Score + " - CT: " + gs.Map.TeamCT.Score);
|
|
||||||
this.client.UpdateSmallAsset("t_logo", Convert.ToString("Kills: " + gs.Player.MatchStats.Kills + " | Deaths: " + gs.Player.MatchStats.Deaths));
|
|
||||||
}else if(gs.Player.Team == PlayerTeam.CT)
|
|
||||||
{
|
|
||||||
this.client.UpdateLargeAsset(gs.Map.Name, "CT: " + gs.Map.TeamCT.Score + " - T: " + gs.Map.TeamT.Score);
|
|
||||||
this.client.UpdateSmallAsset("ct_logo", Convert.ToString("Kills: " + gs.Player.MatchStats.Kills + " | Deaths: " + gs.Player.MatchStats.Deaths));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.client.UpdateSmallAsset("");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void start()
|
|
||||||
{
|
|
||||||
|
|
||||||
Globals.gameStateListener.Start();
|
|
||||||
if (!client.IsInitialized)
|
|
||||||
{
|
|
||||||
client.Initialize();
|
|
||||||
}
|
|
||||||
client.OnReady += ClientOnOnReady;
|
|
||||||
client.OnPresenceUpdate += ClientOnOnPresenceUpdate;
|
|
||||||
client.SetPresence(new RichPresence()
|
|
||||||
{
|
|
||||||
Details = "Launching Game...",
|
|
||||||
State = "",
|
|
||||||
Assets = new Assets()
|
|
||||||
{
|
|
||||||
LargeImageKey = "csgo_icon",
|
|
||||||
LargeImageText = "",
|
|
||||||
SmallImageKey = "",
|
|
||||||
SmallImageText = ""
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (Globals.settings_RpcShowElapsedTime.Value)
|
|
||||||
{
|
|
||||||
client.UpdateStartTime();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ClientOnOnPresenceUpdate(object sender, PresenceMessage args)
|
|
||||||
{
|
|
||||||
DiscordRpcView.logContent = new customEvent("[" + this.ProcessName + ".exe] ➜ Received Update on " + args.Name, EventType.RPCUpdateEvent);
|
|
||||||
DiscordRpcView.triggerLogupdate.Value = "nlejgmolegjog";
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ClientOnOnReady(object sender, ReadyMessage args)
|
|
||||||
{
|
|
||||||
DiscordRpcView.logContent = new customEvent("[" + this.ProcessName + ".exe] ➜ Received Ready from user " + args.User.Username, EventType.RPCReadyEvent);
|
|
||||||
DiscordRpcView.triggerLogupdate.Value = "nlejgmolegjog";
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stop()
|
|
||||||
{
|
|
||||||
|
|
||||||
Globals.gameStateListener.Stop();
|
|
||||||
|
|
||||||
if (this.client.IsInitialized)
|
|
||||||
{
|
|
||||||
client.ClearPresence();
|
|
||||||
client.OnReady -= ClientOnOnReady;
|
|
||||||
client.OnPresenceUpdate -= ClientOnOnPresenceUpdate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void checkState(Process[] processes)
|
|
||||||
{
|
|
||||||
if(!String.IsNullOrEmpty(this.ProcessName))
|
|
||||||
{
|
|
||||||
bool foundProcess = false;
|
|
||||||
foreach (Process process in processes)
|
|
||||||
{
|
|
||||||
if (process.ProcessName == this.ProcessName)
|
|
||||||
{
|
|
||||||
foundProcess = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.isRunning)
|
|
||||||
{
|
|
||||||
if (foundProcess)
|
|
||||||
{
|
|
||||||
//Do when Process is launched
|
|
||||||
//message.running(this.ProcessName);
|
|
||||||
start();
|
|
||||||
|
|
||||||
/*
|
|
||||||
Globals.logContent.Value = output;
|
|
||||||
Globals.logUpdateTrigger.Value = "mjfgoklemkgoeg";
|
|
||||||
*/
|
|
||||||
DiscordRpcView.logContent = new customEvent("↪ " + "CSGO" + " [" + this.ProcessName + ".exe] started", EventType.ProcessStartedEvent);
|
|
||||||
DiscordRpcView.triggerLogupdate.Value = "nlejgmolegjog";
|
|
||||||
this.isRunning = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.isRunning)
|
|
||||||
{
|
|
||||||
if (!foundProcess)
|
|
||||||
{
|
|
||||||
//Do when Process is closed
|
|
||||||
//message.closed(this.ProcessName);
|
|
||||||
stop();
|
|
||||||
/*
|
|
||||||
Globals.logContent.Value = output;
|
|
||||||
Globals.logUpdateTrigger.Value = "mjfgoklemkgoeg";
|
|
||||||
*/
|
|
||||||
DiscordRpcView.logContent = new customEvent( "↩ " + "CSGO" + " [" + this.ProcessName + ".exe] closed", EventType.ProcessStoppedEvent);
|
|
||||||
DiscordRpcView.triggerLogupdate.Value = "nlejgmolegjog";
|
|
||||||
|
|
||||||
this.isRunning = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return "CSGO";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -35,9 +35,6 @@
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="CSGSI, Version=1.3.1.0, Culture=neutral, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\packages\CSGSI.1.3.1\lib\CSGSI.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="DiscordRPC, Version=1.0.175.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="DiscordRPC, Version=1.0.175.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\DiscordRichPresence.1.0.175\lib\net35\DiscordRPC.dll</HintPath>
|
<HintPath>..\packages\DiscordRichPresence.1.0.175\lib\net35\DiscordRPC.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
@ -67,7 +64,6 @@
|
||||||
<Compile Include="Misc\UpdateMessage.xaml.cs">
|
<Compile Include="Misc\UpdateMessage.xaml.cs">
|
||||||
<DependentUpon>UpdateMessage.xaml</DependentUpon>
|
<DependentUpon>UpdateMessage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="RPC\CSGO.cs" />
|
|
||||||
<Compile Include="RPC\Game.cs" />
|
<Compile Include="RPC\Game.cs" />
|
||||||
<Page Include="MainWindow.xaml">
|
<Page Include="MainWindow.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="CSGSI" version="1.3.1" targetFramework="net48" />
|
|
||||||
<package id="DiscordRichPresence" version="1.0.175" targetFramework="net48" />
|
<package id="DiscordRichPresence" version="1.0.175" targetFramework="net48" />
|
||||||
<package id="Newtonsoft.Json" version="12.0.2" targetFramework="net48" />
|
<package id="Newtonsoft.Json" version="12.0.2" targetFramework="net48" />
|
||||||
</packages>
|
</packages>
|
Loading…
Add table
Reference in a new issue