public static int Main(string[] args) { if (args.Length < 1) { return(XConsole.PrintInfo("HookGenerator.CLI - generate API-like osu! methods access assembly\n" + "by exys, 2019\n" + "\n" + "Usage:\n" + "HookGenerator.CLI [clean module]")); } string originalModulePath; if (!File.Exists(originalModulePath = Path.GetFullPath(args[0]))) { return(XConsole.PrintError("Specified module path does not exist!")); } try { _originalModule = ModuleDefMD.Load(originalModulePath); } catch (Exception e) { return(XConsole.PrintError("An error occurred while trying to load module! Details:\n" + e)); } XConsole.PrintInfo($"Loaded module: {_originalModule.Assembly.FullName}."); var assemblyName = $"OsuHooks-{MD5Helper.Compute(originalModulePath).Substring(0, 8)}"; var moduleName = $"{assemblyName}.dll"; var hookModule = new HookGenerator(assemblyName, _originalModule).CreateHookModule(); XConsole.PrintInfo($"Finally writing {moduleName}!"); hookModule.Write(Path.Combine(Path.GetDirectoryName(originalModulePath) ?? throw new Exception("Path to write module to is null unexpectedly"), moduleName)); return(0); }
/// <summary> /// Get osu! assembly by stream and target filename /// </summary> /// <param name="streamName">Target stream name (Stable/Beta/cuttingedge)</param> /// <param name="targetFile">Target filename (ex. osu!.exe, bass_fx.dll etc.)</param> /// <param name="target">Target number (file_version), default is latest</param> /// <returns>Dictionary (file name to write with extension; file data)</returns> private static byte[] GetDataFromStream(string streamName, string targetFile, long target = -1) { byte[] ret = null; HttpWebRequest request; if (target == -1) { request = (HttpWebRequest)WebRequest.Create(string.Format(CHECK_UPDATES_TEMPLATE, streamName, DateTime.Now.Ticks)); } else { request = (HttpWebRequest)WebRequest.Create(string.Format(DOWNLOAD_TARGET_TEMPLATE, streamName, target)); } request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; string jsonResponse; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) using (Stream stream = response.GetResponseStream()) using (StreamReader reader = new StreamReader(stream)) { jsonResponse = reader.ReadToEnd(); } dynamic updateFiles = JToken.Parse(jsonResponse); if (updateFiles is JObject) { Message("Error response received from server:\n" + updateFiles.response.Value); return(null); } if (updateFiles is JArray) { foreach (var updateFile in updateFiles) { if (updateFile.filename.Value != targetFile) { continue; } if (File.Exists(targetFile)) { if (updateFile.file_hash.Value.Equals(MD5Helper.Compute(targetFile), StringComparison.OrdinalIgnoreCase)) { continue; } } var cachedAssemblyPath = Path.Combine(ExecutingAssemblyLocation, updateFile.file_hash.Value + Path.GetExtension(targetFile)); if (File.Exists(cachedAssemblyPath)) { Message($"Found cached copy of {targetFile}!"); return(File.ReadAllBytes(cachedAssemblyPath)); } int retryCount = 0; while (true) { try { ret = GetDataFromUrl(updateFile.url_full.Value); break; } catch (Exception ex) { Message($"Failed to download \"{target} - {updateFile.filename.Value}\", retrying in {RETRY_SLEEP_TIME / 1000} seconds. More info:\n{ex}"); Thread.Sleep(RETRY_SLEEP_TIME); } if (++retryCount > 3) { return(ret); } } File.WriteAllBytes(cachedAssemblyPath, ret); Message($"Successfully downloaded {targetFile}!"); break; } } return(ret); }