<p>When thinking about web automation we need to go beyond simple integrations and think of it as a class of programming that makes use of various distributed API's to be put to work backing parts of applications, or replacing them entirely. Where once all software was built and run on a single machine with localised libraries and runtimes, we now have the world's API's <a href="http://en.wikipedia.org/wiki/Unix_philosophy#Do_One_Thing_and_Do_It_Well">doing their one thing well</a>, at scale, right at our fingertips.</p>
<p>That's pretty neat! It's an exciting future.</p>
<p>bip.io is purpose built to this end, and although it's a web automation framework, it's also a visual programming tool for building and easily maintaining discrete endpoints which can augment your own applications, using external and native API's.</p>
<p>I had the chance to build a new 'randomised integer' flow control recently and took it as an opportunity to not only build some useful Bips (essentially, distributed graphs), but also take advantage the 'app-like' characteristics of Bips by replacing the loading message on the bip.io dashboard. Anyone else on the team could now update the configuration as they like, no programming required. No sprint planning, no builds, no deployment plan. It was fun, quick to do and pretty useful, so here it goes!</p>
<h6 id="inanutshell">In A Nutshell</h6>
<p>We're going to generate the message in the dashboard loading screen</p>
<p><img src="http://idfiles.leveelabs.com/55bd0288af0b0930ba599bd0c4b7ca38/resources/img_new/blog_bip_io/Screen-Shot-2015-04-01-at-2-01-52-PM-2.png" alt="" /></p>
<p>From a public Web Hook Bip that looks like this</p>
<p><img src="http://idfiles.leveelabs.com/55bd0288af0b0930ba599bd0c4b7ca38/resources/img_new/blog_bip_io/Screen-Shot-2015-04-01-at-2-26-13-PM.png" alt="" /></p>
<h6 id="problemspace">Problem Space</h6>
<p>So this is the most important part - Planning. The loading messages are generated randomly for each hit on the dashboard from a list of possibilities. When we look at a piece of existing code like :</p>
<pre>$motds = Array(
"message 1",
"message 2",
"etc..."
);
define('MOTD', $motds[ array_rand($motds) ]);
</pre>
<p>... it can be distilled down to being just a 'list of strings'. One of those strings needs to be extracted randomly, stored and displayed somehow. And that's what this Bip should do.</p>
<p>I know we have a text templater that can contain a list, and ways to split lists of strings using flow controls. The randomisation part means there's some math involved, so the math pod is needed too. That bit should take care of the extraction requirements.</p>
<p>The logical steps of extracting a random string from a list will be (annotated with bipio actions) :</p>
<ul>
<li>get the number of lines (<code>templater.text_template</code>)</li>
<li>generate a random number between 0 and the number of lines (<code>math.random_int</code>)</li>
<li>get every line number (<code>flow.lsplit</code>)</li>
<li>test that the line number matches the random number (<code>math.eval</code>)</li>
<li>if the line number matches the random number, then that's a random line (<code>flow.truthy</code>)</li>
</ul>
<p>However, because Bips are asynchronous, distributed pipelines, there's no way to loop back all the possible outputs from that computation, I'll need somewhere to store the result for retrieval later. For that, I'll use a Syndication container, which can store line items (<code>syndication.list</code>).</p>
<h6 id="selectawebhooktrigger">Select A Web Hook Trigger</h6>
<p><a href="http://en.wikipedia.org/wiki/Webhook">Web Hooks</a> are a certain flavor of Bip which sits passively in the system and waits for messages to arrive before performing it's work. They're kind of like personal API's that can be called on demand with any ad-hoc data structure.</p>
<p>Find them by just going to <strong>Create A Bip > Create New Event</strong> and select <strong>Incoming Web Hook</strong></p>
<p><img src="http://idfiles.leveelabs.com/55bd0288af0b0930ba599bd0c4b7ca38/resources/img_new/blog_bip_io/Screen-Shot-2015-04-01-at-2-46-51-PM.png" alt="" /></p>
<p>Now I'm ready. While it's not completely necessary, it's useful to give web hooks a name. The name will become part of the URL. For this I called it <code>random_motd</code> - Random Message Of The Day, because it will behave similarly to <a href="http://en.wikipedia.org/wiki/Motd_%28Unix%29">unix motd's</a></p>
<p><img src="http://idfiles.leveelabs.com/55bd0288af0b0930ba599bd0c4b7ca38/resources/img_new/blog_bip_io/Screen-Shot-2015-04-01-at-2-49-02-PM.png" alt="" /></p>
<h6 id="createcontainers">Create Containers</h6>
<p>Here's a little cheat if you're following along. Go ahead and plug this filter into the action search area <code>message template,math,by line,truthy,store</code>.</p>
<p>It should give you a list that matches pretty closely to the actions mentioned earlier, and look similar to</p>
<p><img src="http://idfiles.leveelabs.com/55bd0288af0b0930ba599bd0c4b7ca38/resources/img_new/blog_bip_io/Screen-Shot-2015-04-01-at-2-39-23-PM.png" alt="" /></p>
<p>Add them all into the graph. When it comes to creating the syndication container, make sure to set replace mode, rather than append mode. This will make sure that new motd's aren't appended to the container, and that it's contents are replaced instead.</p>
<p><img src="http://idfiles.leveelabs.com/55bd0288af0b0930ba599bd0c4b7ca38/resources/img_new/blog_bip_io/Screen-Shot-2015-04-01-at-3-12-33-PM.png" alt="" /></p>
<p><strong>^^ This is really important and ties everything together in the end</strong></p>
<h6 id="connectthedotsandpersonalize">Connect The Dots And Personalize</h6>
<p>Whichever the preferred method is, by either connecting these in advance or step by step, eventually we'll need a graph that looks like this :</p>
<p><img src="http://idfiles.leveelabs.com/55bd0288af0b0930ba599bd0c4b7ca38/resources/img_new/blog_bip_io/Screen-Shot-2015-04-01-at-2-26-13-PM-1.png" alt="" /></p>
<p>I usually connect them all up first and let bip.io try to figure out how data should be transformed, but it's personal preference. I start by dragging from the Web Hook icon to templater and so on, until the syndication container is the last node in the pipeline.</p>
<p><img src="http://idfiles.leveelabs.com/55bd0288af0b0930ba599bd0c4b7ca38/resources/img_new/blog_bip_io/drag-1.gif" alt="" /></p>
<p>For each of the nodes, double click and set up these transformations</p>
<p><img src="http://idfiles.leveelabs.com/55bd0288af0b0930ba599bd0c4b7ca38/resources/img_new/blog_bip_io/doubleclick.gif" alt="" /></p>
<p><strong>Templater</strong> - Set the template</p>
<h2 id="imgsrccontentimages201504screenshot20150401at21324pmpngalt"><img src="http://idfiles.leveelabs.com/55bd0288af0b0930ba599bd0c4b7ca38/resources/img_new/blog_bip_io/Screen-Shot-2015-04-01-at-2-13-24-PM.png" alt="" /></h2>
<p><strong>Math</strong> - Generate random value</p>
<h2 id="imgsrccontentimages201504screenshot20150401at21334pmpngalt"><img src="http://idfiles.leveelabs.com/55bd0288af0b0930ba599bd0c4b7ca38/resources/img_new/blog_bip_io/Screen-Shot-2015-04-01-at-2-13-34-PM.png" alt="" /></h2>
<p><strong>Flow Control</strong> - Split lines</p>
<h2 id="imgsrccontentimages201504screenshot20150401at21344pmpngalt"><img src="http://idfiles.leveelabs.com/55bd0288af0b0930ba599bd0c4b7ca38/resources/img_new/blog_bip_io/Screen-Shot-2015-04-01-at-2-13-44-PM.png" alt="" /></h2>
<p><strong>Math</strong> - Select Random Line</p>
<h2 id="imgsrccontentimages201504screenshot20150401at21355pmpngalt"><img src="http://idfiles.leveelabs.com/55bd0288af0b0930ba599bd0c4b7ca38/resources/img_new/blog_bip_io/Screen-Shot-2015-04-01-at-2-13-55-PM.png" alt="" /></h2>
<p><strong>Flow Control</strong> - Test Current Line Equals The Random Line</p>
<h2 id="imgsrccontentimages201504screenshot20150401at21405pmpngalt"><img src="http://idfiles.leveelabs.com/55bd0288af0b0930ba599bd0c4b7ca38/resources/img_new/blog_bip_io/Screen-Shot-2015-04-01-at-2-14-05-PM.png" alt="" /></h2>
<p><strong>Syndication</strong> - Replace Into Container <img src="http://idfiles.leveelabs.com/55bd0288af0b0930ba599bd0c4b7ca38/resources/img_new/blog_bip_io/Screen-Shot-2015-04-01-at-2-14-15-PM.png" alt="" /></p>
<h6 id="selectarenderer">Select A Renderer</h6>
<p>Almost there, we have the pipeline defined but how is calling this endpoint going to return a random message? That's where <strong>Renderers</strong> come in. Renderers let a Web Hook Bip respond in custom ways beyond a simple <code>200 OK</code> message by making use of <a href="http://en.wikipedia.org/wiki/Remote_procedure_call">RPC's</a> provided by Actions themselves, but usually hidden.</p>
<p>What we want to do in this case, is serve the random line that has been stored in the syndication list container, back to the connecting client. Luckily <code>syndication.list</code> has a renderer to do just this, so I enable it by going to the Renderer tab and hitting 'Enable' for the 'Returns List Content' renderer under 'Syndication : current motd'</p>
<p><img src="http://idfiles.leveelabs.com/55bd0288af0b0930ba599bd0c4b7ca38/resources/img_new/blog_bip_io/Screen-Shot-2015-04-01-at-5-14-14-PM.png" alt="" /></p>
<p>Makes Sense?</p>
<h6 id="readytosave">Ready To Save</h6>
<p>Because it's a web hook, you'll generally need your username and API token to call it, but I don't care about authentication for this demo, so under the Auth tab, Authentiction should be set to 'none'. None auth means its available to anyone with the link.</p>
<p><a href="https://team.bip.io/bip/http/random_motd">try it</a></p>
<p>Or install it yourself</p>
<p><iframe src="https://bip.io/widget/eyJpZCI6IjRlNjMxMjRhLTIxZDktNDQyZi1hNmYwLWI3YTRkYmZkYTZjNSIsImJpcF9pZCI6IjUxNjk4NjBjLTQxZTYtNDM0OS05NWJhLTExYTAxZWJmODhmNyIsInR5cGUiOiJodHRwIiwibmFtZSI6InJhbmRvbV9tb3RkIiwibm90ZSI6IlRoaXMgV2ViIEhvb2sgcmVzcG9uZHMgd2l0aCBhIHJhbmRvbSBtZXNzYWdlIG9mIHRoZSBkYXkgdG8gYW55IGNvbm5lY3RpbmcgY2xpZW50LiAgVG8gbW9kaWZ5IHRoZSBsaXN0IG9mIGF2YWlsYWJsZSBtZXNzYWdlcywganVzdCBlZGl0IHRoZSB0ZW1wbGF0ZXIgYWN0aW9uIiwiaWNvbiI6IiIsImNvbmZpZyI6eyJhdXRoIjoidG9rZW4iLCJyZW5kZXJlciI6eyJyZW5kZXJlciI6ImdldCIsImNoYW5uZWxfaWQiOiJzeW5kaWNhdGlvbi5saXN0In19LCJvd25lcl9pZCI6IjZhNGU1Mzc2LTg5ZDctMGY4OS1jM2RkLTAwMDAzNjM2ZTk2YyIsIm93bmVyX25hbWUiOiJCaXBJTyBUZWFtIiwibWFuaWZlc3RfaGFzaCI6ImVhM2EwMzZhZTQ0OGYxNDg2ZDkzYzc4Y2Q0YmIwM2MxIiwiaHViIjp7InNvdXJjZSI6eyJlZGdlcyI6WyJ0ZW1wbGF0ZXIudGV4dF90ZW1wbGF0ZSJdLCJ0cmFuc2Zvcm1zIjp7InRlbXBsYXRlci10ZXh0X3RlbXBsYXRlIjp7Im1lc3NhZ2UiOiJXaG9hIE5vdyHCoFxuVGhlIEFuc3dlciBJcyA0MsKgXG5Sb2Fkcz8gV2hlcmUgV2UncmUgR29pbmcsIFdlIERvbid0IE5lZWQgUm9hZHPCoFxuQmlwSU8gU2VydmVyIGlzIE9wZW4gU291cmNlIVxuwqBBbHdheXMgTG9vayBPbiBUaGUgQnJpZ2h0IFNpZGUgT2YgTGlmZcKgXG5HcmFwaGluZyBBbGwgVGhlIFRoaW5ncy4uLsKgXG5SZWFjaGluZyBUaGUgTW90aGVyc2hpcC4uLsKgXG5UaGVzZSBBUkUgVGhlIERyb2lkcyBZb3UncmUgTG9va2luZyBGb3IhwqBcbkNvbnN0cnVjdGluZyBBZGRpdGlvbmFsIFB5bG9uc8KgXG5IZXkgUHJlc3RvIcKgXG5UaW1lIG5vdCBpbXBvcnRhbnQuIE9ubHkgbGlmZSBpbXBvcnRhbnTCoFxuVGhhbmtzIEZvciBVc2luZyBCaXBJTyHCoFxuQXNzZW1ibGluZyBUaGUgSW50ZXJuZXTCoFxuV2UncmUgSW4gVGhlIFBpcGUgRml2ZSBCeSBGaXZlwqBcbkRvIE9yIERvIE5vdCwgVGhlcmUgSXMgTm8gVHJ5wqBcblJldGljdWxhdGluZyBTcGxpbmVzwqBcbldhcmV3b2x2ZXMgTm90IFN3ZWFyd29sdmVzIcKgXG5UaGlua2luZy4uLsKgXG5XaGVuIHlvdSdyZSBmZWVsaW5nIHVuZGVyIHByZXNzdXJlLCBkbyBzb21ldGhpbmcgZGlmZmVyZW50LiBSb2xsIHVwIHlvdXIgc2xlZXZlcywgb3IgZWF0IGFuIG9yYW5nZSJ9fX0sInRlbXBsYXRlci10ZXh0X3RlbXBsYXRlIjp7ImVkZ2VzIjpbIm1hdGgucmFuZG9tX2ludCJdLCJ0cmFuc2Zvcm1zIjp7Im1hdGgtcmFuZG9tX2ludCI6eyJtYXgiOiJbJXRlbXBsYXRlci50ZXh0X3RlbXBsYXRlI2xpbmVfY291bnQlXSIsIm1pbiI6IjAifX19LCJtYXRoLXJhbmRvbV9pbnQiOnsiZWRnZXMiOlsiZmxvdy5sc3BsaXQiXSwidHJhbnNmb3JtcyI6eyJmbG93LWxzcGxpdCI6eyJib2R5IjoiWyV0ZW1wbGF0ZXIudGV4dF90ZW1wbGF0ZSNtZXNzYWdlJV0ifX19LCJmbG93LWxzcGxpdCI6eyJlZGdlcyI6WyJtYXRoLmV2YWwiXSwidHJhbnNmb3JtcyI6eyJtYXRoLWV2YWwiOnsiZXhwcmVzc2lvbiI6IlslZmxvdy5sc3BsaXQjaW5kZXglXcKgPT0gWyVtYXRoLnJhbmRvbV9pbnQjcmFuZG9tX2ludCVdIn19fSwibWF0aC1ldmFsIjp7ImVkZ2VzIjpbImZsb3cudHJ1dGh5Il0sInRyYW5zZm9ybXMiOnsiZmxvdy10cnV0aHkiOnsidmFsdWUiOiJbJW1hdGguZXZhbCNyZXN1bHQlXSJ9fX0sImZsb3ctdHJ1dGh5Ijp7ImVkZ2VzIjpbInN5bmRpY2F0aW9uLmxpc3QiXSwidHJhbnNmb3JtcyI6eyJzeW5kaWNhdGlvbi1saXN0Ijp7ImV4cG9ydF9maWxlX25hbWUiOiIiLCJsaW5lX2l0ZW0iOiJbJWZsb3cubHNwbGl0I3ZhbHVlJV0ifX19fSwic2VhcmNoIjoiXCJUaGlzIFdlYiBIb29rIHJlc3BvbmRzIHdpdGggYSByYW5kb20gbWVzc2FnZSBvZiB0aGUgZGF5IHRvIGFueSBjb25uZWN0aW5nIGNsaWVudC4gIFRvIG1vZGlmeSB0aGUgbGlzdCBvZiBhdmFpbGFibGUgbWVzc2FnZXMsIGp1c3QgZWRpdCB0aGUgdGVtcGxhdGVyIGFjdGlvblwiXCJyYW5kb21fbW90ZFwiIFwidGVtcGxhdGVyLnRleHRfdGVtcGxhdGVcIiBcIm1hdGgucmFuZG9tX2ludFwiIFwiZmxvdy5sc3BsaXRcIiBcIm1hdGguZXZhbFwiIFwiZmxvdy50cnV0aHlcIiBcInN5bmRpY2F0aW9uLmxpc3RcIiBcIk1lc3NhZ2UgVGVtcGxhdGVcIiBcIlJhbmRvbSBJbnRlZ2VyXCIgXCJTcGxpdCBUZXh0IGJ5IExpbmVcIiBcIkV2YWxcIiBcIklucHV0IGlzIFRydXRoeVwiIFwiU3RvcmUgYSBsaXN0IG9mIGl0ZW1zXCIiLCJjcmVhdGVkIjoxNDI4MDAzOTAzNjQ3LCJfaWQiOiI1NTFkNjNjN2RiNDM1OGI0NDc3ZWQzNDEiLCJfX3YiOjAsInZvdGVzIjowLCJtYW5pZmVzdCI6WyJ0ZW1wbGF0ZXIudGV4dF90ZW1wbGF0ZSIsIm1hdGgucmFuZG9tX2ludCIsImZsb3cubHNwbGl0IiwibWF0aC5ldmFsIiwiZmxvdy50cnV0aHkiLCJzeW5kaWNhdGlvbi5saXN0Il19" width="100%" height="94"></iframe></p>
<p>A couple of notes if you're building this yourself...</p>
<p>After the Bip has been saved it will appear in your list under My Bips, and callable as <code>https://{your username}.bip.io/bip/http/random_motd</code></p>
<p>You'll need to prime the endpoint by calling it once, which will set the container content and give it something to respond with. After that, you're all set.</p>
<p>Video here</p>
<p><iframe src="https://player.vimeo.com/video/124550797" frameborder="0" width="500" height="382" allowfullscreen="allowfullscreen" webkitallowfullscreen="webkitallowfullscreen" mozallowfullscreen="mozallowfullscreen"></iframe></p>
<p>Happy Bipping!</p>