internal static void Update() { var spinner = new CustomSpinner("Updating cache"); string tmpPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); if (File.Exists(tmpPath)) { File.Delete(tmpPath); } if (Directory.Exists(tmpPath)) { Directory.Delete(tmpPath, true); } try { DownloadPages(Remote, tmpPath); } catch (WebException eRemote) { try { DownloadPages(AlternativeRemote, tmpPath); } catch (WebException eAlternative) { CustomConsole.WriteError(eAlternative.Message); if (eRemote.Response is HttpWebResponse response && response.StatusCode == HttpStatusCode.Forbidden) { Console.WriteLine("Please try to set the Cloudflare cookie and user-agent. " + "See https://github.com/principis/tldr-sharp/wiki/403-when-updating-cache."); }
public static void Run(InlineTextBlock label, Action action) { if (action == null) { throw new ArgumentNullException(nameof(action)); } var spinner = new CustomSpinner(label); spinner.Display(); try { action(); spinner.Close(); } catch (Exception e) { spinner.DoneText = null; string error = e.Message; if (error.StartsWith("Error:")) { error = error.Substring(7); } Console.ForegroundColor = ConsoleColor.DarkRed; Console.Write("[ERROR]"); Console.ResetColor(); Console.Write($" {error}"); spinner.Close(); Environment.Exit(1); } }
internal static int Print(string pageName, string prefLanguage = null, string platform = null, bool markdown = false) { pageName = pageName.ToLower().TrimStart().Replace(' ', '-'); List <string> languages; if (prefLanguage == null) { languages = Locale.GetPreferredLanguages(); if (languages.Count == 0) { Console.WriteLine( $"[INFO] None of the preferred languages found, using {Locale.GetLanguageName(Locale.DefaultLanguage)} instead. " + "See `tldr --list-languages` for a list of all available languages."); languages.Add(Locale.DefaultLanguage); } } else { languages = new List <string> { prefLanguage }; } platform ??= GetPlatform(); string altPlatform = null; List <Page> results = QueryByName(pageName); if (results.Count == 0) { if ((DateTime.UtcNow.Date - Cache.LastUpdate()).TotalDays > 5) { Console.WriteLine("Page not found."); Console.Write("Cache older than 5 days. "); Updater.Update(); results = QueryByName(pageName); } if (results.Count == 0) { return(NotFound(pageName)); } } results = results.OrderBy(item => item, new PageComparer(new[] { platform, "common" }, languages)).ToList(); Page page; try { page = Find(results, languages, platform); } catch (ArgumentNullException) { if (prefLanguage != null) { Console.WriteLine( $"The `{pageName}` page could not be found in {Locale.GetLanguageName(prefLanguage)}. " + $"{Environment.NewLine}Feel free to translate it: https://github.com/tldr-pages/tldr/blob/master/CONTRIBUTING.md#translations"); return(2); } try { page = FindAlternative(results, languages); if (platform != page.Platform && page.Platform != "common") { altPlatform = page.Platform; } } catch (ArgumentNullException) { return(NotFound(pageName)); } } if (!page.Local) { CustomSpinner.Run("Page not cached. Downloading", page.Download); } string path = page.GetPath(); if (!File.Exists(path)) { Console.WriteLine("[ERROR] File \"{0}\" not found.", path); return(1); } if (markdown) { Console.WriteLine(File.ReadAllText(path)); } else { return(Render(path, altPlatform)); } return(0); }
internal static void CheckSelfUpdate() { var spinner = new CustomSpinner("Checking for update"); using var client = new WebClient(); client.Headers.Add("user-agent", Program.UserAgent); string json; try { json = client.DownloadString(ApiUrl); } catch (WebException e) { CustomConsole.WriteError( $"{e.Message}{Environment.NewLine}Please make sure you have a functioning internet connection."); Environment.Exit(1); return; } var remoteVersion = new Version( json.Split(new[] { "," }, StringSplitOptions.None) .First(s => s.Contains("tag_name")) .Split(':')[1] .Trim('"', ' ', 'v')); spinner.Dispose(); if (remoteVersion.CompareTo(Assembly.GetExecutingAssembly().GetName().Version) <= 0) { Console.WriteLine("tldr-sharp is up to date!"); return; } if (Environment.OSVersion.Platform == PlatformID.Unix) { var updateQuestion = new YesNoQuestion($"Version {remoteVersion} is available. Do you want to update?") { DefaultAnswer = YesNoAnswer.No, ForegroundColor = null, QuestionForegroundColor = null, BackgroundColor = null, QuestionBackgroundColor = null }; if (updateQuestion.ReadAnswer() != YesNoAnswer.Yes) { return; } Console.WriteLine("Select desired method:"); Console.WriteLine("0\tDebian package (.deb)"); Console.WriteLine("1\tRPM package (.rpm)"); Console.WriteLine("2\tinstall script (.sh)"); string option; int optionNb; do { Console.Write("Enter number 0..2: "); option = Console.ReadLine(); } while (!int.TryParse(option, out optionNb) || optionNb > 3 || optionNb < 0); Console.WriteLine(); switch (optionNb) { case 0: SelfUpdate(UpdateType.Debian, remoteVersion); break; case 1: SelfUpdate(UpdateType.Rpm, remoteVersion); break; case 2: SelfUpdate(UpdateType.Script, remoteVersion); break; } } else { Console.WriteLine("Version {0} is available. Download it from {1}", remoteVersion, "https://github.com/principis/tldr-sharp/releases/"); } }
private static void SelfUpdate(UpdateType type, Version version) { Console.WriteLine($"Updating tldr-sharp to v{version}"); string tmpPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); if (File.Exists(tmpPath)) { File.Delete(tmpPath); } string url = GetUpdateUrl(type, version); using (var client = new WebClient()) { try { client.DownloadFile(url, tmpPath); } catch (WebException e) { CustomConsole.WriteError( $"{e.Message}{Environment.NewLine}Please make sure you have a functioning internet connection."); Environment.Exit(1); return; } } var startInfo = new ProcessStartInfo { FileName = "/bin/bash", UseShellExecute = false, RedirectStandardOutput = true, Arguments = type switch { UpdateType.Debian => "-c \"sudo dpkg -i " + tmpPath + "\"", UpdateType.Rpm => "-c \"sudo rpm -i " + tmpPath + "\"", UpdateType.Script => "-c \"bash " + tmpPath + "\"", _ => throw new ArgumentOutOfRangeException(nameof(type), type, null) } }; using (var process = new Process { StartInfo = startInfo }) { process.Start(); Console.Write(process.StandardOutput.ReadToEnd()); while (!process.HasExited) { Thread.Sleep(100); } File.Delete(tmpPath); if (process.ExitCode != 0) { Console.WriteLine( "[ERROR] Oops! Something went wrong!{0}Help us improve your experience by sending an error report.", Environment.NewLine); Environment.Exit(1); } } CustomSpinner.Run("Clearing Cache", Cache.Clear); Console.WriteLine("[INFO] v{0} installed.", version); Environment.Exit(0); }
internal static void Create() { using var spinner = new CustomSpinner("Creating index"); var cacheDir = new DirectoryInfo(Program.CachePath); SqliteConnection.CreateFile(Program.DbPath); using var conn = new SqliteConnection("Data Source=" + Program.DbPath + ";"); conn.Open(); using var command = new SqliteCommand(conn); using SqliteTransaction transaction = conn.BeginTransaction(); command.CommandText = "CREATE TABLE pages (name VARCHAR(100), platform VARCHAR(10), lang VARCHAR(7), local INTEGER)"; command.ExecuteNonQuery(); command.CommandText = "CREATE TABLE config (parameter VARCHAR(20), value VARCHAR(100))"; command.ExecuteNonQuery(); command.CommandText = "INSERT INTO config (parameter, value) VALUES(@parameter, @value)"; command.Parameters.AddWithValue("@parameter", "last-update"); command.Parameters.AddWithValue("@value", DateTime.UtcNow.Date.ToString(CultureInfo.InvariantCulture)); command.ExecuteNonQuery(); command.Transaction = transaction; command.CommandType = CommandType.Text; // Create indexes command.CommandText = "CREATE INDEX names_index ON pages (name, platform, lang, local)"; command.ExecuteNonQuery(); command.CommandText = "CREATE INDEX lang_platform_index ON pages (lang, platform, name, local)"; command.ExecuteNonQuery(); command.CommandText = "CREATE INDEX platform_index ON pages (platform)"; command.ExecuteNonQuery(); command.CommandText = "CREATE INDEX lang_index ON pages (lang)"; command.ExecuteNonQuery(); // Add pages command.CommandText = "INSERT INTO pages (name, platform, lang, local) VALUES(@name, @platform, @lang, @local)"; List <string> preferredLanguages = Locale.GetEnvLanguages(); foreach (DirectoryInfo dir in cacheDir.EnumerateDirectories("*pages*")) { string lang = Locale.DefaultLanguage; bool isLocal = true; if (dir.Name.Contains(".")) { lang = dir.Name.Split('.')[1]; } if (lang != Locale.DefaultLanguage && preferredLanguages.All(x => lang.Substring(0, 2) != x.Substring(0, 2))) { isLocal = false; } foreach (DirectoryInfo osDir in dir.EnumerateDirectories()) { foreach (FileInfo file in osDir.EnumerateFiles("*.md", SearchOption.AllDirectories)) { command.Parameters.AddWithValue("@name", Path.GetFileNameWithoutExtension(file.Name)); command.Parameters.AddWithValue("@platform", osDir.Name); command.Parameters.AddWithValue("@lang", lang); command.Parameters.AddWithValue("@local", isLocal); command.ExecuteNonQuery(); } } } transaction.Commit(); spinner.Close(); }
private static int doMain(string[] args) { bool showHelp = false; bool list = false; bool ignorePlatform = false; string language = null; string platform = null; string search = null; bool markdown = false; string render = null; var options = new OptionSet { "Usage: tldr command [options]" + Environment.NewLine, "Simplified and community-driven man pages" + Environment.NewLine, { "a|list-all", "List all pages", a => list = ignorePlatform = a != null }, { "c|clear-cache", "Clear the cache", c => { CustomSpinner.Run("Clearing cache", Cache.Clear); Environment.Exit(0); } }, { "f=|render=", "Render a specific markdown file", v => render = v }, { "h|help", "Display this help text", h => showHelp = h != null }, { "l|list", "List all pages for the current platform and language", l => list = l != null }, { "list-os", "List all platforms", o => { Cache.Check(); Console.WriteLine(string.Join(Environment.NewLine, ListPlatform())); } }, { "list-languages", "List all languages", la => { Cache.Check(); Console.WriteLine(string.Join(Environment.NewLine, ListLanguages().Select(lang => { string name = Locale.GetLanguageName(lang); return(name == null ? lang : $"{lang}:\t{name}"); }))); } }, { "L=|language=|lang=", "Specifies the preferred language", la => language = la }, { "m|markdown", "Show the markdown source of a page", v => markdown = v != null }, { "p=|platform=", "Override the default platform", o => platform = o }, { "s=|search=", "Search for a string", s => search = s }, { "u|update", "Update the cache", u => Updater.Update() }, { "self-update", "Check for tldr-sharp updates", u => { SelfUpdater.CheckSelfUpdate(); Environment.Exit(0); } }, { "v|version", "Show version information", v => { string version = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location) .ProductVersion; Console.WriteLine($"tldr-sharp {version}"); Console.WriteLine("tldr-pages client specification " + ClientSpecVersion); Environment.Exit(0); } } }; List <string> extra; try { extra = options.Parse(args); } catch (OptionException e) { Console.WriteLine(e.Message); return(1); } if (showHelp || args.Length == 0) { options.WriteOptionDescriptions(Console.Out); return(args.Length == 0 ? 1 : 0); } if (render != null) { return(PageController.Render(render)); } // All following functions rely on the cache, so check it. Cache.Check(); if (language != null) { if (!CheckLanguage(language)) { Console.WriteLine("[ERROR] unknown language '{0}'", language); return(1); } } if (list) { PageController.ListAll(ignorePlatform, language, platform); return(0); } if (search != null) { return(PageController.Search(search, language, platform)); } StringBuilder builder = new StringBuilder(); foreach (string arg in extra) { if (arg.StartsWith("-")) { if (builder.Length == 0) { Console.WriteLine("[ERROR] unknown option '{0}'", arg); } return(1); } builder.Append($" {arg}"); } string page = builder.ToString(); return(page.Trim().Length > 0 ? PageController.Print(page, language, platform, markdown) : 0); }