The newLISP on Rockets blog

 RSS Feed for this blog

Converting JSON data into a list

Post #: 81
Post type: Blog post
Date: 2013-01-30 16:28:47.000
Author: Rocket Man

JSON stands for the JavaScript Object Notation, and it's used by lots of applications because it's much more compact than the bulky XML format. It's also suspiciously similar to LISP lists, which isn't that surprising considering that JavaScript was originally written as a LISP interpreter.

The basic format is something like this:

"firstName": "John",
"lastName": "Smith",
"age": 25,
"address": {
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": 10021
"phoneNumber": [
"type": "home",
"number": "212 555-1234"
"type": "fax",
"number": "646 555-4567"

I've written a function in Rockets that converts this notation into a native newLISP list. Basically all I've done is replace { with ( and [ with (, then removed colons, commas, and other extraneous syntax. I ran into a small problem with very large text strings, because newLISP's internal list evaluator doesn't like them and returns a "string token too long" error. To fix this, I put [text] and [/text] in place of everything that had quotes, which tells newLISP's internal evaluator to treat it as a long string of text. Using (read-eval) I convert this long string of long strings back into a list, and all the [text] and [/text] goes away and you have a normal list!

The function is called (convert-json-to-list) and it's included in Rockets. I'm already finding it useful for my new project.

Comments (5)

Views: 5652

How to extract data from an RSS feed in Rockets

Post #: 80
Post type: Blog post
Date: 2013-01-25 14:12:04.000
Author: Rocket Man

RSS feeds are useful and great, but the XML structure they come in is rather unwieldy to read through and parse. newLISP has a great function called (parse-xml) that converts an XML tree into a list, but now you just have an unwieldy list. It's helpful to be able to extract only the data we want and put it in a simple nested list.

I've written a new function in Rockets that lets you do just that.

First, get the data from the RSS feed URL that you want:

(set 'feed-url "";))
(set 'rss-result (xml-parse (get-url feed-url)))

Now, we want to extract the fields "title", "author", and "link" from that feed.

(set 'field-result (get-fields-from-rss rss-result '("title" "author" "link")))

(field-result) will return the following:

(("News Post: The Book Of Divine Wisdom" " (Tycho)" "";)
("News Post: So many games!" " (Gabe)" "";)
...etc ... )

If a field isn't present in the RSS data, (field-result) will populate that part of the list with the "nil" value instead.

NOTE: Remove the spurious ";" characters in the example code here before running it

Happy RSSing!

Views: 4914

Copying Apache log files to a database

Post #: 79
Post type: Blog post
Date: 2013-02-15 10:57:40.000
Author: Rocket Man

Apache log files typically just sit around filling up your hard drive space, a vast array of text too unwieldy to search through.

A useful thing to do is to parse these files and copy them to a database. I've written a script that will do this using Rockets. It's not a web page-- it's a script that you should run from the command line (use sudo newlisp log-to-database.lsp) It will create a new database from scratch called SERVER-LOGS.db that you can then query and search using SQLite.

The script can be found here:

Note: I may be updating this later, as the database files seems quite large (only slightly smaller than the logs themselves)

Comments (1)

Views: 5076

How to implement New/Unread Posts in a forum

Post #: 78
Post type: Blog post
Date: 2013-01-16 14:14:11.000
Author: Rocket Man

This is a trickier issue than it appears at first.

The obvious solution is to just check the date of the last posted message and compare it with, say, the last time the user logged in. But in practice this doesn't work, because you want to view a post and have it removed from your "New" list right away, not at some later date. You actually have to bite the bullet and store a list of posts that you have read or unread. I chose "read" because by default users don't have anything in that list, which is easier to implement.

The list is stored as a string of post Id numbers, delimited by hyphens. When displaying the list of forum posts, it checks each one to see if the post Id is in your list of read posts, just by doing a (find) search on the string.

That part is easy. But what about when someone adds a new comment to a thread you've read? Ideally you want it to be bumped back to "Unread" status.

The solution I came up with is to get a list of every user's Read list whenever someone posts a comment. Then you loop through it and if you find the Post Id in there, you just snip it out using (replace).

Oh, I also added a "Mark All as Read" button, for people who just want all those pesky "New" icons to go away, RIGHT NOW. It gets a list of every post and adds them all to your Read list.

Is it as efficient as it could be? Will it bog down when you have a million users? I have no idea. I'll cross that bridge when I come to it. For now, it seems to work pretty well.

Comments (1)

Views: 5163

View counts!

Post #: 77
Post type: Blog post
Date: 2013-01-15 17:19:09.000
Author: Rocket Man

I've added a small feature that shows the number of views each forum thread or blog post has gained. Each time you view a thread in the forum view or view a complete blog post by clicking on the link, the number is bumped.

Because this is a new feature, all the old views aren't counted. :( So they are starting at zero.

This did require a change to the database, as I didn't already have the column "PostViews" in the Posts table. This can present a problem when people are upgrading from an earlier version of Rockets that doesn't have that column. I've updated setup-rockets.lisp to create this field when making a new database, but people's existing databases won't have it. I'll probably have to add a "update database to latest version" script that will just add the missing columns for people with older versions. One nice thing is that the database doesn't need any values in there. It just needs to be altered to add this missing field.

Comments (4)

Views: 4516

Happy New Year and a server upgrade!

Post #: 76
Post type: Blog post
Date: 2013-01-07 14:36:31.000
Author: Rocket Man

Welcome to 2013! It's fun living in the future.

I've upgraded the server from Ubuntu 10.04 to Ubuntu 12.04 LTS, so please let me know if there are any hiccups or strange behaviors on the site.

I'll be posting more soon!

Comments (34)

Views: 10249

Towards the creation of newLISP on Rockets installation scripts...

Post #: 73
Post type: Blog post
Date: 2012-12-12 15:07:52.000
Author: Rocket Man

I'm now starting to use Rockets for projects at work, so I need a way to create the user database from scratch. Anyone wanting to start using the newLISP on Rockets Blog source code will need to do the same thing. So our desires align!

I've created a simple installation script called setup-rockets.lisp. It needs to be run from the command line:

sudo newlisp setup-rockets.lisp

This will ask you a few questions (database, name, password, etc) and set up a new database for you with the right tables and create an admin user. Obviously you never want this to be run by someone else over the web, so make sure that it can't be viewed over your web server (either by permissions, or by using my Apache .htaccess directive that excludes all files ending in .lisp from being viewed (.lsp files are fine though!)

# Prevent framework source from being accessed
<Files ~ "\.lisp$">
Order allow,deny
Deny from all

# Prevent database files from being accessed
<Files ~ "\.db$">
Order allow,deny
Deny from all

Once the database is created (it will append the ".db" extension as well... you notice I've excluded those files so that you can't download the database from the web or via wget) you need to make sure it has the permissions to read and write by the owner:

chown www-data:www-data DATABASENAME.db
chmod 755 DATABASENAME.db

and you should be ready to go!

Comments (20)

Views: 5318

An easy way to increase your post count...

Post #: 72
Post type: Blog post
Date: 2012-12-03 13:28:52.000
Author: Rocket Man

Is now to post more!

Now comments on blog posts, forum posts, or replies to forum posts will count towards your post count total. This feature wasn't implemented before, so I've gone ahead and retroactively counted everyone's posts (thanks to the COUNT(*) features of SQLite) to ensure not a single post of yours goes uncounted!

Post counts are a fun way to keep track of contributions to an online community. Implementing the +1 bump every time a user posts was quite easy:

; now update the user's postcount! postcount++!!
(set 'UserId Rockets:UserId)
(set 'UserPosts (++ Rockets:UserPosts))
(update-record "Users" UserId UserPosts)

I was pretty happy to be able to use the ++ function given that on many online forums, people post things like "Postcount++" when they post. Of course, this is LISP, so the ++ comes first.

You can view your post count by going to Edit Profile (click your name on the upper right to pull down the user menu) or simply by viewing a forum thread to see everyone's post counts! I didn't put post counts in the Blog view because blog posts are supposed to be, well, more about the post itself than about everyone increasing post counts. But if you view a blog thread in Forum view you will see that the appropriate counts have been updated.

At some point I will implement ranks based on postcount, which will also appear in the forum view and in your profile. So get out there and start posting!

Comments (6)

Views: 4830

Calendars, date-pickers, and your birthday!

Post #: 69
Post type: Blog post
Date: 2012-11-27 15:14:43.000
Author: Rocket Man

Happy Birthday! Or is it?

It's handy in web applications to have a way to select dates in a rigid format, and to have a little calendar to make it easier for users to select dates. I've incorporated a plugin for Bootstrap that does just that.

Inside a form, just use the following code:

(form-datepicker "Enter your birth date" "date" show-birthdate "dp1")

This will open up a little form box where you can type in a date, or if you click on the date box a calendar pops up.

To see it in action, go to your User Profile page (click on your name on the upper right) and you can set your birthdate there! At some point I'll add a little feature that will send you a Happy Birthday email, just for fun.

When I was implementing this I discovered that SQLite wants dates in a YYYY-MM-DD HH:MM:SS.000 format and this calendar wants it in MM-DD-YYYY format. It's quite easy to convert between the two, but I might add some date functions to Rockets to make this easier. Of course everyone has their own preferred date format, which complicates things still further...

Comments (6)

Views: 4438

Avatar uploads are working!

Post #: 68
Post type: Blog post
Date: 2012-11-19 20:52:42.000
Author: Rocket Man

After a fair bit of fiddling, I've gotten avatar uploads working on the newLISP on Rockets blog. Now you can upload your own image.

The code to display a file upload form looks like this:

(displayln "<p>Upload new avatar (all avatars scaled to 64x64 pixels): <form name='FileUpload' action='rockets-avatarupload.lsp' method='POST' enctype='multipart/form-data'><input type='file' id='uploadName' name='uploaded_data' onChange='this.form.textname.value = this.value'><input type='hidden' name='textname'><input type='submit' value='Upload' name='submit'></form>")

The form variables are put into the ($POST) tree, along with a variable called "filename" that holds the file name, and "binary-data" that holds the file itself.

To retrieve these from ($POST), just use the following code:

(set 'file-name ($POST "filename"))
(set 'file-binary ($POST "binary-data"))

Then to save the file , I use the following command:

(write-file (string "images/avatars/" file-name) file-binary)

One bit of warning: you will need to set the ownership permissions on the directory where you are saving these files to something that the Apache user has write access to. In Ubuntu this was something like:

sudo chown www-data:www-data images/avatars

And that's it! The avatar images are not scaled when they are uploaded, but they are displayed with fixed dimensions of 64x64 pixels. This means if you upload a larger image it will look tiny. In the future I will add a module that automatically resizes files to a dimension of your choice, but for now, try to keep avatars to no larger than 100x100.

Comments (2)

Views: 4682