Skip to content

Commit

Permalink
Refactoring and added update fallback.
Browse files Browse the repository at this point in the history
  • Loading branch information
principis committed Aug 7, 2019
1 parent c52de12 commit 9d6ca29
Show file tree
Hide file tree
Showing 8 changed files with 716 additions and 504 deletions.
126 changes: 126 additions & 0 deletions tldr-sharp/Cache.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.IO;
using System.Net;
using Mono.Data.Sqlite;

namespace tldr_sharp
{
internal static class Cache
{
private const string Remote = "https://raw.githubusercontent.com/tldr-pages/tldr/master/pages";

internal static void Check()
{
if (File.Exists(Program.DbPath)) return;

Console.WriteLine("Database not found. ");
Updater.Update();
}

internal static void CreateSchema()
{
using (var conn = new SqliteConnection("Data Source=" + Program.DbPath + ";")) {
conn.Open();

using (SqliteTransaction transaction = conn.BeginTransaction())
using (var command = new SqliteCommand(conn)) {
command.Transaction = transaction;
command.CommandType = CommandType.Text;

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();

// Create indexes
command.CommandText = "CREATE INDEX os_names ON pages (platform, name)";
command.ExecuteNonQuery();
command.CommandText = "CREATE INDEX lang_names ON pages (lang, name)";
command.ExecuteNonQuery();
command.CommandText = "CREATE INDEX names_index ON pages (lang, platform, name)";
command.ExecuteNonQuery();

transaction.Commit();
}
}
}

internal static void Clear()
{
DirectoryInfo cacheDir;
try {
if (File.Exists(Program.CachePath)) File.Delete(Program.CachePath);

cacheDir = new DirectoryInfo(Program.CachePath);

if (cacheDir.Exists) {
cacheDir.Delete(true);
}
} catch (Exception e) {
Console.WriteLine("[ERROR] {0}", e.Message);
Environment.Exit(1);
return;
}

cacheDir.Create();
}

internal static void DownloadPage(Page page)
{
var pageFile = new FileInfo(page.GetPath());
Directory.CreateDirectory(pageFile.DirectoryName ?? throw new ArgumentException());

using (var client = new WebClient()) {
client.Headers.Add("user-agent", Program.UserAgent);


string language = page.Language == Program.DefaultLanguage ? string.Empty : $".{page.Language}";

string data = client.DownloadString($"{Remote}{language}/{page.Platform}/{page.Name}.md");
using (StreamWriter sw = pageFile.CreateText()) {
sw.WriteLine(data);
}
}

using (var conn = new SqliteConnection("Data Source=" + Program.DbPath + ";")) {
conn.Open();
using (SqliteCommand command = conn.CreateCommand()) {
command.CommandText =
"UPDATE pages SET local = TRUE WHERE name = @name AND lang = @lang AND platform = @platform";
command.Parameters.Add(new SqliteParameter("@name", page.Name));
command.Parameters.Add(new SqliteParameter("@platform", page.Platform));
command.Parameters.Add(new SqliteParameter("@lang", page.Language));

command.ExecuteNonQuery();
}
}
}

internal static DateTime LastUpdate()
{
using (var conn = new SqliteConnection("Data Source=" + Program.DbPath + ";")) {
conn.Open();

using (var command = new SqliteCommand("SELECT value FROM config WHERE parameter = @parameter", conn)) {
command.Parameters.Add(new SqliteParameter("@parameter", "last-update"));

using (SqliteDataReader reader = command.ExecuteReader()) {
reader.Read();
return DateTime.Parse(reader.GetString(0));
}
}
}
}
}
}
151 changes: 151 additions & 0 deletions tldr-sharp/Index.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Mono.Data.Sqlite;

namespace tldr_sharp
{
internal static class Index
{
internal static List<Page> Query(string query, SqliteParameter[] parameters, string page = null)
{
using (var conn = new SqliteConnection("Data Source=" + Program.DbPath + ";")) {
conn.Open();

string commandString = page == null
? $"SELECT name, platform, lang, local FROM pages WHERE {query}"
: $"SELECT platform, lang, local FROM pages WHERE {query}";
using (var command = new SqliteCommand(commandString, conn)) {
command.Parameters.AddRange(parameters);

using (SqliteDataReader reader = command.ExecuteReader()) {
var results = new List<Page>();
while (reader.Read()) {
if (page == null) {
results.Add(new Page(reader.GetString(0), reader.GetString(1), reader.GetString(2),
reader.GetBoolean(3)));
} else {
results.Add(new Page(page, reader.GetString(0), reader.GetString(1),
reader.GetBoolean(2)));
}
}

return results;
}
}
}
}

internal static string GetPlatform()
{
switch (Environment.OSVersion.Platform) {
case PlatformID.MacOSX:
return "osx";
case PlatformID.Unix:
return "linux";
case PlatformID.Win32NT:
case PlatformID.Win32S:
case PlatformID.Win32Windows:
return "windows";
default:
return "common";
}
}


internal static IEnumerable<string> ListPlatform()
{
using (var conn = new SqliteConnection("Data Source=" + Program.DbPath + ";")) {
conn.Open();
using (var command = new SqliteCommand("SELECT DISTINCT platform FROM pages", conn)) {
using (SqliteDataReader reader = command.ExecuteReader()) {
SortedSet<string> platform = new SortedSet<string>();
while (reader.Read()) platform.Add(reader.GetString(0));

return platform;
}
}
}
}


internal static List<string> GetPreferredLanguages()
{
var valid = new List<string>();
var languages = ListLanguages();
if (languages.Contains(Program.Language)) valid.Add(Program.Language);

Environment.GetEnvironmentVariable("LANGUAGE")
?.Split(':')
.Where(x => !x.Equals(string.Empty))
.ToList().ForEach(delegate(string s) {
valid.AddRange(languages.Where(l => l.Substring(0, 2).Equals(s)));
});

return valid;
}

internal static List<string> GetEnvLanguages()
{
var languages = new List<string> {Program.Language};
var envs = Environment.GetEnvironmentVariable("LANGUAGE")
?.Split(':')
.Where(x => !x.Equals(string.Empty))
.ToList();
if (envs != null) languages.AddRange(envs);
return languages;
}


internal static string GetPreferredLanguageOrDefault()
{
var languages = ListLanguages();
if (languages.Contains(Program.Language)) return Program.Language;

var prefLanguages = Environment.GetEnvironmentVariable("LANGUAGE")
?.Split(':')
.Where(x => !x.Equals(string.Empty));

if (prefLanguages != null) {
foreach (string lang in prefLanguages) {
try {
return languages.First(x => x.Substring(0, 2).Equals(lang));
} catch (InvalidOperationException) { }
}
}

return Program.DefaultLanguage;
}


internal static ICollection<string> ListLanguages()
{
using (var conn = new SqliteConnection("Data Source=" + Program.DbPath + ";")) {
conn.Open();
using (var command = new SqliteCommand("SELECT DISTINCT lang FROM pages", conn)) {
using (SqliteDataReader reader = command.ExecuteReader()) {
var languages = new List<string>();
while (reader.Read()) languages.Add(reader.GetString(0));

return languages;
}
}
}
}


internal static bool CheckLanguage(string language)
{
using (var conn = new SqliteConnection("Data Source=" + Program.DbPath + ";")) {
conn.Open();
using (var command = new SqliteCommand("SELECT 1 FROM pages WHERE lang = @language", conn)) {
command.Parameters.Add(new SqliteParameter("@language", language));

using (SqliteDataReader reader = command.ExecuteReader()) {
return reader.HasRows;
}
}
}
}
}
}
Loading

0 comments on commit 9d6ca29

Please sign in to comment.