Building a command-line utility to search for WordPress content using .NET Core and System.Text.Json

Photo by @amartino20 / Unsplash.com

Recent weeks have been busy, and many things have demanded my attention. As a result I haven’t had too much time to build things, and I love to build things. So today, during a coffee break at work, I decided to spend 15 minutes to get something built. And it would need to be something I’d actually use.

Allow me to introduce – wpAPI_CLI, a simple and fast command-line utility to search for WordPress posts and their content.

Planning

I use Microsoft To Do to track ideas and topics I’d like to write about in the future. But after I’ve written an article and published it, I often cross it over in my To Do list and move on. So I needed a tool that quickly allows me to check against my published content if I’ve written about a specific topic.

In essence, my tool would work with a simple keyword:

wpAPI_CLI.exe <keyword>

WordPress exposes a REST API, and that REST API has a Search method. My tool would need to connect with this API, and execute a search using a keyword. The structure for the API call is:

/wp-json/wp/v2/posts?search=keyword&per_page=100

I added the &per_page=100 to get a reasonable amount of results. The default is 10.

Writing code

I just refreshed my laptop (more on that in a separate post a bit later), and had to re-install Visual Studio 2019. I created a new C# (and .NET Core) Console Project, and started hammering my code out. It’s pretty simple – but then again, so is my need.

First, as I’m calling a REST API, I need System.Net.Http, and for parsing the resulting JSON, I wanted to use the new System.Text.Json.

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Web;

I’ll then define a few variables in my Main() class:

string WP_HOST = "https://jussiroine.com";
string WP_API = "/wp-json/wp/v2/posts";
string WP_METHOD = "?search";
string WP_PARAMS = "&per_page=100";

I’ll pick up the keyword directly from the command-line. As I only had 15 minutes I decided to blindly trust the user (me) in inputting something usable:

string WP_KEYWORD = args[0];

Next, I’ll call the API and construct my query:

HttpClient client = new HttpClient();
var response = client.GetStringAsync(WP_HOST + WP_API + WP_METHOD + "=" + WP_KEYWORD + WP_PARAMS).Result;

And from this result, I’ll parse through all links:

var document = JsonDocument.Parse(response);
var root = document.RootElement;

var items = new List<string>();

And now items holds all the posts, which I’ll then need to parse into something usable:

int i = 0; 
foreach (var prop in root.EnumerateArray())
{
	i++; 
	// title - remove {rendered..}
	var rawTitle = JsonDocument.Parse(prop.GetProperty("title").ToString());
	var postTitle = rawTitle.RootElement.GetProperty("rendered").ToString();

	// strip HTML entities from title
	postTitle = HttpUtility.HtmlDecode(postTitle.ToString());
	postTitle = Regex.Replace(postTitle, "<.*?>", String.Empty);
	postTitle = Regex.Replace(postTitle, @"^\s+$[\r\n]*", string.Empty, RegexOptions.Multiline);

	// postLink
	var postLink = prop.GetProperty("link").ToString();

	Console.WriteLine("{0}", postLink);
}

And that’s it!

Trying it out

Time to try it out! I built this to an executable, and ran it with a few keywords to test:

Future betterments

For a future coffee break, I already came up with an interesting list of opportunities to work with:

  • Move the search logic (REST API query, essentially) to be hosted in Azure Functions
  • Local caching
  • Performance metrics – perhaps in Azure App Insights
  • Better command-line parameter handling
  • Highlight relevant line of text in content when it matches the keyword being search
  • Consider security a bit more

For now, I’m able to use this little tool and it’s already proving to be quite useful!