Hacking on GNU social: Unicode Smileys
As you probably know already, GNU social is a GNU Affero licensed microblogging server software written in PHP that implements the OStatus protocol, an open standard for distributed status updates.
Everyone can deploy her own server and follow people in her own server or any other, as I explained here https://www.fsf.org/blogs/community/thousands-of-spaniards-leave-twitter-for-gnu-social.
I have run my own server for quite a long time, and the time to make some contribution back to this great software has come! I always thought that it would be great to take advantage of Unicode characters to insert some emojis in GNU social notices. You can always copy and paste these entities (http://unicode-table.com/en/) but the experience is better if that feature is integrated, so I decided to create a plugin.
Where do I start to hack
The best way to start is to follow best practices. These practices are translated into code in a plugin named
Sample that is distributed along with the server. That Sample plugin can be found here.
The essential part is a PHP file that defines a class that inherits from Plugin. So we start with this:
class SmileysUnicodePlugin extends Plugin
You don’t really start with a blank class, because you can copy standard methods from the sample plugin, but make sure you understand what you are copying and why. Each request to a GNU social server can be seen as a dialog between the main engine and the plugins:
Engine: I have created the main header, have you got something to do?
Engine: I have created the main navbar, have you got something to insert?
Plugin: no, sir
Engine: Well, I’ve spitted out my jQuery files, anything to add?
Plugin: Certainly! Please add references to these files!
This is done because we implement a method like this:
function onEndShowJQueryScripts(Action $action)
//This is the file to modify if you want to add or remove unicode sets
//This is the plugin main jQuery file
If you reveal the source code of the final page, you will see references to these two files. There is a similar method to insert your own CSS code (
Third party plugins are installed normally in
[GNU Social root]/local/plugins. With a file for the plugin main class named
SmileysUnicodePlugin.php that defines a class
Plugin, that defines these two methods (
onEndShowStyles), we are ready to deploy our first plugin. Create a directory structure for the plugin:
Now, modify the file
[GNU social root] to add this directive:
And you are ready to go, no server restart required. The GNU social cycle will load your plugin and insert your code in the final result.
Developing the plugin
I wanted to create the plugin with some restrictions:
- Work with all themes.
- Little or no modification at all necessary for the HTML code of the upstream themes.
That’s why we call it a plugin. If you find yourself hacking on server software you are creating a fork and your code will not be portable to other nodes. The first challenge was where to put the control that opens a dialog containing the entities. This is tricky because it has to work in a predictable manner with all themes. I decided to insert this little snippet inside the
fieldset of the form for a new notice:
In each request, the engine only creates one form, that of the main notice. It doesn’t create a form for the replies. Instead, it is created every time a user activates a reply by copying the main notice form with jQuery. This is important, because you can’t add the label to a form that doesn’t exist yet. So I put it there and expect it to be copied along with the rest of the form. This design decision has some effects on the jQuery behaviour assignment that we will see later.
When you hack on GNU social you have jQuery and jQuery UI available. This is very convenient to rapidly build interfaces. I chose the controls
Tabs to present the Unicode entities.
As I said earlier, I can insert a control and assign a click function to it with jQuery if that control exists, but the controls for opening the dialog in the replies don’t exist until I click on a «reply to» button in any notice. But jQuery, great library as it is, brings us a solution. If I assign this click function to
document and specify a selector, it will automatically add the behaviour to any new element that matches the selector.
Having worked around that, I only have to make sure that each click on a smiley puts it in the appropiate form (the main one or a reply form).
Extending the icon sets
Have a look at
assets/js/config.js. If you want new icon sets (see http://unicode-table.com/en/) you only have to find the initial (decimal) number and the final number and add the set as I have done with «Emoji», «Dingbats» and «Miscellaneous». Not all entities will appear on all combinations of operating system/locale/browser but you can try!
Show me the code!
And last but not least, browse the code for this plugin in https://git.gnu.io/danielside/SmileysUnicode. If you maintain a GNU social node, feel free to install it and hack around.