{"id":319,"date":"2017-04-23T12:32:54","date_gmt":"2017-04-23T00:32:54","guid":{"rendered":"https:\/\/eion.robbmob.com\/blog\/?p=319"},"modified":"2017-04-23T12:32:54","modified_gmt":"2017-04-23T00:32:54","slug":"four-more-prpls","status":"publish","type":"post","link":"https:\/\/eion.robbmob.com\/blog\/2017\/04\/23\/four-more-prpls\/","title":{"rendered":"Four more prpls"},"content":{"rendered":"<p>It suddenly occurred to me that I never posted about the new prpls that I&#8217;ve written since the Hangouts prpl. Today we shall fix that.<br \/>\n<!--more--><\/p>\n<h2>Rocket.Chat<\/h2>\n<p>The first plugin since Hangouts was one for <a href=\"https:\/\/rocket.chat\/\" target=\"_blank\" rel=\"noopener noreferrer\">Rocket.Chat<\/a>, an open-source team communications platform (read: Slack-clone) that uses the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Distributed_Data_Protocol\" target=\"_blank\" rel=\"noopener noreferrer\">Meteor DDP<\/a> protocol (ugh, <a href=\"https:\/\/en.wikipedia.org\/wiki\/RAS_syndrome\" target=\"_blank\" rel=\"noopener noreferrer\">RAS syndrome<\/a>!) for syncing data over websockets.<\/p>\n<p>What&#8217;s most interesting about this prpl is its use of <a href=\"https:\/\/en.wikipedia.org\/wiki\/Markdown\" target=\"_blank\" rel=\"noopener noreferrer\">Markdown<\/a> for rich-text formatting, rather than HTML; a first for a protocol for me. After hunting around for a few C or C++ libraries for converting Markdown into HTML so that it can be rendered in libpurple, I ended up settling on <a href=\"http:\/\/www.pell.portland.or.us\/~orc\/Code\/discount\/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">libdiscount2<\/a> and a home-grown parser for HTML to Markdown using <a href=\"https:\/\/developer.gnome.org\/glib\/stable\/glib-Simple-XML-Subset-Parser.html\" target=\"_blank\" rel=\"noopener noreferrer\">GMarkupParser<\/a>.<\/p>\n<p>Unfortunately Rocket.Chat doesn&#8217;t have a very stable API, so some calls will have parameters in different order&#8217;s depending on what version of the Rocket.Chat server the plugin is connected to. Also annoying was that the demo server has different API&#8217;s and responses than a normal Rocket.Chat server would, so getting the plugin working against the demo server then didn&#8217;t work against a regular server that I also tested with.<\/p>\n<p>I managed to get most features implemented, including IM&#8217;s and group chats, as well as a pseudo-buddy list based on people you&#8217;ve messaged (with an &#8216;auto add&#8217; account setting)<\/p>\n<h2>Battle.net v2<\/h2>\n<p>aka <a href=\"https:\/\/worldofwarcraft.com\/en-us\/news\/20297652\/battlenet-update-9-21-2016\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Blizzard Client<\/a>, not to be confused with Battle.net Classic. Battle.net is a <a href=\"https:\/\/developers.google.com\/protocol-buffers\/\" target=\"_blank\" rel=\"noopener noreferrer\">protobuf<\/a>-based protocol with a <a href=\"https:\/\/github.com\/HearthSim\/python-bnet\/wiki\/1.-Overview\" target=\"_blank\" rel=\"noopener noreferrer\">unique RPC mechanism<\/a>. Kudos to the <a href=\"https:\/\/hearthsim.info\/\" target=\"_blank\" rel=\"noopener noreferrer\">HearthSim<\/a> for figuring it all out \ud83d\ude42<\/p>\n<p>What&#8217;s interesting about this protocol is that it sends &#8220;Player X is in game Y&#8221; information as a numeric code rather than as a string, in order for the client to handle translations without the protocol having to worry about it. Also interesting is that two games can share the same numeric code to mean two totally different user statuses. What&#8217;s also unique about this protocol is that the &#8216;Away&#8217; presence is set as a flag, similar to AIM so technically a user can say they&#8217;re Online, Away and Busy all at the same time (although the UI prevents this in practice). libpurple has support for statuses as flags, but the Pidgin GUI won&#8217;t let you set a status that way, so there&#8217;s a bit of hackery to be able to set a status as if it weren&#8217;t a flag, but receive a status as if it were a flag.<\/p>\n<p>I&#8217;ve only added support for IM&#8217;s and not chats at this stage, but so far there hasn&#8217;t been any demand for group chats. Maybe in the future?<\/p>\n<h2>Discord<\/h2>\n<p>Discord is like &#8220;Slack for Gamers&#8221;. It&#8217;s a hosted team collaboration focused at the gaming market. It&#8217;s API is <a href=\"https:\/\/discordapp.com\/developers\/docs\/topics\/gateway#connecting\" target=\"_blank\" rel=\"noopener noreferrer\">primarily Websocket-based<\/a> with <a href=\"https:\/\/discordapp.com\/developers\/docs\/reference\" target=\"_blank\" rel=\"noopener noreferrer\">HTTP\/REST API<\/a> calls to compliment.<\/p>\n<p>There&#8217;s been a <a href=\"https:\/\/github.com\/sm00th\/bitlbee-discord#readme\" target=\"_blank\" rel=\"noopener noreferrer\">Discord plugin for bitlbee<\/a> around for over a year now, and I&#8217;ve had requests to bring that to Pidgin. Initially I tried porting the plugin to libpurple with a crazy bunch of #define&#8217;s in order not to not need to rewrite it to use libpurple functions instead of bitlbee functions, but that didn&#8217;t really work out. I did experiment with making a plugin loader for libpurple that would let it load in bitlbee plugins, but after copying over most of bitlbee&#8217;s code to be able to achieve this, it seemed like a maintenance nightmare and was quickly abandoned too \ud83d\ude42 Instead, I started a new plugin based on the Rocket.Chat plugin (which was in-turn based on the FunYahoo++ plugin *puke*).<\/p>\n<p>The quirk in this protocol is the ability to connect to multiple Servers (aka Guilds) from one account. While Slack or Rocket.Chat let you do something similar, you need to set up separate accounts with each server to be able to do so; not an all-in-one-family-feedbag like Discord does. So there&#8217;s a bit of extra code needed to be able to translate a room onto a server and vice versa.<\/p>\n<p>This is still a work-in-progress (I only started work on it a couple of weeks ago), but already it&#8217;s got pretty solid group chat, buddy list, and direct message integration. This one might even be the first prpl from me that gets WebRTC-based audio integration into libpurple (after a failed attempt in the Hangouts plugin). We shall see!<\/p>\n<h2>Mattermost<\/h2>\n<p>The latest plugin I&#8217;ve been writing is one for <a href=\"https:\/\/about.mattermost.com\/\" target=\"_blank\" rel=\"noopener noreferrer\">Mattermost<\/a>, an open-source Slack alternative (similar to Rocket.Chat). The protocol is primarily <a href=\"https:\/\/api.mattermost.com\/\" target=\"_blank\" rel=\"noopener noreferrer\">REST-based<\/a> with a <a href=\"https:\/\/api.mattermost.com\/#tag\/WebSocket\" target=\"_blank\" rel=\"noopener noreferrer\">Websocket<\/a> used for live events such as messages or presence info.<\/p>\n<p>Mattermost is similar to Discord in that one account can connect to multiple Teams, which can be on one server &#8211; so we&#8217;re using a similar lookup table for mapping group chat &#8220;channels&#8221; to the corresponding team. It&#8217;s also similar to Rocket.chat in that it uses Markdown in its protocol for rich-text.<\/p>\n<p>What&#8217;s really great about working with Mattermost is that the API is consistent, with <a href=\"https:\/\/docs.mattermost.com\/administration\/changelog.html\" target=\"_blank\" rel=\"noopener noreferrer\">sensible deprecation policies<\/a> (contrast with Rocket.Chat&#8217;s &#8220;fast and loose&#8221; strategy when it comes to changing API parameters). What&#8217;s a little scary is that the API major version seems to get a bump every year, and there might need to be frequent changes in the plugin to adapt with the newer server API versions &#8211; but it might also be nothing to worry about \ud83d\ude42<\/p>\n<p>This is another work-in-progress plugin that I only started on a few days ago, and I&#8217;ve been working with the Mattermost developers to come up with a great plugin. They&#8217;ve also been really helpful in building <a href=\"https:\/\/github.com\/EionRobb\/purple-mattermost#readme\" target=\"_blank\" rel=\"noopener noreferrer\">documentation<\/a> for installing and using the plugin.<\/p>\n<h2>Go get &#8217;em!<\/h2>\n<p>The easiest way to find the new plugins is via the <a href=\"https:\/\/developer.pidgin.im\/wiki\/ThirdPartyPlugins\" target=\"_blank\" rel=\"noopener noreferrer\">Pidgin ThirdPartyPlugins wiki page<\/a> which will also give you links to lots of other tasty libpurple and Pidgin plugins \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It suddenly occurred to me that I never posted about the new prpls that I&#8217;ve written since the Hangouts prpl. Today we shall fix that.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true},"categories":[7],"tags":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p3CEsE-59","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/eion.robbmob.com\/blog\/wp-json\/wp\/v2\/posts\/319"}],"collection":[{"href":"https:\/\/eion.robbmob.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/eion.robbmob.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/eion.robbmob.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/eion.robbmob.com\/blog\/wp-json\/wp\/v2\/comments?post=319"}],"version-history":[{"count":1,"href":"https:\/\/eion.robbmob.com\/blog\/wp-json\/wp\/v2\/posts\/319\/revisions"}],"predecessor-version":[{"id":320,"href":"https:\/\/eion.robbmob.com\/blog\/wp-json\/wp\/v2\/posts\/319\/revisions\/320"}],"wp:attachment":[{"href":"https:\/\/eion.robbmob.com\/blog\/wp-json\/wp\/v2\/media?parent=319"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/eion.robbmob.com\/blog\/wp-json\/wp\/v2\/categories?post=319"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/eion.robbmob.com\/blog\/wp-json\/wp\/v2\/tags?post=319"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}