Extending SubText to report Future Posts

time to read 3 min | 449 words

Since I am making so much use of future posts recently, I decided that it would be interesting to have a sidebar that shows the future posts. The problem is that I really don’t want to mess around with SubText.

This is not a slight against SubText, it has served me well for a long time. It is simply that for what I wanted, the number of steps that I would have to go through is way too long:

  • Get the relevant source
  • Compile it on my machine
  • Figure out SubText’s architecture and where I should make my changes
  • Upload a new version of the blog engine

It is possible, but it just take too long. Moreover, it would most certainly break the next time that I would update SubText, because I would forget all about it.

But it is not the only way to get stuff done, however. Here is my solution:

Update: I actually had a bug here related to time zone handling, fixed now.

Update 2: I used the 3.5 TimeZone semantics for this, but my server is running 2.0, use an okay hack instead. And fixed potential issue with < & > in the titles.

<%@ Page Language="C#" %>
<%@ OutputCache Duration="60" VaryByParam="None" %>

<%@ Import Namespace="System.Data.SqlClient" %>
<%@ Import Namespace="System.Configuration" %>
<ul>
<%
string connectionString = ConfigurationManager.ConnectionStrings["subtextData"].ConnectionString;
using(SqlConnection connection = new SqlConnection(connectionString))
{
	connection.Open();
	
	using(SqlCommand cmd = connection.CreateCommand())
	{
		cmd.CommandText = @"
select top 15 Id, DateSyndicated, Title from subtext_Content
where DateSyndicated > @nowIsrael
order by DateSyndicated
";
		DateTime nowIsrael = DateTime.UtcNow.AddHours(3);
		
		cmd.Parameters.AddWithValue("nowIsrael",nowIsrael);
		
		using(SqlDataReader reader = cmd.ExecuteReader())
		{
			if(reader.HasRows == false)
			{
				%><li>Queue is empty</li><%
			}
			while(reader.Read())
			{
				DateTime dateSyndicated = (DateTime)reader["DateSyndicated"];
				string title = (string) reader["Title"];
				string formattedSyndication;
				TimeSpan timeLeft = dateSyndicated - DateTime.Now;
				
				if (timeLeft.Days > 7)
					formattedSyndication = timeLeft.Days / 7 + " weeks " + timeLeft.Days % 7 + " days";
				else if (timeLeft.Days > 0)
					formattedSyndication = timeLeft.Days + " days";
				else if (timeLeft.Hours > 0)
					formattedSyndication = timeLeft.Hours + " hours";
				else if (timeLeft.Minutes > 0)
					formattedSyndication = timeLeft.Minutes + " minutes";
				else
					formattedSyndication = "In a moment";
				
				%>
				<li><%= formattedSyndication %> <br /> <%= Server.HtmlEncode(title) %></li>
				<%
			}			
		}
	}
}
%>
</ul>

And then it was just a matter of changing the template to include the following JavaScript:

$('#futurePosts').load('http://ayende.com/Blog/FuturePosts.aspx');

And that is it. It works, it is safe, it can’t really break anything, and it will probably survive blog upgrades.