Skip to content

Commit

Permalink
Get all words, words that contain and/or start with a sequence of let…
Browse files Browse the repository at this point in the history
…ters.

Refactoring.
  • Loading branch information
josago97 committed Oct 17, 2020
1 parent 3369867 commit dfeeac2
Show file tree
Hide file tree
Showing 5 changed files with 269 additions and 77 deletions.
31 changes: 29 additions & 2 deletions RAE.Demo/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ class Program
GetKeysAsync,
SearchWordAsync,
WordOfTheDayAsync,
FetchRandomWorldAsync
FetchRandomWorldAsync,
GetRandomWorldAsync,
GetWordsStartWithAsync,
GetWordsContainAsync,
GetAllWordsAsync
};

static async Task Main()
Expand All @@ -34,7 +38,7 @@ static async Task Main()

static async Task GetKeysAsync()
{
var query = "hola";
var query = "w";
var keys = await drae.GetKeysAsync(query);

Console.WriteLine($"GetKeys ({query}): {string.Join(", ", keys)}");
Expand Down Expand Up @@ -70,5 +74,28 @@ static async Task FetchRandomWorldAsync()
Console.WriteLine($"Definitions of {word.Content}:");
Array.ForEach(definitions, Console.WriteLine);
}

static async Task GetWordsStartWithAsync()
{
string character = "A";
string[] words = await drae.GetWordsStartWithAsync(character);

Console.WriteLine($"There are {words.Length} words in the dictionary that start with '{character}'");
}

static async Task GetWordsContainAsync()
{
string character = "A";
string[] words = await drae.GetWordsContainAsync(character);

Console.WriteLine($"There are {words.Length} words in the dictionary that contain '{character}'");
}

static async Task GetAllWordsAsync()
{
string[] allWords = await drae.GetAllWordsAsync();

Console.WriteLine($"There are {allWords.Length} words in the dictionary");
}
}
}
123 changes: 48 additions & 75 deletions RAE/DRAE.cs
Original file line number Diff line number Diff line change
@@ -1,30 +1,17 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Linq;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace RAE
{
/*
Based on information obtained from:
Basado en la información obtenida de:
https://devhub.io/repos/mgp25-RAE-API
*/
public class DRAE
{
private const string URLBASE = "https://dle.rae.es/data";
private const string TOKEN = "cDY4MkpnaFMzOmFHZlVkQ2lFNDM0";

private HttpClient _httpClient;
private RAEAPI _raeAPI;
private ListaPalabrasAPI _listaPalabrasAPI;

public DRAE()
{
_httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", TOKEN);
_raeAPI = new RAEAPI();
_listaPalabrasAPI = new ListaPalabrasAPI();
}

/// <summary>
Expand All @@ -35,17 +22,18 @@ public DRAE()
/// <para>The id of the word to search.</para>
/// <para>El id de la palabra a buscar.</para>
/// </param>
public async Task<string[]> FetchWordByIdAsync(string wordId)
public Task<string[]> FetchWordByIdAsync(string wordId)
{
var response = await _httpClient.GetStringAsync($"{URLBASE}/fetch?id={wordId}");

MatchCollection matches = Regex.Matches(response, "<p class=\"(?:j|m)\".*?>.*?</p>");

string[] definitions = matches.Cast<Match>()
.Select(m => Regex.Replace(m.Value, "<.*?>", ""))
.ToArray();
return _raeAPI.FetchWordByIdAsync(wordId);
}

return definitions;
/// <summary>
/// <para>Get all the words that exist.</para>
/// <para>Obtiene todas las palabras que existen.</para>
/// </summary>
public Task<string[]> GetAllWordsAsync()
{
return _listaPalabrasAPI.GetAllWordsAsync();
}

/// <summary>
Expand All @@ -56,49 +44,53 @@ public async Task<string[]> FetchWordByIdAsync(string wordId)
/// <para>The base word.</para>
/// <para>La palabra base.</para>
/// </param>
public async Task<List<string>> GetKeysAsync(string query)
public Task<string[]> GetKeysAsync(string query)
{
string response = await _httpClient.GetStringAsync($"{URLBASE}/keys?q={query}&callback=");
string json = Regex.Match(response, @"\[.*?\]").Value;

var keys = JsonConvert.DeserializeObject<List<string>>(json);

return keys;
return _raeAPI.GetKeysAsync(query);
}

/// <summary>
/// <para>Get a random word.</para>
/// <para>Obtiene una palabra aleatoria.</para>
/// </summary>
public async Task<Word> GetRandomWordAsync()
public Task<Word> GetRandomWordAsync()
{
string response = await _httpClient.GetStringAsync($"{URLBASE}/random");

string idFormat = "article id=\"";
Match idMatch = Regex.Match(response, $@"{idFormat}\w+");
string id = Regex.Replace(idMatch.Value, idFormat, "");

string contentFormat = "class=\"f\".*?>";
Match contentMatch = Regex.Match(response, $@"{contentFormat}\w[\,\s\w]*");
string content = Regex.Replace(contentMatch.Value, contentFormat, "");

return new Word(id, content);
return _raeAPI.GetRandomWordAsync();
}

/// <summary>
/// <para>Get the word of the day.</para>
/// <para>Obtiene la palabra del día.</para>
/// </summary>
public async Task<Word> GetWordOfTheDayAsync()
public Task<Word> GetWordOfTheDayAsync()
{
string response = await _httpClient.GetStringAsync($"{URLBASE}/wotd?callback=");
string json = response.Substring(1, response.Length - 2);
JObject jobject = JObject.Parse(json);
return _raeAPI.GetWordOfTheDayAsync();
}

string id = jobject.Value<string>("id");
string content = jobject.Value<string>("header");
/// <summary>
/// <para>Gets the words that start with a sequence of letters.</para>
/// <para>Obtiene las palabras que empiezan con una secuencia de letras.</para>
/// </summary>
/// <param name="query">
/// <para>Sequence of letters to search.</para>
/// <para>Secuencia de letras a buscar.</para>
/// </param>
public Task<string[]> GetWordsStartWithAsync(string query)
{
return _listaPalabrasAPI.GetWordsStartWithAsync(query);
}

return new Word(id, content);
/// <summary>
/// <para>Gets the words that contain a sequence of letters.</para>
/// <para>Obtiene las palabras que contienen una secuencia de letras.</para>
/// </summary>
/// <param name="query">
/// <para>Sequence of letters to search.</para>
/// <para>Secuencia de letras a buscar.</para>
/// </param>
public Task<string[]> GetWordsContainAsync(string query)
{
return _listaPalabrasAPI.GetWordsContainAsync(query);
}

/// <summary>
Expand All @@ -113,28 +105,9 @@ public async Task<Word> GetWordOfTheDayAsync()
/// <para>If true it will take secondary entries.</para>
/// <para>Si es verdadero cogerá entradas secundarias.</para>
/// </param>
public async Task<List<Word>> SearchWordAsync(string word, bool allGroups = true)
{
string response = await _httpClient.GetStringAsync($"{URLBASE}/search?w={word}");
JToken jtoken = JToken.Parse(response);

var words = new List<Word>();
foreach (var w in jtoken.SelectToken("res"))
{
int group = w.Value<int>("grp");

if (allGroups || group == 0)
{
string id = w.Value<string>("id");
string content = w.Value<string>("header");

Match contentMatch = Regex.Match(content, @"[A-Za-z/-]+");

words.Add(new Word(id, contentMatch.Success ? contentMatch.Value : content));
}
}

return words;
public Task<List<Word>> SearchWordAsync(string word, bool allGroups = true)
{
return _raeAPI.SearchWordAsync(word, allGroups);
}
}
}
87 changes: 87 additions & 0 deletions RAE/ListaPalabrasAPI.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using HtmlAgilityPack;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;

namespace RAE
{
internal class ListaPalabrasAPI
{
private const string URLBASE = "https://www.listapalabras.com";
private static readonly string[] ALPHABET = new[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "Ñ", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };

private HttpClient _httpClient;

public ListaPalabrasAPI()
{
_httpClient = new HttpClient();
}

public async Task<string[]> GetAllWordsAsync()
{
List<string> words = new List<string>();

await Task.Run(() => Array.ForEach(ALPHABET, s => words.AddRange(GetWordsStartWithAsync(s).Result)));

return words.ToArray();
}

public async Task<string[]> GetWordsStartWithAsync(string query)
{
HtmlDocument page = await LoadPageAsync($"{URLBASE}/palabras-con.php?letra={query}&total=s");

return GetWords(page);
}

public async Task<string[]> GetWordsContainAsync(string query)
{
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("busqueda", query)
});

HtmlDocument page = await LoadPageAsync($"{URLBASE}/palabras-con.php", content);

return GetWords(page);
}

private async Task<HtmlDocument> LoadPageAsync(string url)
{
var document = new HtmlDocument();

using (Stream documentStream = await _httpClient.GetStreamAsync(url))
{
document.Load(documentStream);
}

return document;
}

private async Task<HtmlDocument> LoadPageAsync(string url, HttpContent content)
{
var document = new HtmlDocument();

var response = await _httpClient.PostAsync(url, content);

using (Stream documentStream = await response.Content.ReadAsStreamAsync())
{
document.Load(documentStream);
}

return document;
}

private string[] GetWords(HtmlDocument document)
{
string[] words = document.GetElementbyId("columna_resultados_generales")
.SelectNodes("descendant::*[@id='palabra_resultado']")
.Select(n => n.InnerText.Trim(' ', '\n'))
.ToArray();

return words;
}
}
}
1 change: 1 addition & 0 deletions RAE/RAE.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="HtmlAgilityPack" Version="1.11.24" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
</ItemGroup>

Expand Down
Loading

0 comments on commit dfeeac2

Please sign in to comment.