so i got a chatbot going with a word definition command and it's written in C#. .net does not have a native json parsing pile of trash so I used Wordnik's XML api. come a few weeks ago and the definition command stops working, i check why and it turns out they shut down their XML apis. best part about it is that i didn't get an email about it or anything and also the return data of the api telling you the endpoints were deprecated are json encoded.
It wasn't all bad because it lead to this beauty of a commit comment:
Now here's the diff of the change, I just said fuck it and used Regex to swoop the data out of the json encoded string. It's horribly imperfect but works good enough for my needs.
this post has no real point or purpose, i just wanted to share the commit comment and my beautiful solution
It wasn't all bad because it lead to this beauty of a commit comment:
Now here's the diff of the change, I just said fuck it and used Regex to swoop the data out of the json encoded string. It's horribly imperfect but works good enough for my needs.
diff --git a/Satori/Wordnik/DefineCommand.cs b/Satori/Wordnik/DefineCommand.cs
index 5ad03b1..3319911 100644
--- a/Satori/Wordnik/DefineCommand.cs
+++ b/Satori/Wordnik/DefineCommand.cs
@@ -25,6 +25,8 @@ public override void Dispatch(StringBuilder output, CommandArgs args)
if (!int.TryParse(args.Arguments.Skip(2).Take(1)?.FirstOrDefault() ?? string.Empty, out int page))
page = 1;
+ else
+ word = word.Substring(0, word.LastIndexOf(' '));
if (string.IsNullOrEmpty(word))
return;
diff --git a/Satori/Wordnik/WordDefinition.cs b/Satori/Wordnik/WordDefinition.cs
index 71b3a39..486bddd 100644
--- a/Satori/Wordnik/WordDefinition.cs
+++ b/Satori/Wordnik/WordDefinition.cs
@@ -1,17 +1,11 @@
-using System.Xml.Serialization;
-
-namespace Satori.Wordnik
+namespace Satori.Wordnik
{
- [XmlType(@"definition")]
public sealed class WordDefinition
{
- [XmlElement(@"text")]
public string Text { get; set; }
- [XmlElement(@"word")]
public string Word { get; set; }
- [XmlElement(@"partOfSpeech")]
public string PartOfSpeech { get; set; }
}
}
diff --git a/Satori/Wordnik/WordnikApi.cs b/Satori/Wordnik/WordnikApi.cs
index d12182d..c9bc786 100644
--- a/Satori/Wordnik/WordnikApi.cs
+++ b/Satori/Wordnik/WordnikApi.cs
@@ -1,16 +1,15 @@
using System;
using System.Collections.Generic;
-using System.IO;
using System.Linq;
using System.Net.Http;
-using System.Xml.Serialization;
+using System.Text.RegularExpressions;
namespace Satori.Wordnik
{
public sealed class WordnikApi : IDisposable
{
private const string BASE_URL = @"https://api.wordnik.com/v4/";
- private const string WORD_API = BASE_URL + @"word.xml/";
+ private const string WORD_API = BASE_URL + @"word.json/";
private readonly IBindable<string> ApiKey;
private readonly HttpClient HttpClient;
@@ -19,6 +18,8 @@ public sealed class WordnikApi : IDisposable
private Dictionary<string, IEnumerable<WordDefinition>> Definitions = new Dictionary<string, IEnumerable<WordDefinition>>();
+ public readonly Regex DataGrab = new Regex("\"(partOfSpeech|word|text)\":\"(.*?)\"");
+
public WordnikApi(HttpClient client, IBindable<string> apiKey)
{
HttpClient = client;
@@ -27,26 +28,78 @@ public WordnikApi(HttpClient client, IBindable<string> apiKey)
public IEnumerable<WordDefinition> DefineWord(string word)
{
- word = word.Replace(@" ", @"%20");
- word = string.Join(string.Empty, word.Where(c => char.IsLetterOrDigit(c) || c == '+')).ToLowerInvariant();
-
- if (Definitions.ContainsKey(word))
- return Definitions[word];
-
- string url = WORD_API + word + @"/definitions?limit=200&includeRelated=false&sourceDictionaries=all&useCanonical=true&includeTags=false&api_key=" + ApiKey.Value;
-
- XmlSerializer xml = new XmlSerializer(typeof(List<WordDefinition>), new XmlRootAttribute(@"definitions"));
- List<WordDefinition> defs;
-
- using (HttpResponseMessage r = HttpClient.GetAsync(url).Result)
- using (HttpContent c = r.Content)
- using (Stream s = c.ReadAsStreamAsync().Result)
- defs = xml.Deserialize(s) as List<WordDefinition>;
+ try
+ {
+ word = word.Replace(@" ", @"%20");
+ word = string.Join(string.Empty, word.Where(c => char.IsLetterOrDigit(c) || c == '+')).ToLowerInvariant();
+
+ if (Definitions.ContainsKey(word))
+ return Definitions[word];
+
+ string url = WORD_API + word + @"/definitions?limit=200&includeRelated=false&sourceDictionaries=all&useCanonical=true&includeTags=false&api_key=" + ApiKey.Value;
+
+ string output;
+
+ using (HttpResponseMessage r = HttpClient.GetAsync(url).Result)
+ using (HttpContent c = r.Content)
+ output = c.ReadAsStringAsync().Result;
+
+ List<WordDefinition> defs = new List<WordDefinition>();
+ MatchCollection matches = DataGrab.Matches(output);
+ WordDefinition current = new WordDefinition();
+
+ foreach (Match match in matches)
+ {
+ string key = match.Groups[1].Value;
+ string value = match.Groups[2].Value;
+
+ switch (key)
+ {
+ case @"partOfSpeech":
+ if (!string.IsNullOrEmpty(current.PartOfSpeech))
+ {
+ defs.Add(current);
+ current = new WordDefinition();
+ }
+
+ current.PartOfSpeech = value;
+ break;
+
+ case @"word":
+ if (!string.IsNullOrEmpty(current.Word))
+ {
+ defs.Add(current);
+ current = new WordDefinition();
+ }
+
+ current.Word = value;
+ break;
+
+ case @"text":
+ if (!string.IsNullOrEmpty(current.Text))
+ {
+ defs.Add(current);
+ current = new WordDefinition();
+ }
+
+ current.Text = value;
+ break;
+ }
+ }
+
+ if (!defs.Contains(current) && !string.IsNullOrEmpty(current.PartOfSpeech)
+ && !string.IsNullOrEmpty(current.Word) && !string.IsNullOrEmpty(current.Text))
+ defs.Add(current);
- if (defs != null)
Definitions.Add(word, defs);
- return defs;
+ return defs;
+ }
+ catch
+ {
+ Definitions.Remove(word);
+ return Enumerable.Empty<WordDefinition>();
+ }
}
~WordnikApi()
this post has no real point or purpose, i just wanted to share the commit comment and my beautiful solution