Pages

Saturday, May 21, 2016

Typescript, React and Sass - All in one - Skeleton Project built with Webpack

Just recently I had the need to set up a project that included 
Typescript, React, Sass and building it with Webpack, and couldn't find any good up-to-date source on the web for a 
skeleton project to base it on.

So I decided to create my own.

You can check it out (free of course) on my GitHub account:





Monday, May 9, 2016

Hubot Script for Image Search on Bing

How to write a Hubot script that integrates with Bing in Javascript

In case you haven't heard of Slack, I recommend you check it out.
Slack is a Messaging App with an extremely cool edge of customization abilities.

One of those abilities allows you to install an App that plugs-in to Slack, called Hubot.
A Hubot is a Bot app, that can listen to your commands on Slack, and perform a task.

After installing your Hubot on your machine, you will notice it has a "scripts" directory.
You can use this directory to write your own custom scripts which the Hubot will execute!
Very cool!

The scripts can be written in CoffeeScript and in Javascript.
You can simply copy-paste the code below, but notice that it will not work, unless you get your own Bing API key.
You can easily get it for free here.
This is how the screen looks like at Bing after you will (create an account as needed and) login.

Be sure to copy the API Key that (highlighted in red) shows in the box, 




and replace it with the 'key', 
which equals to 'XXXX-....-XXXX' in the code below.









The expected result





Enjoy hacking & slacking!
Nir


The code

// bing.js


'use strict'

var querystring = require('querystring');
var http = require('https');

// replace the 'XXXXX...' string here with your own Bing API KEY
var key = 'XXXXX-XXXXX-XXXXX-XXXXX'; 
var HOST_NAME = 'bingapis.azure-api.net';
var DEFAULT_NUMBER_OF_IMGS = 20;
var SAFE = {
  low: 'Off',
  medium: 'Moderate',
  high: 'Strict'
};

var HTTP_REQUEST_HEADERS = {
  "Accept": "*/*",
  "Content-Type": "application/json",
  "Ocp-Apim-Subscription-Key": key
};

function getParams(query, count, offset, safe) {
  count = count || DEFAULT_NUMBER_OF_IMGS;
  count = Math.max(5, Math.min(50, count));
  offset = offset || Math.floor(Math.random() * 4);
  return {
    'hostname': HOST_NAME,
    'method': 'GET',
    'path': buildQueryParameters(query, count, offset, safe || SAFE.medium),
    'headers': HTTP_REQUEST_HEADERS
  };
}

function buildQueryParameters(query, count, offset, safey) {
  return '/api/v5/images/search?q=' + query + 
'&count=' + count + '&offset=' + offset + 
'&mkt=en-us&safeSearch=' + safey;
}

function getImagesFromBing(query, hubotCallback) {
  var body = [];
  var params = getParams(query);
  var req = http.request(params, function(res) {
    res.setEncoding('utf8');
    res.on('data', function (chunk) {
      body.push(chunk);
    });
    res.on('end', function () {
       var data = body.join('');
       var dataAsJson = JSON.parse(data);
       var values = dataAsJson.value;
       var imgs = values.map(function(val) {
         return val.contentUrl;
       });
       hubotCallback(imgs);
    });
  });
  req.end();
}

module.exports = function(robot) {
    robot.hear(/bingme (.*)/i, function(res) {
        var photoname = res.match[1];
        res.reply("Looking for a photo of \"" + photoname + "\" on Bing!");

        var escapedQuery = querystring.escape(photoname);
        getImagesFromBing(escapedQuery, function(imgs) {
          var randomPhotoIndex = Math.floor(Math.random() * imgs.length);
          res.send(imgs[randomPhotoIndex]);
        });
    });
}