Exemple #1
0
        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.");
                    }
Exemple #2
0
        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);
            }
        }
Exemple #3
0
        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);
        }
Exemple #4
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/");
            }
        }
Exemple #5
0
        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);
        }
Exemple #6
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();
        }
Exemple #7
0
        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);
        }