Ejemplo n.º 1
0
		private static RestApiSpec CreateRestApiSpecModel(string downloadBranch, string[] folders)
		{
			var directories = Directory.GetDirectories(CodeConfiguration.RestSpecificationFolder, "*", SearchOption.AllDirectories)
				.Where(f=>folders == null || folders.Length == 0 || folders.Contains(new DirectoryInfo(f).Name))
				.ToList();

			var endpoints = new Dictionary<string, ApiEndpoint>();
			using (var pbar = new ProgressBar(directories.Count, $"Listing {directories.Count} directories", new ProgressBarOptions { BackgroundColor = ConsoleColor.DarkGray }))
			{
				foreach (var jsonFiles in directories.Select(dir => Directory.GetFiles(dir).Where(f => f.EndsWith(".json")).ToList()))
				{
					using (var fileProgress = pbar.Spawn(jsonFiles.Count, $"Listing {jsonFiles.Count} files", new ProgressBarOptions { ProgressCharacter = '─', BackgroundColor = ConsoleColor.DarkGray }))
					{
						foreach (var endpoint in jsonFiles.Select(CreateApiEndpoint))
						{
							endpoints.Add(endpoint.Key, endpoint.Value);
							fileProgress.Tick();
						}
					}
					pbar.Tick();
				}
			}

			return new RestApiSpec { Endpoints = endpoints, Commit = downloadBranch };
		}
        private static async Task <string> IteratePlaylists(List <string> playlists, string network, string region)
        {
            string hits = string.Empty;

            using (ShellProgressBar.ProgressBar progressBar = new ShellProgressBar.ProgressBar(playlists.Count, string.Empty, ConsoleColor.Green))
            {
                using HttpClient client = new HttpClient { Timeout = TimeSpan.FromSeconds(3) };
                await playlists.AsParallel().AsOrdered().ParallelForEachAsync(async playlist =>
                {
                    string[] lines = File.ReadAllLines(playlist);
                    using (ChildProgressBar child = progressBar.Spawn(lines.Length,
                                                                      "processing " + Path.GetFileName(playlist),
                                                                      new ProgressBarOptions {
                        ProgressCharacter = '-', CollapseWhenFinished = true
                    }))
                    {
                        for (int i = 0; i < lines.Length; i++)
                        {
                            if (ContainsStream(lines[i], network, region))
                            {
                                try
                                {
                                    if (!string.IsNullOrEmpty(await client.GetStringAsync(lines[i + 1])))
                                    {
                                        hits += lines[i] + "\n" + lines[i + 1] + "\n";
                                    } // take the link that should be after the line, test if working
                                }
                                catch (Exception e) when(e is HttpRequestException || e is InvalidOperationException)
                                {
                                }                                                                                          // some links are dumb, this fixes program from breaking from dumb links
                            }
                            child.Tick();
                        }
                    }
                    progressBar.Tick();
                }, maxDegreeOfParallelism: Environment.ProcessorCount * 5);

                while (progressBar.CurrentTick < progressBar.MaxTicks)
                {
                    progressBar.Tick();
                } // progress bar percentage correction in case spaghetti
            }
            return(hits);
        }
Ejemplo n.º 3
0
        public static void Run(string[] args, ConfiguratorInputOptions InputOptions)
        {
            ShellProgressBarHack.PatchExcerptFunc();

            var rootPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

            log = new StreamWriter(File.Open(Path.Combine(rootPath, LogFilePath), FileMode.Create, FileAccess.Write, FileShare.Read), Encoding.UTF8);
            var localPackageDirPath = Path.Combine(rootPath, "Pkg");
            var profileDirPath      = Path.Combine(rootPath, "Prfl");

            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(Unhandled);
            DateTime now = DateTime.Now;

            log.Log(now.ToString("F", new CultureInfo("en-US")));
            log.Log("Configurator for Dotnet Runtime Patcher by Meigyoku Thmn");
            log.Log($"Version {Application.ProductVersion}");
            Console.OutputEncoding = Encoding.UTF8;
            var desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);

            Package selectedPackage = new Package(null, null, null);
            string  targetPath      = null;

            if (InputOptions.Specify == true)
            {
                if (InputOptions.Id == null || InputOptions.Name == null || InputOptions.ServerUrl == null || InputOptions.TargetPath == null)
                {
                    log.Log("Invalid arg syntax!");
                    Environment.Exit(-1);
                }
                selectedPackage.Id        = InputOptions.Id;
                selectedPackage.Name      = InputOptions.Name;
                selectedPackage.ServerUrl = InputOptions.ServerUrl;
                targetPath = InputOptions.TargetPath;
                goto BeforeStep3;
            }

            // STEP 1: List all servers/packages, then ask user to select a package
            log.Log($"Get server list from {SystemCfgUrl}\n");
            string systemCfgStr;

            using (var wc = new WebClient {
                Encoding = Encoding.UTF8
            }) {
                systemCfgStr = wc.DownloadString(SystemCfgUrl);
            }
            var systemCfg = JObject.Parse(systemCfgStr);
            var servers   = systemCfg["servers"].Children <JProperty>().Aggregate(new List <JObject>(), (acc, server) => {
                var serverUri = new Uri((string)server.Value).Concat("server.jsonc");
                try {
                    string serverCfgStr;
                    using (var wc = new WebClient {
                        Encoding = Encoding.UTF8
                    }) {
                        serverCfgStr = wc.DownloadString(serverUri);
                    }
                    var serverCfg    = JObject.Parse(serverCfgStr);
                    serverCfg["url"] = serverUri.ToString();
                    serverCfg["id"]  = server.Name;
                    acc.Add(serverCfg);
                }
                catch (Exception err) {
                    log.Log($"Url: {serverUri}");
                    log.Log(err.Message);
                }
                return(acc);
            });
            var count    = 0;
            var packages = new List <Package>();

            foreach (var serverCfg in servers)
            {
                log.Log(" " + serverCfg["title"]);
                foreach (JProperty package in serverCfg["packages"])
                {
                    log.Log($"  [{count++}] {package.Name}: {package.Value}");
                    packages.Add(new Package(package.Name, (string)serverCfg["id"], (string)serverCfg["url"]));
                }
            }
            log.Log($"\nPlease select your desired package (from 0 to {count - 1}): ");
            int selectedIndex;

            while (!int.TryParse(Console.ReadLine(), out selectedIndex) || (selectedIndex > count - 1 || selectedIndex < 0))
            {
                ;
            }
            log.WriteLine(selectedIndex);
            selectedPackage = packages[selectedIndex];
            if (selectedPackage.Id.IndexOf('/') != -1 || selectedPackage.Name.IndexOf('/') != -1 || selectedPackage.Id.IndexOf('\\') != -1 || selectedPackage.Name.IndexOf('\\') != -1)
            {
                log.Log($"Package name ({selectedPackage.Name}) or package id ({selectedPackage.Id}) has slash character, our system cannot allow such character.");
                return;
            }

            // STEP 2: ask user to select the exe that they want to patch
            log.Log("\nPlease select your target executable file.");
            OpenFileDialog openFileDg = new OpenFileDialog();

            openFileDg.Title           = "Please select your target executable file";
            openFileDg.Filter          = "Executable file|*.exe|All files|*.*";
            openFileDg.CheckFileExists = true;
            openFileDg.CheckPathExists = true;
            var dialogRs = openFileDg.ShowDialog();

            if (dialogRs == DialogResult.Cancel)
            {
                return;
            }
            targetPath = openFileDg.FileName;

BeforeStep3:
            log.Log(targetPath);
            var targetInfo = GetChecksumAndSize(targetPath);

            // STEP 3: download packages
            log.Log();
            log.Log("Selected Package:");
            log.Log($"  Name = {selectedPackage.Name}");
            log.Log($"  Id = {selectedPackage.Id}");
            log.Log($"  ServerUrl = {selectedPackage.ServerUrl}");
            var    versionUri = new Uri(selectedPackage.ServerUrl).Concat(selectedPackage.Name, "versions.jsonc");
            string versionCfgStr;

            using (var wc = new WebClient {
                Encoding = Encoding.UTF8
            }) {
                versionCfgStr = wc.DownloadString(versionUri);
            }
            var versionCfg    = JObject.Parse(versionCfgStr);
            var targetVersion = versionCfg[targetInfo.Hash];

            if (targetVersion == null || (long)targetVersion["size"] != targetInfo.Size)
            {
                log.Log("We can't find proper patch for your application file, maybe your app is a newer version, or we don't have a patch for it.");
                return;
            }
            var patchName = (string)targetVersion["name"];

            if (patchName == null || patchName.IndexOf("/") != -1 || patchName.IndexOf("\\") != -1)
            {
                log.Log("We found a patch, but its patch name is null or contains slash character, such character is invalid.");
                log.Log($"Hash: {targetInfo.Hash}");
                log.Log($"Name: {patchName}");
                log.Log($"Ver: {targetVersion["ver"]}");
                log.Log($"Size: {targetInfo.Size}");
                return;
            }
            var    patchRoot = patchName + '/';
            var    filesUri  = new Uri(selectedPackage.ServerUrl).Concat(selectedPackage.Name, "files.jsonc");
            string filesCfgStr;

            using (var wc = new WebClient {
                Encoding = Encoding.UTF8
            }) {
                filesCfgStr = wc.DownloadString(filesUri);
            }
            var     filesCfg     = JObject.Parse(filesCfgStr);
            var     files        = filesCfg.Children <JProperty>().Where(file => file.Name.IndexOf(patchRoot, 0, patchRoot.Length) != -1);
            var     oldFilesPath = Path.Combine(localPackageDirPath, selectedPackage.Id, selectedPackage.Name, "files.jsonc");
            JObject oldFiles;

            try {
                log.Log($"Read local file list: {oldFilesPath}");
                oldFiles = JObject.Parse(File.ReadAllText(oldFilesPath));
            }
            catch (Exception ex) when(ex is FileNotFoundException || ex is DirectoryNotFoundException)
            {
                log.Log("Local file list doesn't exist.");
                oldFiles = new JObject();
            }
            Console.Clear();
            Console.WriteLine(); // for some reason, on some computers, the first line of console is updated very slow, so I just leave the first line alone
            var writeCount = 0;
            var skipCount  = 0;
            int totalTicks = files.Count();
            var options    = new ProgressBarOptions {
                BackgroundCharacter   = '\u2593',
                ProgressBarOnBottom   = true,
                EnableTaskBarProgress = true,
                ForegroundColor       = ConsoleColor.Yellow,
                ForegroundColorDone   = ConsoleColor.Green,
                BackgroundColor       = ConsoleColor.DarkGray,
            };
            var childOptions = new ProgressBarOptions {
                BackgroundCharacter = '\u2593',
                ProgressBarOnBottom = true,
                ForegroundColor     = ConsoleColor.Yellow,
                ForegroundColorDone = ConsoleColor.Green,
                BackgroundColor     = ConsoleColor.DarkGray,
            };
            var mainMessage = "Files downloading progress";

            using (var pbar = new SProgressBar(totalTicks, mainMessage, options)) {
                pbar.Tick(0, $"0/{totalTicks}");
                // use 5 connection as the maximium, unless you want your whole country blocked by github
                Parallel.ForEach(Partitioner.Create(files, EnumerablePartitionerOptions.NoBuffering), new ParallelOptions()
                {
                    MaxDegreeOfParallelism = 5
                }, (file) => {
                    var oldChecksum = oldFiles[file.Name];
                    if (oldChecksum != null && (uint)file.Value == (uint)oldChecksum)
                    {
                        pbar.Tick($"{pbar.CurrentTick + 1}/{totalTicks} {mainMessage}");
                        Interlocked.Increment(ref skipCount);
                        return;
                    }
                    var fileUri  = new Uri(selectedPackage.ServerUrl).Concat(selectedPackage.Name, file.Name);
                    var filePath = Path.Combine(localPackageDirPath, selectedPackage.Id, selectedPackage.Name, file.Name);
                    log.Log(fileUri.ToString(), noPrint: true, useLock: true);
                    Directory.CreateDirectory(Path.GetDirectoryName(filePath));
                    new Func <Task>(async() => {
                        using (var child = pbar.Spawn(100, fileUri.ToString(), childOptions))
                            using (var wc = new WebClient {
                                Encoding = Encoding.UTF8
                            }) {
                                child.Tick(0);
                                wc.DownloadProgressChanged += (sender, e) => {
                                    child.Tick(e.ProgressPercentage);
                                };
                                await wc.DownloadFileTaskAsync(fileUri, filePath);
                            }
                    })().Wait();
                    pbar.Tick($"{pbar.CurrentTick + 1}/{totalTicks} {mainMessage}");
                    Interlocked.Increment(ref writeCount);
                });
            }
            log.Log($"Downloaded {writeCount} file(s)");
            log.Log($"Skipped {skipCount} file(s)");
            log.Log($"Write new file list to {oldFilesPath}");
            Directory.CreateDirectory(Path.GetDirectoryName(oldFilesPath));
            File.WriteAllText(oldFilesPath, filesCfgStr);
            var versionsPath = Path.Combine(localPackageDirPath, selectedPackage.Id, selectedPackage.Name, "versions.jsonc");

            log.Log($"Write {versionsPath}");
            Directory.CreateDirectory(Path.GetDirectoryName(versionsPath));
            File.WriteAllText(versionsPath, versionCfgStr);

            if (InputOptions.Specify == true)
            {
                goto AfterAllSteps;
            }

            var urlFilePath = Path.Combine(localPackageDirPath, selectedPackage.Id, "urls.jsonc");
            var urlFileCfg  = new JObject();

            urlFileCfg["serverUrl"] = selectedPackage.ServerUrl;
            log.Log($"Write {urlFilePath}");
            Directory.CreateDirectory(Path.GetDirectoryName(urlFilePath));
            File.WriteAllText(urlFilePath, urlFileCfg.ToString());

            // STEP 4: create config file
            var defaultShortcutName = $"{targetVersion["name"]}_{selectedPackage.Name}";
            var exeCfg = new JObject();

            exeCfg["targetPath"] = targetPath;
            exeCfg["package"]    = $"{selectedPackage.Id}/{selectedPackage.Name}";
            log.Log($"Write profile {defaultShortcutName + ".jsonc"} to root directory");
            var exeProfilePath = Path.Combine(profileDirPath, defaultShortcutName + ".jsonc");

            Directory.CreateDirectory(Path.GetDirectoryName(exeProfilePath));
            File.WriteAllText(exeProfilePath, exeCfg.ToString());

            // STEP 5: create shortcut on desktop
            log.Log("\nPlease set a name of a shortcut file that we will create on your desktop:");
            log.Log($"(Default: {defaultShortcutName})");
            var newShortcutName = Console.ReadLine().Trim();

            log.WriteLine(newShortcutName);
            if (newShortcutName.Length == 0)
            {
                newShortcutName = defaultShortcutName;
            }
            if (!newShortcutName.IsValidPath())
            {
                log.Log("Invalid path, use the default instead.");
                newShortcutName = defaultShortcutName;
            }
            var arguments = $"\"{defaultShortcutName}\"";

            CreateShortcut(
                Path.Combine(desktopPath, newShortcutName + ".lnk"),
                typeof(RuntimePatcher.Helper).Assembly.Location,
                arguments,
                targetPath + ", 0"
                );
            log.Log("Created a shortcut on desktop.");

AfterAllSteps:
            log.Log("\nAll done! Press enter to exit this wizard.");
            log.Close();
            Console.ReadLine();
        }