Add CLI Tool

This commit is contained in:
CreepyCrafter24 2020-03-24 20:53:23 +01:00
parent af4b9238be
commit 023f452b26
28 changed files with 1039 additions and 408 deletions

22
CLI.md Normal file
View File

@ -0,0 +1,22 @@
# CLI
Updating the cache: uptool update
Installing a package: uptool install <package>
Upgrading a package: uptool upgrade <package>
Reinstalling a package: uptool reinstall <package>
Removing a package: uptool remove <package>
Removing a package and all its configuration and data files: uptool purge <package>
List installed packages: uptool list
Upgrade all packages: uptool dist-upgrade
Search for a package: uptool search <text>
Show package info: uptool show <package>

View File

@ -16,7 +16,7 @@ Now you can add this\
as a PostBuild event to automatically run pkgtool. Customize this if you need to.\
For GitHub actions I wrote [this](https://github.com/JFronny/CC-Clicker/blob/master/.github/workflows/main.yml).\
If you copy it, make sure to replace the descriptions and ID under the `Fenerate XML` step\
You can also add something like this to your Readme: [![UpTool2](https://img.shields.io/badge/dynamic/xml?color=informational&label=UpTool2&query=%2F%2Fapp%2FVersion&url=https%3A%2F%2Fgithub.com%2FJFronny%2FCC-Clicker%2Freleases%2Fdownload%2F1.0.7380.28108%2Fapp.xml&style=flat)](https://jfronny.github.io/home/uptool)\
You can also add something like this to your Readme: [![UpTool2](https://img.shields.io/github/v/tag/JFronny/CC-Clicker?color=informational&label=UpTool2)](https://jfronny.github.io/home/uptool)\
(Look at the source for the MD Code)
## Folder layout
- %APPDATA%\UpTool2

View File

@ -14,7 +14,7 @@
<ApplicationIcon>..\UpTool2.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CC-Functions.Misc" Version="1.1.7384.27745" />
<PackageReference Include="System.CommandLine" Version="2.0.0-beta1.20104.2" />
<PackageReference Include="CC-Functions.Misc" Version="1.1.7388.28729" />
<PackageReference Include="System.CommandLine" Version="2.0.0-beta1.20158.1" />
</ItemGroup>
</Project>

View File

@ -10,12 +10,17 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
.gitignore = .gitignore
.github\workflows\main.yml = .github\workflows\main.yml
README.md = README.md
CLI.md = CLI.md
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UpTool build tool", "UpTool build tool\UpTool build tool.csproj", "{AAB8D6BA-3A43-4DC4-95EE-6757482B77FD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Installer", "Installer\Installer.csproj", "{1D273392-3796-4BE9-A67F-BB402315D52D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpToolLib", "UpToolLib\UpToolLib.csproj", "{FACD621F-6C6D-4D4B-B322-4364A0F9B4C2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpToolCLI", "UpToolCLI\UpToolCLI.csproj", "{3EC369B9-D927-4A53-BE1A-7E7006081BCE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -34,6 +39,14 @@ Global
{1D273392-3796-4BE9-A67F-BB402315D52D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1D273392-3796-4BE9-A67F-BB402315D52D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1D273392-3796-4BE9-A67F-BB402315D52D}.Release|Any CPU.Build.0 = Release|Any CPU
{FACD621F-6C6D-4D4B-B322-4364A0F9B4C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FACD621F-6C6D-4D4B-B322-4364A0F9B4C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FACD621F-6C6D-4D4B-B322-4364A0F9B4C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FACD621F-6C6D-4D4B-B322-4364A0F9B4C2}.Release|Any CPU.Build.0 = Release|Any CPU
{3EC369B9-D927-4A53-BE1A-7E7006081BCE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3EC369B9-D927-4A53-BE1A-7E7006081BCE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3EC369B9-D927-4A53-BE1A-7E7006081BCE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3EC369B9-D927-4A53-BE1A-7E7006081BCE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -29,7 +29,8 @@
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
System.ComponentModel.ComponentResourceManager resources =
new System.ComponentModel.ComponentResourceManager(typeof(UpTool2.MainForm));
this.sidebarPanel = new System.Windows.Forms.FlowLayoutPanel();
this.infoPanel = new System.Windows.Forms.Panel();
this.action_run = new System.Windows.Forms.Button();
@ -48,15 +49,12 @@
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this.searchPackageDialog = new System.Windows.Forms.OpenFileDialog();
this.infoPanel.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
((System.ComponentModel.ISupportInitialize) (this.splitContainer)).BeginInit();
this.splitContainer.Panel1.SuspendLayout();
this.splitContainer.Panel2.SuspendLayout();
this.splitContainer.SuspendLayout();
this.optionsPanel.SuspendLayout();
this.SuspendLayout();
//
// sidebarPanel
//
this.sidebarPanel.AutoScroll = true;
this.sidebarPanel.BackColor = System.Drawing.SystemColors.ControlLight;
this.sidebarPanel.Dock = System.Windows.Forms.DockStyle.Fill;
@ -64,9 +62,6 @@
this.sidebarPanel.Name = "sidebarPanel";
this.sidebarPanel.Size = new System.Drawing.Size(312, 451);
this.sidebarPanel.TabIndex = 0;
//
// infoPanel
//
this.infoPanel.Controls.Add(this.action_run);
this.infoPanel.Controls.Add(this.action_remove);
this.infoPanel.Controls.Add(this.action_update);
@ -78,10 +73,9 @@
this.infoPanel.Name = "infoPanel";
this.infoPanel.Size = new System.Drawing.Size(616, 519);
this.infoPanel.TabIndex = 1;
//
// action_run
//
this.action_run.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.action_run.Anchor =
((System.Windows.Forms.AnchorStyles) ((System.Windows.Forms.AnchorStyles.Top |
System.Windows.Forms.AnchorStyles.Right)));
this.action_run.Location = new System.Drawing.Point(491, 6);
this.action_run.Name = "action_run";
this.action_run.Size = new System.Drawing.Size(27, 27);
@ -89,10 +83,9 @@
this.action_run.Text = "↗";
this.action_run.UseVisualStyleBackColor = true;
this.action_run.Click += new System.EventHandler(this.Action_run_Click);
//
// action_remove
//
this.action_remove.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.action_remove.Anchor =
((System.Windows.Forms.AnchorStyles) ((System.Windows.Forms.AnchorStyles.Top |
System.Windows.Forms.AnchorStyles.Right)));
this.action_remove.Enabled = false;
this.action_remove.Location = new System.Drawing.Point(523, 6);
this.action_remove.Name = "action_remove";
@ -101,10 +94,9 @@
this.action_remove.Text = "🗑";
this.action_remove.UseVisualStyleBackColor = true;
this.action_remove.Click += new System.EventHandler(this.Action_remove_Click);
//
// action_update
//
this.action_update.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.action_update.Anchor =
((System.Windows.Forms.AnchorStyles) ((System.Windows.Forms.AnchorStyles.Top |
System.Windows.Forms.AnchorStyles.Right)));
this.action_update.Enabled = false;
this.action_update.Location = new System.Drawing.Point(554, 6);
this.action_update.Name = "action_update";
@ -113,10 +105,9 @@
this.action_update.Text = "⭱";
this.action_update.UseVisualStyleBackColor = true;
this.action_update.Click += new System.EventHandler(this.Action_update_Click);
//
// action_install
//
this.action_install.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.action_install.Anchor =
((System.Windows.Forms.AnchorStyles) ((System.Windows.Forms.AnchorStyles.Top |
System.Windows.Forms.AnchorStyles.Right)));
this.action_install.Enabled = false;
this.action_install.Location = new System.Drawing.Point(586, 6);
this.action_install.Name = "action_install";
@ -125,37 +116,23 @@
this.action_install.Text = "⭳";
this.action_install.UseVisualStyleBackColor = true;
this.action_install.Click += new System.EventHandler(this.Action_install_Click);
//
// infoPanel_Description
//
this.infoPanel_Description.Location = new System.Drawing.Point(3, 51);
this.infoPanel_Description.Name = "infoPanel_Description";
this.infoPanel_Description.Size = new System.Drawing.Size(611, 458);
this.infoPanel_Description.TabIndex = 1;
//
// infoPanel_Title
//
this.infoPanel_Title.AutoSize = true;
this.infoPanel_Title.Font = new System.Drawing.Font("Microsoft Sans Serif", 20.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.infoPanel_Title.Font = new System.Drawing.Font("Microsoft Sans Serif", 20.25F,
System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.infoPanel_Title.Location = new System.Drawing.Point(2, 1);
this.infoPanel_Title.Name = "infoPanel_Title";
this.infoPanel_Title.Size = new System.Drawing.Size(0, 31);
this.infoPanel_Title.TabIndex = 0;
//
// splitContainer
//
this.splitContainer.Dock = System.Windows.Forms.DockStyle.Fill;
this.splitContainer.Location = new System.Drawing.Point(0, 0);
this.splitContainer.Name = "splitContainer";
//
// splitContainer.Panel1
//
this.splitContainer.Panel1.Controls.Add(this.sidebarPanel);
this.splitContainer.Panel1.Controls.Add(this.optionsPanel);
this.splitContainer.Panel1MinSize = 160;
//
// splitContainer.Panel2
//
this.splitContainer.Panel2.Controls.Add(this.infoPanel);
this.splitContainer.Panel2MinSize = 160;
this.splitContainer.Size = new System.Drawing.Size(933, 519);
@ -163,9 +140,6 @@
this.splitContainer.SplitterWidth = 5;
this.splitContainer.TabIndex = 0;
this.splitContainer.TabStop = false;
//
// optionsPanel
//
this.optionsPanel.Controls.Add(this.controls_upload);
this.optionsPanel.Controls.Add(this.filterBox);
this.optionsPanel.Controls.Add(this.searchBox);
@ -176,10 +150,9 @@
this.optionsPanel.Name = "optionsPanel";
this.optionsPanel.Size = new System.Drawing.Size(312, 68);
this.optionsPanel.TabIndex = 0;
//
// controls_upload
//
this.controls_upload.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.controls_upload.Anchor =
((System.Windows.Forms.AnchorStyles) ((System.Windows.Forms.AnchorStyles.Top |
System.Windows.Forms.AnchorStyles.Right)));
this.controls_upload.Location = new System.Drawing.Point(284, 6);
this.controls_upload.Name = "controls_upload";
this.controls_upload.Size = new System.Drawing.Size(27, 27);
@ -187,11 +160,10 @@
this.controls_upload.Text = "↑";
this.controls_upload.UseVisualStyleBackColor = true;
this.controls_upload.Click += new System.EventHandler(this.controls_upload_Click);
//
// filterBox
//
this.filterBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.filterBox.Anchor =
((System.Windows.Forms.AnchorStyles) (((System.Windows.Forms.AnchorStyles.Top |
System.Windows.Forms.AnchorStyles.Left) |
System.Windows.Forms.AnchorStyles.Right)));
this.filterBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.filterBox.FormattingEnabled = true;
this.filterBox.Location = new System.Drawing.Point(68, 7);
@ -199,19 +171,15 @@
this.filterBox.Size = new System.Drawing.Size(209, 23);
this.filterBox.TabIndex = 3;
this.filterBox.SelectedIndexChanged += new System.EventHandler(this.UpdateSidebarV);
//
// searchBox
//
this.searchBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.searchBox.Anchor =
((System.Windows.Forms.AnchorStyles) (((System.Windows.Forms.AnchorStyles.Bottom |
System.Windows.Forms.AnchorStyles.Left) |
System.Windows.Forms.AnchorStyles.Right)));
this.searchBox.Location = new System.Drawing.Point(3, 38);
this.searchBox.Name = "searchBox";
this.searchBox.Size = new System.Drawing.Size(307, 23);
this.searchBox.TabIndex = 2;
this.searchBox.TextChanged += new System.EventHandler(this.UpdateSidebarV);
//
// controls_settings
//
this.controls_settings.Location = new System.Drawing.Point(3, 6);
this.controls_settings.Name = "controls_settings";
this.controls_settings.Size = new System.Drawing.Size(27, 27);
@ -219,9 +187,6 @@
this.controls_settings.Text = "⚙";
this.controls_settings.UseVisualStyleBackColor = true;
this.controls_settings.Click += new System.EventHandler(this.Controls_settings_Click);
//
// controls_reload
//
this.controls_reload.Location = new System.Drawing.Point(34, 6);
this.controls_reload.Name = "controls_reload";
this.controls_reload.Size = new System.Drawing.Size(27, 27);
@ -229,26 +194,17 @@
this.controls_reload.Text = "↻";
this.controls_reload.UseVisualStyleBackColor = true;
this.controls_reload.Click += new System.EventHandler(this.Controls_reload_Click);
//
// toolTip
//
this.toolTip.AutoPopDelay = 5000;
this.toolTip.InitialDelay = 300;
this.toolTip.ReshowDelay = 100;
this.toolTip.ShowAlways = true;
//
// searchPackageDialog
//
this.searchPackageDialog.Filter = "Packages (*.zip)|*.zip";
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(933, 519);
this.Controls.Add(this.splitContainer);
this.HelpButton = true;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Icon = ((System.Drawing.Icon) (resources.GetObject("$this.Icon")));
this.MinimumSize = new System.Drawing.Size(631, 269);
this.Name = "MainForm";
this.ShowIcon = false;
@ -258,12 +214,11 @@
this.infoPanel.PerformLayout();
this.splitContainer.Panel1.ResumeLayout(false);
this.splitContainer.Panel2.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit();
((System.ComponentModel.ISupportInitialize) (this.splitContainer)).EndInit();
this.splitContainer.ResumeLayout(false);
this.optionsPanel.ResumeLayout(false);
this.optionsPanel.PerformLayout();
this.ResumeLayout(false);
}
#endregion

View File

@ -5,9 +5,12 @@ using System.IO;
using System.IO.Compression;
using System.Reflection;
using System.Windows.Forms;
using UpTool2.DataStructures;
using UpTool2.Properties;
using UpTool2.Tool;
using UpToolLib;
using UpToolLib.DataStructures;
using UpToolLib.Tool;
#if DEBUG
using System.Threading;
using System.Linq;
@ -17,13 +20,12 @@ namespace UpTool2
{
public sealed partial class MainForm : Form
{
HelpEventHandler help;
private readonly HelpEventHandler _help;
public MainForm()
{
GlobalVariables.ReloadElements = ReloadElements;
InitializeComponent();
help = MainForm_HelpRequested;
HelpRequested += help;
_help = MainForm_HelpRequested;
HelpRequested += _help;
filterBox.DataSource = Enum.GetValues(typeof(Status));
if (Program.Online)
{
@ -52,13 +54,12 @@ namespace UpTool2
{
#endif
AppInstall.Install((App) action_install.Tag);
ReloadElements();
trying = false;
#if !DEBUG
}
catch (Exception e1)
{
if (!GlobalVariables.RelE)
throw;
trying = MessageBox.Show(e1.ToString(), "Install failed", MessageBoxButtons.RetryCancel) ==
DialogResult.Retry;
}
@ -70,29 +71,11 @@ namespace UpTool2
{
try
{
string app = ((App) action_remove.Tag).appPath;
string tmp = PathTool.tempPath;
if (Directory.Exists(tmp))
Directory.Delete(tmp, true);
Directory.CreateDirectory(tmp);
ZipFile.ExtractToDirectory(Path.Combine(app, "package.zip"), tmp);
Process.Start(new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = $"/C \"{Path.Combine(tmp, "Remove.bat")}\"",
WorkingDirectory = Path.Combine(app, "app"),
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
}).WaitForExit();
Directory.Delete(tmp, true);
Directory.Delete(app, true);
if (GlobalVariables.RelE)
ReloadElements();
AppExtras.Remove((App) action_remove.Tag, true);
ReloadElements();
}
catch (Exception e1)
{
if (!GlobalVariables.RelE)
throw;
MessageBox.Show(e1.ToString(), "Removal failed");
}
}
@ -115,8 +98,6 @@ namespace UpTool2
}
catch (Exception e1)
{
if (!GlobalVariables.RelE)
throw;
MessageBox.Show(e1.ToString(), "Install failed");
}
#endif
@ -145,13 +126,15 @@ namespace UpTool2
int availableUpdates = 0;
foreach (App app in GlobalVariables.Apps.Values)
{
Panel sidebarIcon = new Panel();
sidebarIcon.Tag = app;
sidebarIcon.BackColor = app.Color;
sidebarIcon.Size = new Size(70, 70);
sidebarIcon.BackgroundImage = app.Icon;
sidebarIcon.BackgroundImageLayout = ImageLayout.Stretch;
bool updatable = !app.Local && (app.status & Status.Updatable) == Status.Updatable;
Panel sidebarIcon = new Panel
{
Tag = app,
BackColor = app.Color,
Size = new Size(70, 70),
BackgroundImage = (Bitmap) app.Icon,
BackgroundImageLayout = ImageLayout.Stretch
};
bool updateable = !app.Local && (app.status & Status.Updatable) == Status.Updatable;
sidebarIcon.Click += (sender, e) =>
{
infoPanel_Title.Text = app.Name;
@ -162,39 +145,29 @@ namespace UpTool2
action_remove.Tag = app;
action_remove.Enabled = Directory.Exists(app.appPath);
action_update.Tag = app;
action_update.Enabled = updatable;
action_update.Enabled = updateable;
action_run.Tag = app;
action_run.Enabled = (app.status & Status.Installed) == Status.Installed && !app.Local && app.Runnable && Directory.Exists(app.appPath);
};
if (updatable)
if (updateable)
availableUpdates++;
toolTip.SetToolTip(sidebarIcon, app.Name);
sidebarPanel.Controls.Add(sidebarIcon);
}
UpdateSidebarV(null, null);
Text =
$"UpTool2 {(availableUpdates == 0 ? "(All up-to-date)" : $"({availableUpdates.ToString()} Updates)")}";
$"UpTool2 {(availableUpdates == 0 ? "(All up-to-date)" : $"({availableUpdates} Updates)")}";
}
private void Action_run_Click(object sender, EventArgs e)
{
string path = Path.Combine(((App) action_run.Tag).dataPath, ((App) action_run.Tag).MainFile);
try
{
Process.Start(
new ProcessStartInfo
{
FileName = path,
WorkingDirectory = ((App) action_run.Tag).dataPath
});
AppExtras.RunApp((App) action_run.Tag);
}
catch (Exception e1)
{
MessageBox.Show(e1
#if DEBUG
+ $"{Environment.NewLine}File was: {path}"
#endif
+ "Failed to start!");
MessageBox.Show($"{e1}Failed to start!");
}
}
@ -202,16 +175,13 @@ namespace UpTool2
{
try
{
GlobalVariables.RelE = false;
Action_remove_Click(sender, e);
Action_install_Click(sender, e);
AppExtras.Update((App) action_install.Tag);
}
catch (Exception e1)
{
MessageBox.Show(e1.ToString(), "Install failed");
}
ReloadElements();
GlobalVariables.RelE = true;
}
private void Controls_reload_Click(object sender, EventArgs e)
@ -252,15 +222,15 @@ namespace UpTool2
else
{
#endif
Enum.TryParse(filterBox.SelectedValue.ToString(), out Status status);
for (int i = 0; i < sidebarPanel.Controls.Count; i++)
{
Panel sidebarIcon = (Panel) sidebarPanel.Controls[i];
App app = (App) sidebarIcon.Tag;
sidebarIcon.Visible = app.Name.Contains(searchBox.Text) &&
((int) app.status & (int) (Program.Online ? status : Status.Installed)) != 0;
}
ClearSelection();
App[] apps = AppExtras.FindApps(searchBox.Text);
Enum.TryParse(filterBox.SelectedValue.ToString(), out Status status);
for (int i = 0; i < sidebarPanel.Controls.Count; i++)
{
Panel sidebarIcon = (Panel) sidebarPanel.Controls[i];
App app = (App) sidebarIcon.Tag;
sidebarIcon.Visible = apps.Contains(app) && ((int) app.status & (int) (Program.Online ? status : Status.Installed)) != 0;
}
ClearSelection();
#if DEBUG
}
#endif
@ -310,7 +280,7 @@ namespace UpTool2
private void MainForm_HelpRequested(object sender, HelpEventArgs hlpevent)
{
HelpRequested -= help;
HelpRequested -= _help;
try
{
DateTime buildTime = GetBuildDateTime(Assembly.GetExecutingAssembly());
@ -320,7 +290,7 @@ Build Date: {buildTime:dd.MM.yyyy}", "UpTool2");
}
finally
{
HelpRequested += help;
HelpRequested += _help;
hlpevent.Handled = true;
}
}

View File

@ -3,8 +3,6 @@ using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
@ -13,6 +11,9 @@ using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
using UpTool2.Tool;
using UpToolLib.Tool;
using CC_Functions.Misc;
using UpToolLib;
namespace UpTool2
{
@ -57,13 +58,14 @@ namespace UpTool2
#endif
hasHandle = true;
}
ExternalFunctionalityManager.Init(new UTLibFunctions());
SetSplash(1, "Initializing paths");
if (!Directory.Exists(PathTool.dir))
Directory.CreateDirectory(PathTool.dir);
FixXml();
SetSplash(2, "Performing checks");
string metaXml = XDocument.Load(PathTool.InfoXml).Element("meta").Element("UpdateSource").Value;
Online = Ping(metaXml);
Online = new Uri(metaXml).Ping();
if (Application.ExecutablePath != PathTool.GetRelative("Install", "UpTool2.dll"))
Splash.Invoke((Action)(() => MessageBox.Show(Splash, $"WARNING!{Environment.NewLine}Running from outside the install directory is not recommended!")));
if (!Directory.Exists(PathTool.GetRelative("Apps")))
@ -177,40 +179,7 @@ namespace UpTool2
{
try
{
if (!File.Exists(PathTool.InfoXml) || XDocument.Load(PathTool.InfoXml).Element("meta") == null)
new XElement("meta").Save(PathTool.InfoXml);
XDocument x = XDocument.Load(PathTool.InfoXml);
XElement meta = x.Element("meta");
if (meta.Element("UpdateSource") == null)
meta.Add(new XElement("UpdateSource"));
if (new[]
{
"",
"https://raw.githubusercontent.com/CreepyCrafter24/UpTool2/master/Meta.xml",
"https://raw.githubusercontent.com/JFronny/UpTool2/master/Meta.xml",
"https://gist.githubusercontent.com/JFronny/f1ccbba3d8a2f5862592bb29fdb612c4/raw/Meta.xml"
}
.Contains(meta.Element("UpdateSource").Value))
meta.Element("UpdateSource").Value =
"https://github.com/JFronny/UpTool2/releases/latest/download/meta.xml";
if (meta.Element("Repos") == null)
meta.Add(new XElement("Repos"));
if (meta.Element("Repos").Elements("Repo").Count() == 0)
meta.Element("Repos").Add(new XElement("Repo", new XElement("Name", "UpTool2 official Repo"),
new XElement("Link",
"https://gist.githubusercontent.com/JFronny/f1ccbba3d8a2f5862592bb29fdb612c4/raw/Repo.xml")));
meta.Element("Repos").Elements("Repo").Select(s => s.Element("Link"))
.Where(s => new[]
{
null, "https://github.com/JFronny/UpTool2/releases/download/Repo/Repo.xml",
"https://raw.githubusercontent.com/JFronny/UpTool2/master/Repo.xml"
}.Contains(s.Value))
.ToList().ForEach(s =>
s.Value =
"https://gist.githubusercontent.com/JFronny/f1ccbba3d8a2f5862592bb29fdb612c4/raw/Repo.xml");
if (meta.Element("LocalRepo") == null)
meta.Add(new XElement("LocalRepo"));
x.Save(PathTool.InfoXml);
XmlTool.FixXml();
}
catch (XmlException)
{
@ -263,21 +232,5 @@ namespace UpTool2
});
return false;
}
private static bool Ping(string url)
{
try
{
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);
request.Timeout = 3000;
request.AllowAutoRedirect = true;
using WebResponse response = request.GetResponse();
return true;
}
catch
{
return false;
}
}
}
}

View File

@ -1,6 +1,7 @@
using System.Windows.Forms;
using System.Xml.Linq;
using UpTool2.Tool;
using UpToolLib.Tool;
namespace UpTool2
{

View File

@ -1,177 +0,0 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net;
using System.Windows.Forms;
using System.Xml.Linq;
using CC_Functions.Misc;
using UpTool2.DataStructures;
using UpTool2.Properties;
namespace UpTool2.Tool
{
internal static class RepoManagement
{
public static void FetchRepos()
{
Program.FixXml();
XElement meta = XDocument.Load(PathTool.InfoXml).Element("meta");
List<XElement> tmpAppsList = new List<XElement>();
List<string> repArr = meta.Element("Repos").Elements("Repo").Select(s => s.Element("Link").Value).Distinct()
.ToList();
using (WebClient client = new WebClient())
{
int i = 0;
while (i < repArr.Count)
{
#if !DEBUG
try
{
#endif
XDocument repo = XDocument.Load(new Uri(repArr[i]).Unshorten().AbsoluteUri);
repArr.AddRange(repo.Element("repo").Elements("repolink").Select(s => s.Value)
.Where(s => !repArr.Contains(s)));
XElement[] tmp_apparray = repo.Element("repo").Elements("app").Where(app =>
!tmpAppsList.Any(a => a.Element("ID").Value == app.Element("ID").Value) ||
!tmpAppsList
.Where(a => a.Element("ID").Value == app.Element("ID").Value).Any(a =>
GetVer(a.Element("Version")) >= app.Element("Version").GetVer())).ToArray()
.Concat(repo.Element("repo").Elements("applink")
.Select(s => XDocument.Load(new Uri(s.Value).Unshorten().AbsoluteUri).Element("app")))
.ToArray();
for (int i1 = 0; i1 < tmp_apparray.Length; i1++)
{
XElement app = tmp_apparray[i1];
//"Sanity check"
Version.Parse(app.Element("Version").Value);
Guid.Parse(app.Element("ID").Value);
//Create XElement
tmpAppsList.Add(new XElement("App",
new XElement("Name", app.Element("Name").Value),
new XElement("Description", app.Element("Description").Value),
new XElement("Version", app.Element("Version").Value),
new XElement("ID", app.Element("ID").Value),
new XElement("File", app.Element("File").Value),
new XElement("Hash", app.Element("Hash").Value)
));
if (app.Element("MainFile") != null)
tmpAppsList.Last().Add(new XElement("MainFile", app.Element("MainFile").Value));
if (app.Element("Icon") != null)
try
{
//Scale Image and save as Base64
Image src = Image.FromStream(
client.OpenRead(new Uri(app.Element("Icon").Value).Unshorten()));
Bitmap dest = new Bitmap(70, 70);
dest.SetResolution(src.HorizontalResolution, src.VerticalResolution);
using (Graphics g = Graphics.FromImage(dest))
{
g.CompositingMode = CompositingMode.SourceCopy;
g.CompositingQuality = CompositingQuality.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
using ImageAttributes wrapMode = new ImageAttributes();
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
g.DrawImage(src, new Rectangle(0, 0, 70, 70), 0, 0, src.Width, src.Height,
GraphicsUnit.Pixel, wrapMode);
}
using MemoryStream ms = new MemoryStream();
dest.Save(ms, ImageFormat.Png);
tmpAppsList.Last()
.Add(new XElement("Icon", Convert.ToBase64String(ms.ToArray())));
}
catch
{
}
if (tmpAppsList.Count(a => a.Element("ID").Value == app.Element("ID").Value) > 1)
tmpAppsList.Where(a => a.Element("ID").Value == app.Element("ID").Value).Reverse()
.Skip(1)
.ToList().ForEach(a => tmpAppsList.Remove(a));
}
#if !DEBUG
}
catch (Exception e)
{
MessageBox.Show(e.ToString(), "Failed to load repo: " + repArr[i]);
}
#endif
i++;
}
}
tmpAppsList.Sort((x, y) =>
string.Compare(x.Element("Name").Value, y.Element("Name").Value, StringComparison.Ordinal));
if (meta.Element("LocalRepo") == null)
meta.Add(new XElement("LocalRepo"));
XElement repos = meta.Element("LocalRepo");
repos.RemoveNodes();
tmpAppsList.ForEach(app => repos.Add(app));
meta.Save(PathTool.InfoXml);
}
private static Version GetVer(this XElement el) =>
int.TryParse(el.Value, out int i) ? new Version(0, 0, 0, i) : Version.Parse(el.Value);
public static void GetReposFromDisk()
{
GlobalVariables.Apps.Clear();
string xml = PathTool.InfoXml;
XDocument.Load(xml).Element("meta").Element("LocalRepo").Elements().ToList().ForEach(app =>
{
Guid id = Guid.Parse(app.Element("ID").Value);
string locInPath = PathTool.GetInfoPath(id);
XElement locIn = File.Exists(locInPath) ? XDocument.Load(locInPath).Element("app") : app;
if (int.TryParse(app.Element("Version").Value, out _))
app.Element("Version").Value = GlobalVariables.minimumVer.ToString();
GlobalVariables.Apps.Add(id, new App(
locIn.Element("Name").Value,
locIn.Element("Description").Value,
Version.Parse(app.Element("Version").Value),
app.Element("File").Value,
false,
app.Element("Hash").Value,
id,
Color.White,
app.Element("Icon") == null
? Resources.C_64.ToBitmap()
: (Bitmap) new ImageConverter().ConvertFrom(
Convert.FromBase64String(app.Element("Icon").Value)),
locIn.Element("MainFile") != null || app.Element("MainFile") != null,
locIn.Element("MainFile") == null
? app.Element("MainFile") == null ? "" : app.Element("MainFile").Value
: locIn.Element("MainFile").Value
));
});
Directory.GetDirectories(PathTool.appsPath)
.Where(s => Guid.TryParse(Path.GetFileName(s), out Guid guid) &&
!GlobalVariables.Apps.ContainsKey(guid)).ToList().ForEach(s =>
{
Guid tmp = Guid.Parse(Path.GetFileName(s));
try
{
XElement data = XDocument.Load(PathTool.GetInfoPath(tmp)).Element("app");
GlobalVariables.Apps.Add(tmp,
new App("(local) " + data.Element("Name").Value, data.Element("Description").Value,
GlobalVariables.minimumVer, "", true, "", tmp, Color.Red, Resources.C_64.ToBitmap(),
data.Element("MainFile") != null,
data.Element("MainFile") == null ? "" : data.Element("MainFile").Value));
}
catch (Exception e)
{
if (MessageBox.Show($@"An error occured while loading this local repo:
{e.Message}
Do you want to exit? Otherwise the folder will be deleted, possibly causeing problems later.", "",
MessageBoxButtons.YesNo) == DialogResult.No)
Directory.Delete(PathTool.GetAppPath(tmp), true);
else
Environment.Exit(0);
}
});
}
}
}

55
UpTool2/UTLibFunctions.cs Normal file
View File

@ -0,0 +1,55 @@
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Net;
using System.Windows.Forms;
using UpTool2.Properties;
using UpTool2.Tool;
using UpToolLib;
using UpToolLib.DataStructures;
namespace UpTool2
{
class UTLibFunctions : IExternalFunctionality
{
public Tuple<bool, byte[]> Download(Uri link)
{
using DownloadDialog dialog = new DownloadDialog(link.AbsoluteUri);
bool success = dialog.ShowDialog() == DialogResult.OK;
return new Tuple<bool, byte[]>(success, success ? dialog.Result : null);
}
public string FetchImageB64(Uri link)
{
using WebClient client = new WebClient();
Image src = Image.FromStream(
client.OpenRead(link));
Bitmap dest = new Bitmap(70, 70);
dest.SetResolution(src.HorizontalResolution, src.VerticalResolution);
using (Graphics g = Graphics.FromImage(dest))
{
g.CompositingMode = CompositingMode.SourceCopy;
g.CompositingQuality = CompositingQuality.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
using ImageAttributes wrapMode = new ImageAttributes();
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
g.DrawImage(src, new Rectangle(0, 0, 70, 70), 0, 0, src.Width, src.Height,
GraphicsUnit.Pixel, wrapMode);
}
using MemoryStream ms = new MemoryStream();
dest.Save(ms, ImageFormat.Png);
return Convert.ToBase64String(ms.ToArray());
}
public bool YesNoDialog(string text, bool _) => MessageBox.Show(text, "", MessageBoxButtons.YesNo) == DialogResult.Yes;
public void OKDialog(string text) => MessageBox.Show(text);
public object GetDefaultIcon() => Resources.C_64.ToBitmap();
public object ImageFromB64(string b64) => (Bitmap) new ImageConverter().ConvertFrom(Convert.FromBase64String(b64));
public void Log(string text) { }
}
}

View File

@ -19,6 +19,9 @@
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CC-Functions.Misc" Version="1.1.7384.27745" />
<PackageReference Include="CC-Functions.Misc" Version="1.1.7388.28729" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\UpToolLib\UpToolLib.csproj" />
</ItemGroup>
</Project>

225
UpToolCLI/Program.cs Normal file
View File

@ -0,0 +1,225 @@
using System;
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Linq;
using UpToolLib;
using UpToolLib.DataStructures;
using UpToolLib.Tool;
namespace UpToolCLI
{
public class Program
{
public static int Main(string[] args)
{
ExternalFunctionalityManager.Init(new UTLibFunctions());
RootCommand rootCommand = new RootCommand();
rootCommand.AddCommand(new Command("update", "Updates the cache")
{
Handler = CommandHandler.Create(Update)
});
Command install = new Command("install", "Install a package")
{
Handler = CommandHandler.Create<string>(Install)
};
install.AddOption(new Option<string>(new[] { "--identifier", "-i" }, "Something to identify the app"));
rootCommand.AddCommand(install);
Command upgrade = new Command("upgrade", "Upgrade a package")
{
Handler = CommandHandler.Create<string>(Upgrade)
};
upgrade.AddOption(new Option<string>(new[] { "--identifier", "-i" }, "Something to identify the app"));
rootCommand.AddCommand(upgrade);
Command reinstall = new Command("reinstall", "Reinstall a package")
{
Handler = CommandHandler.Create<string>(Reinstall)
};
reinstall.AddOption(new Option<string>(new[] { "--identifier", "-i" }, "Something to identify the app"));
rootCommand.AddCommand(reinstall);
Command remove = new Command("remove", "Remove a package")
{
Handler = CommandHandler.Create<string>(Remove)
};
remove.AddOption(new Option<string>(new[] { "--identifier", "-i" }, "Something to identify the app"));
rootCommand.AddCommand(remove);
Command purge = new Command("purge", "Completely remove a package")
{
Handler = CommandHandler.Create<string>(Purge)
};
purge.AddOption(new Option<string>(new[] { "--identifier", "-i" }, "Something to identify the app"));
rootCommand.AddCommand(purge);
rootCommand.AddCommand(new Command("list", "Lists installed packages")
{
Handler = CommandHandler.Create(List)
});
rootCommand.AddCommand(new Command("dist-upgrade", "Upgrades all packages")
{
Handler = CommandHandler.Create(DistUpgrade)
});
Command search = new Command("search", "Search for packages")
{
Handler = CommandHandler.Create<string>(Search)
};
search.AddOption(new Option<string>(new[] { "--identifier", "-i" }, "Something to identify the app"));
rootCommand.AddCommand(search);
Command show = new Command("show", "Shows package info")
{
Handler = CommandHandler.Create<string>(Show)
};
show.AddOption(new Option<string>(new[] { "--identifier", "-i" }, "Something to identify the app"));
rootCommand.AddCommand(show);
return rootCommand.InvokeAsync(args).Result;
}
private static void Update()
{
Console.WriteLine("Fetching Repos...");
RepoManagement.FetchRepos();
Console.WriteLine("Done!");
}
private static void List()
{
RepoManagement.GetReposFromDisk();
foreach (KeyValuePair<Guid, App> app in GlobalVariables.Apps.Where(s => (s.Value.status & Status.Installed) == Status.Installed))
{
Console.BackgroundColor = (app.Value.status & Status.Local) == Status.Local ? ConsoleColor.DarkRed : ((app.Value.status & Status.Updatable) == Status.Updatable ? ConsoleColor.DarkGreen : ConsoleColor.Black);
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine($"{app.Value.Name} ({app.Key}");
}
Console.ResetColor();
}
private static void DistUpgrade()
{
RepoManagement.GetReposFromDisk();
foreach (KeyValuePair<Guid, App> app in GlobalVariables.Apps.Where(s => (s.Value.status & Status.Updatable) == Status.Updatable))
{
Console.WriteLine($"Updating {app.Value.Name}");
AppExtras.Update(app.Value);
}
}
private static void Show(string identifier)
{
RepoManagement.GetReposFromDisk();
App[] apps = AppExtras.FindApps(identifier);
if (apps.Length == 0)
Console.WriteLine("Package not found.");
else
Console.WriteLine(apps.First());
}
private static void Search(string identifier)
{
RepoManagement.GetReposFromDisk();
App[] apps = AppExtras.FindApps(identifier);
Console.WriteLine($"Found {apps.Length} app(s)");
for (int i = 0; i < apps.Length; i++)
Console.WriteLine($"{apps[i].Name} ({apps[i].Id}");
}
private static void Upgrade(string identifier)
{
RepoManagement.GetReposFromDisk();
App[] apps = AppExtras.FindApps(identifier);
if (apps.Length == 0)
Console.WriteLine("Package not found.");
else
{
App tmp = apps.First();
if ((tmp.status & Status.Updatable) == Status.Updatable)
{
Console.WriteLine($"Upgrading {tmp.Name}");
AppExtras.Update(tmp);
}
else
Console.WriteLine("Package is up-to-date");
}
}
private static void Reinstall(string identifier)
{
RepoManagement.GetReposFromDisk();
App[] apps = AppExtras.FindApps(identifier);
if (apps.Length == 0)
Console.WriteLine("Package not found.");
else
{
App tmp = apps.First();
Console.WriteLine($"Reinstalling {tmp.Name}");
AppExtras.Update(tmp);
}
}
private static void Remove(string identifier)
{
RepoManagement.GetReposFromDisk();
App[] apps = AppExtras.FindApps(identifier);
if (apps.Length == 0)
Console.WriteLine("Package not found.");
else
{
App tmp = apps.First();
if ((tmp.status & Status.Installed) == Status.Installed)
{
Console.WriteLine($"Removing {tmp.Name}");
AppExtras.Remove(tmp, false);
}
else
Console.WriteLine("Package is not installed");
}
}
private static void Purge(string identifier)
{
RepoManagement.GetReposFromDisk();
App[] apps = AppExtras.FindApps(identifier);
if (apps.Length == 0)
Console.WriteLine("Package not found.");
else
{
App tmp = apps.First();
if ((tmp.status & Status.Installed) == Status.Installed)
{
Console.WriteLine($"Purgeing {tmp.Name}");
AppExtras.Remove(tmp, true);
}
else
Console.WriteLine("Package is not installed");
}
}
private static void Install(string identifier)
{
RepoManagement.GetReposFromDisk();
App[] apps = AppExtras.FindApps(identifier);
if (apps.Length == 0)
Console.WriteLine("Package not found.");
else
{
App tmp = apps.First();
if ((tmp.status & Status.Installed) == Status.Installed)
Console.WriteLine("Package is already installed");
else
{
Console.WriteLine($"Installing {tmp.Name}");
AppInstall.Install(tmp);
}
}
}
}
}

View File

@ -0,0 +1,98 @@
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
using System;
using System.IO;
using System.Net;
using System.Threading;
using UpToolLib.DataStructures;
namespace UpToolCLI
{
public class UTLibFunctions : IExternalFunctionality
{
public Tuple<bool, byte[]> Download(Uri link)
{
using WebClient client = new WebClient();
byte[] result = new byte[0];
bool finished = false;
bool success = true;
client.DownloadDataCompleted += (sender, e) =>
{
success = !e.Cancelled;
if (success)
result = e.Result;
finished = true;
};
client.DownloadProgressChanged += (sender, e) =>
{
Console.Write($"{new string('=', e.ProgressPercentage / 10)}[{e.ProgressPercentage}]{new string('-', 10 - e.ProgressPercentage / 10)}");
Console.CursorLeft = 0;
};
client.DownloadDataAsync(link);
while (!finished)
Thread.Sleep(100);
return new Tuple<bool, byte[]>(success, result);
}
public string FetchImageB64(Uri link)
{
using WebClient client = new WebClient();
using Image image = Image.Load(client.OpenRead(link));
image.Mutate(x => x.Resize(70, 70));
using MemoryStream ms = new MemoryStream();
image.SaveAsPng(ms);
return Convert.ToBase64String(ms.ToArray());
}
public bool YesNoDialog(string text, bool defaultVal)
{
bool choosing = true;
bool current = defaultVal;
Console.WriteLine(text);
while (choosing)
{
Console.CursorLeft = 0;
Console.BackgroundColor = current ? ConsoleColor.White : ConsoleColor.Black;
Console.ForegroundColor = current ? ConsoleColor.Black : ConsoleColor.White;
Console.Write("Yes");
Console.ResetColor();
Console.Write(" ");
Console.BackgroundColor = current ? ConsoleColor.Black : ConsoleColor.White;
Console.ForegroundColor = current ? ConsoleColor.White : ConsoleColor.Black;
Console.Write("No");
Console.ResetColor();
switch (Console.ReadKey().Key)
{
case ConsoleKey.LeftArrow:
case ConsoleKey.RightArrow:
current = !current;
break;
case ConsoleKey.Enter:
choosing = false;
break;
case ConsoleKey.Escape:
current = defaultVal;
choosing = false;
break;
}
}
Console.ResetColor();
Console.WriteLine($" Selecting: {current}");
return current;
}
public void OKDialog(string text)
{
Console.WriteLine(text);
Console.BackgroundColor = ConsoleColor.White;
Console.Write("OK");
Console.ResetColor();
Console.ReadKey();
}
public object GetDefaultIcon() => 0;
public object ImageFromB64(string b64) => 0;
public void Log(string text) => Console.WriteLine(text);
}
}

View File

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AssemblyName>uptool</AssemblyName>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.0-beta0007" />
<PackageReference Include="System.CommandLine" Version="2.0.0-beta1.20158.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\UpToolLib\UpToolLib.csproj" />
</ItemGroup>
</Project>

View File

@ -3,10 +3,10 @@ using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Xml.Linq;
using UpTool2.Tool;
using UpToolLib.Tool;
using static System.Environment;
namespace UpTool2.DataStructures
namespace UpToolLib.DataStructures
{
public struct App : IEquatable<App>
{
@ -16,14 +16,14 @@ namespace UpTool2.DataStructures
public readonly string File;
public readonly bool Local;
public readonly string Hash;
private Guid _id;
public readonly Guid Id;
public Color Color;
public readonly Image Icon;
public readonly object Icon;
public readonly bool Runnable;
public readonly string MainFile;
public App(string name, string description, Version version, string file, bool local, string hash, Guid iD,
Color color, Image icon, bool runnable, string mainFile)
Color color, object icon, bool runnable, string mainFile)
{
Name = name ?? throw new ArgumentNullException(nameof(name));
Description = description ?? throw new ArgumentNullException(nameof(description));
@ -31,7 +31,7 @@ namespace UpTool2.DataStructures
File = file ?? throw new ArgumentNullException(nameof(file));
Local = local;
Hash = hash ?? throw new ArgumentNullException(nameof(hash));
_id = iD;
Id = iD;
Color = color;
Icon = icon ?? throw new ArgumentNullException(nameof(icon));
Runnable = runnable;
@ -53,30 +53,30 @@ namespace UpTool2.DataStructures
public override bool Equals(object obj) => obj is App app && Equals(app);
public bool Equals(App other) => _id.Equals(other._id);
public bool Equals(App other) => Id.Equals(other.Id);
public override int GetHashCode() => 1213502048 + EqualityComparer<Guid>.Default.GetHashCode(_id);
public override int GetHashCode() => 1213502048 + EqualityComparer<Guid>.Default.GetHashCode(Id);
public override string ToString() => $@"Name: {Name}
Description:
{string.Join(NewLine, Description.Split('\n').Select(s => { if (s.EndsWith("\r")) s.Remove(s.Length - 1, 1); return "> " + s; }))}
Version: {Version}
File: {File}
Local: {Local.ToString()}
Local: {Local}
Hash: {Hash}
ID: {_id.ToString()}
Color: {Color.ToKnownColor().ToString()}
ID: {Id}
Color: {Color.ToKnownColor()}
Runnable: {Runnable}
MainFile: {MainFile}
Status: {status.ToString()}
Status: {status}
Object Hash Code: {GetHashCode()}";
public static bool operator ==(App left, App right) => left.Equals(right);
public static bool operator !=(App left, App right) => !(left == right);
public string appPath => PathTool.GetAppPath(_id);
public string dataPath => PathTool.GetDataPath(_id);
public string infoPath => PathTool.GetInfoPath(_id);
public string appPath => PathTool.GetAppPath(Id);
public string dataPath => PathTool.GetDataPath(Id);
public string infoPath => PathTool.GetInfoPath(Id);
}
}

View File

@ -0,0 +1,15 @@
using System;
namespace UpToolLib.DataStructures
{
public interface IExternalFunctionality
{
public Tuple<bool, byte[]> Download(Uri link);
public string FetchImageB64(Uri link);
public bool YesNoDialog(string text, bool defaultVal);
public void OKDialog(string text);
public object GetDefaultIcon();
public object ImageFromB64(string b64);
public void Log(string text);
}
}

View File

@ -1,6 +1,6 @@
using System;
namespace UpTool2.DataStructures
namespace UpToolLib.DataStructures
{
[Flags]
public enum Status

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Text;
using UpToolLib.DataStructures;
namespace UpToolLib
{
public static class ExternalFunctionalityManager
{
internal static IExternalFunctionality instance;
public static void Init(IExternalFunctionality externalFunctionality) =>
instance = externalFunctionality;
}
}

View File

@ -1,14 +1,12 @@
using System;
using System.Collections.Generic;
using UpTool2.DataStructures;
using UpToolLib.DataStructures;
namespace UpTool2
namespace UpToolLib
{
internal static class GlobalVariables
public static class GlobalVariables
{
public static readonly Dictionary<Guid, App> Apps = new Dictionary<Guid, App>();
public static bool RelE = true;
public static Action ReloadElements;
public static Version minimumVer => Version.Parse("0.0.0.0");
}
}

View 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 UpToolLib.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", "16.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("UpToolLib.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

@ -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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using UpToolLib.DataStructures;
namespace UpToolLib.Tool
{
public static class AppExtras
{
public static Process RunApp(App app) =>
Process.Start(
new ProcessStartInfo
{
FileName = Path.Combine(app.dataPath, app.MainFile),
WorkingDirectory = app.dataPath
});
public static void Update(App app)
{
Remove(app, false);
AppInstall.Install(app);
}
public static void Remove(App app, bool deleteAll)
{
string tmp = PathTool.tempPath;
if (Directory.Exists(tmp))
Directory.Delete(tmp, true);
Directory.CreateDirectory(tmp);
ZipFile.ExtractToDirectory(Path.Combine(app.appPath, "package.zip"), tmp);
Process.Start(new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = $"/C \"{Path.Combine(tmp, "Remove.bat")}\"",
WorkingDirectory = Path.Combine(app.appPath, "app"),
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
}).WaitForExit();
if (!deleteAll) CheckDirecory(Path.Combine(tmp, "Data"), app.dataPath);
Directory.Delete(tmp, true);
if (File.Exists(app.infoPath))
File.Delete(app.infoPath);
if (File.Exists(Path.Combine(app.appPath, "package.zip")))
File.Delete(Path.Combine(app.appPath, "package.zip"));
if (deleteAll || Directory.GetFiles(app.dataPath).Length + Directory.GetDirectories(app.dataPath).Length == 0)
Directory.Delete(app.appPath, true);
}
private static void CheckDirecory(string tmp, string app)
{
foreach (string file in Directory.GetFiles(tmp)) File.Delete(Path.Combine(app, Path.GetFileName(file)));
foreach (string directory in Directory.GetDirectories(tmp))
CheckDirecory(directory, Path.Combine(app, Path.GetFileName(directory)));
if (Directory.GetFiles(app).Length + Directory.GetDirectories(app).Length == 0)
Directory.Delete(app);
}
public static App[] FindApps(string identifier)
{
Dictionary<Guid, App> tmp = GlobalVariables.Apps;
IEnumerable<KeyValuePair<Guid, App>> tmp1 = tmp.Where(s => s.Key.ToString().StartsWith(identifier));
tmp1 = tmp1.Concat(tmp.Where(s => s.Value.Name.Contains(identifier)));
tmp1 = tmp1.Concat(tmp.Where(s => s.Value.Description.Contains(identifier)));
return tmp1.Select(s => s.Value).ToArray();
}
}
}

View File

@ -3,14 +3,18 @@ using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Security.Cryptography;
using System.Windows.Forms;
using System.Xml.Linq;
using UpTool2.DataStructures;
using UpToolLib.DataStructures;
namespace UpTool2.Tool
namespace UpToolLib.Tool
{
internal static class AppInstall
public static class AppInstall
{
/// <summary>
/// Install an application
/// </summary>
/// <param name="appI">The app to install</param>
/// <param name="download">A method to download files. Input: app file, Outputs: whether the download was successful and the data</param>
public static void Install(App appI)
{
string app = "";
@ -27,19 +31,19 @@ namespace UpTool2.Tool
if (Directory.Exists(app))
Directory.Delete(app, true);
Directory.CreateDirectory(app);
using DownloadDialog dlg = new DownloadDialog(appI.File);
if (dlg.ShowDialog() != DialogResult.OK)
(bool dlSuccess, byte[] dlData) = ExternalFunctionalityManager.instance.Download(new Uri(appI.File));
if (!dlSuccess)
throw new Exception("Download failed");
using (SHA256CryptoServiceProvider sha256 = new SHA256CryptoServiceProvider())
{
string pkgHash = BitConverter.ToString(sha256.ComputeHash(dlg.Result)).Replace("-", string.Empty)
string pkgHash = BitConverter.ToString(sha256.ComputeHash(dlData)).Replace("-", string.Empty)
.ToUpper();
if (pkgHash != appI.Hash.ToUpper())
throw new Exception($@"The hash is not equal to the one stored in the repo:
Package: {pkgHash}
Online: {appI.Hash.ToUpper()}");
}
File.WriteAllBytes(Path.Combine(app, "package.zip"), dlg.Result);
File.WriteAllBytes(Path.Combine(app, "package.zip"), dlData);
CompleteInstall(appI);
#if !DEBUG
}
@ -110,8 +114,6 @@ Online: {appI.Hash.ToUpper()}");
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
}).WaitForExit();
if (GlobalVariables.RelE)
GlobalVariables.ReloadElements.Invoke();
}
}
}

View File

@ -2,9 +2,9 @@
using System.IO;
using System.Linq;
namespace UpTool2.Tool
namespace UpToolLib.Tool
{
internal static class PathTool
public static class PathTool
{
public static string dir =>
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "UpTool2");

View File

@ -0,0 +1,158 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Xml.Linq;
using CC_Functions.Misc;
using UpToolLib.DataStructures;
namespace UpToolLib.Tool
{
public static class RepoManagement
{
public static void FetchRepos()
{
XmlTool.FixXml();
XElement meta = XDocument.Load(PathTool.InfoXml).Element("meta");
List<XElement> tmpAppsList = new List<XElement>();
List<string> repArr = meta.Element("Repos").Elements("Repo").Select(s => s.Element("Link").Value).Distinct()
.ToList();
int i = 0;
while (i < repArr.Count)
{
#if !DEBUG
try
{
#endif
ExternalFunctionalityManager.instance.Log($"[{i + 1}] Loading {repArr[i]}");
XDocument repo = XDocument.Load(new Uri(repArr[i]).Unshorten().AbsoluteUri);
repArr.AddRange(repo.Element("repo").Elements("repolink").Select(s => s.Value)
.Where(s => !repArr.Contains(s)));
XElement[] tmp_apparray = repo.Element("repo").Elements("app").Where(app =>
!tmpAppsList.Any(a => a.Element("ID").Value == app.Element("ID").Value) ||
!tmpAppsList
.Where(a => a.Element("ID").Value == app.Element("ID").Value).Any(a =>
GetVer(a.Element("Version")) >= app.Element("Version").GetVer())).ToArray()
.Concat(repo.Element("repo").Elements("applink")
.Select(s =>
{
ExternalFunctionalityManager.instance.Log($"- Loading {s.Value}");
return XDocument.Load(new Uri(s.Value).Unshorten().AbsoluteUri).Element("app");
}))
.ToArray();
for (int i1 = 0; i1 < tmp_apparray.Length; i1++)
{
XElement app = tmp_apparray[i1];
//"Sanity check"
Version.Parse(app.Element("Version").Value);
Guid.Parse(app.Element("ID").Value);
//Create XElement
tmpAppsList.Add(new XElement("App",
new XElement("Name", app.Element("Name").Value),
new XElement("Description", app.Element("Description").Value),
new XElement("Version", app.Element("Version").Value),
new XElement("ID", app.Element("ID").Value),
new XElement("File", app.Element("File").Value),
new XElement("Hash", app.Element("Hash").Value)
));
if (app.Element("MainFile") != null)
tmpAppsList.Last().Add(new XElement("MainFile", app.Element("MainFile").Value));
if (app.Element("Icon") != null)
try
{
tmpAppsList.Last()
.Add(new XElement("Icon", ExternalFunctionalityManager.instance.FetchImageB64(new Uri(app.Element("Icon").Value).Unshorten())));
}
catch
{
}
if (tmpAppsList.Count(a => a.Element("ID").Value == app.Element("ID").Value) > 1)
tmpAppsList.Where(a => a.Element("ID").Value == app.Element("ID").Value).Reverse()
.Skip(1)
.ToList().ForEach(a => tmpAppsList.Remove(a));
}
#if !DEBUG
}
catch (Exception e)
{
ExternalFunctionalityManager.instance.OKDialog($"Failed to load repo: {repArr[i]}{Environment.NewLine}{e}");
}
#endif
i++;
}
tmpAppsList.Sort((x, y) =>
string.Compare(x.Element("Name").Value, y.Element("Name").Value, StringComparison.Ordinal));
if (meta.Element("LocalRepo") == null)
meta.Add(new XElement("LocalRepo"));
XElement repos = meta.Element("LocalRepo");
repos.RemoveNodes();
tmpAppsList.ForEach(app => repos.Add(app));
meta.Save(PathTool.InfoXml);
}
private static Version GetVer(this XElement el) =>
int.TryParse(el.Value, out int i) ? new Version(0, 0, 0, i) : Version.Parse(el.Value);
/// <summary>
/// Load the repository cache
/// </summary>
/// <param name="errorHandler">Function to call on an exception, will ask the user whether he wants to quit</param>
public static void GetReposFromDisk()
{
GlobalVariables.Apps.Clear();
string xml = PathTool.InfoXml;
XDocument.Load(xml).Element("meta").Element("LocalRepo").Elements().ToList().ForEach(app =>
{
Guid id = Guid.Parse(app.Element("ID").Value);
string locInPath = PathTool.GetInfoPath(id);
XElement locIn = File.Exists(locInPath) ? XDocument.Load(locInPath).Element("app") : app;
if (int.TryParse(app.Element("Version").Value, out _))
app.Element("Version").Value = GlobalVariables.minimumVer.ToString();
GlobalVariables.Apps.Add(id, new App(
locIn.Element("Name").Value,
locIn.Element("Description").Value,
Version.Parse(app.Element("Version").Value),
app.Element("File").Value,
false,
app.Element("Hash").Value,
id,
Color.White,
app.Element("Icon") == null
? ExternalFunctionalityManager.instance.GetDefaultIcon()
: ExternalFunctionalityManager.instance.ImageFromB64(app.Element("Icon").Value),
locIn.Element("MainFile") != null || app.Element("MainFile") != null,
locIn.Element("MainFile") == null
? app.Element("MainFile") == null ? "" : app.Element("MainFile").Value
: locIn.Element("MainFile").Value
));
});
Directory.GetDirectories(PathTool.appsPath)
.Where(s => Guid.TryParse(Path.GetFileName(s), out Guid guid) &&
!GlobalVariables.Apps.ContainsKey(guid)).ToList().ForEach(s =>
{
Guid tmp = Guid.Parse(Path.GetFileName(s));
try
{
XElement data = XDocument.Load(PathTool.GetInfoPath(tmp)).Element("app");
GlobalVariables.Apps.Add(tmp,
new App("(local) " + data.Element("Name").Value, data.Element("Description").Value,
GlobalVariables.minimumVer, "", true, "", tmp, Color.Red, ExternalFunctionalityManager.instance.GetDefaultIcon(),
data.Element("MainFile") != null,
data.Element("MainFile") == null ? "" : data.Element("MainFile").Value));
}
catch (Exception e)
{
if (ExternalFunctionalityManager.instance.YesNoDialog($@"An error occured while loading this local repo:
{e.Message}
Do you want to exit? Otherwise the folder will be deleted, possibly causeing problems later.", false))
Environment.Exit(0);
else
Directory.Delete(PathTool.GetAppPath(tmp), true);
}
});
}
}
}

47
UpToolLib/Tool/XmlTool.cs Normal file
View File

@ -0,0 +1,47 @@
using System.IO;
using System.Linq;
using System.Xml.Linq;
namespace UpToolLib.Tool
{
public static class XmlTool
{
public static void FixXml()
{
if (!File.Exists(PathTool.InfoXml) || XDocument.Load(PathTool.InfoXml).Element("meta") == null)
new XElement("meta").Save(PathTool.InfoXml);
XDocument x = XDocument.Load(PathTool.InfoXml);
XElement meta = x.Element("meta");
if (meta.Element("UpdateSource") == null)
meta.Add(new XElement("UpdateSource"));
if (new[]
{
"",
"https://raw.githubusercontent.com/CreepyCrafter24/UpTool2/master/Meta.xml",
"https://raw.githubusercontent.com/JFronny/UpTool2/master/Meta.xml",
"https://gist.githubusercontent.com/JFronny/f1ccbba3d8a2f5862592bb29fdb612c4/raw/Meta.xml"
}
.Contains(meta.Element("UpdateSource").Value))
meta.Element("UpdateSource").Value =
"https://github.com/JFronny/UpTool2/releases/latest/download/meta.xml";
if (meta.Element("Repos") == null)
meta.Add(new XElement("Repos"));
if (meta.Element("Repos").Elements("Repo").Count() == 0)
meta.Element("Repos").Add(new XElement("Repo", new XElement("Name", "UpTool2 official Repo"),
new XElement("Link",
"https://gist.githubusercontent.com/JFronny/f1ccbba3d8a2f5862592bb29fdb612c4/raw/Repo.xml")));
meta.Element("Repos").Elements("Repo").Select(s => s.Element("Link"))
.Where(s => new[]
{
null, "https://github.com/JFronny/UpTool2/releases/download/Repo/Repo.xml",
"https://raw.githubusercontent.com/JFronny/UpTool2/master/Repo.xml"
}.Contains(s.Value))
.ToList().ForEach(s =>
s.Value =
"https://gist.githubusercontent.com/JFronny/f1ccbba3d8a2f5862592bb29fdb612c4/raw/Repo.xml");
if (meta.Element("LocalRepo") == null)
meta.Add(new XElement("LocalRepo"));
x.Save(PathTool.InfoXml);
}
}
}

View File

@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CC-Functions.Misc" Version="1.1.7388.28729" />
</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>
</Project>