Friday, June 10, 2016

Python and the MySQL driver hole I found myself

So I'm a Python developer now and Django to boot. To those who read this blog would have noticed that I primary do Java and AngularJS but I've used Python sparingly so this change ain't so bad.

But first off, this Python 2 and 3 is freakin' annoying but it still works out nicely with virtual environments. Then I walked into Python's mess of MySQL drivers. Working with Django with a MySQL backend, there's little or no mention of needing a MySQL driver, if a newbie walked into this error it take them a chuck of time to figure it out. And if they figure it out, will then stumble into the myriad of options (mysql-connector-python, PyMySQL, etc.) which lead me to the hole I mention on the title.

The whole start was just because I picked PyMySQL as my driver which a pure Python implementation of a MySQL connector. My Python script kept failing on me until I found that I need to install the damn thing:

try:
    import pymysql

    pymysql.install_as_MySQLdb()
except ImportError:
    pass

Before I run my __main__ function.

Phew.

Well, I can't back out now. I'm a Python dev now anyway.

Wednesday, May 11, 2016

Being stupid while calling Twitter's Search API

A few days ago, I just figured out how to authenticate my Ionic app using Twitter's application-only Oauth. Application only authentication allows you call Twitter APIs without that Twitter login screen.

The being stupid part started when I tried using the Search API.

    var twitterStreamURL = "https://api.twitter.com/1.1/search/tweets.json?q="; 
    var qValue = "queryString";
    var numberOfTweets = "&count=10";

It should be easy to see that to call the Search API you'll concatinate the qValue (or query string) and the numberOfTweets (number of tweets to get) to the twitterStreamURL. You'd do then a ajax call then get the resulting JSON.
    
    var cURL = "https://api.twitter.com/1.1/search/tweets.json?q=" + qvalue + numberOfTweets; 

These would be no problem with the query string had only one value or no special characters. This stumped me a bit because I used escape() function at first which I knew about. It still works but the escape() function is deprecated. Which lead me to encodeURI(). It worked until it was asked to search for strings with hash tags. I didn't read the fine print for encodeURI which said it doesn't encode certain special characters. This finally lead me to the encodeURIComponent() function.
    
    var cURL = "https://api.twitter.com/1.1/search/tweets.json?q=" + encodeURIComponent(qvalue) + numberOfTweets; 

The moral of this story is I need read the fine print.

Friday, April 8, 2016

Ionic, Satellizer, Facebook and that "Given URL is not allowed" error

You can have your Ionic mobile application use Facebook authentication. You can do it the hard way - i.e. do it yourself via $http calls - or go the easy route via Satellizer. Being the lazy bastard that I am, I'll be using Satellizer.

Satellizer can be setup quickly, do bower install, add the needed JavaScript bits to your index.html and reference it in you Ionic app.

angular.module('meAwesomeIonicApp', ['ionic', 'ngCordova', 'satellizer', 'ngAnimate']).config(...)

From here you'll need to go to Facebook Developer and register your app. You'll then add the FB application appId to your satellizer settings. It should look something like:

    var commonConfig = {
        popupOptions: {
            location: 'no',
            toolbar: 'yes',
            width: window.screen.width,
            height: window.screen.height
        }
    };

    if (ionic.Platform.isIOS() || ionic.Platform.isAndroid()) {
        commonConfig.redirectUri = 'http://localhost/';
        $authProvider.platform = 'mobile'
    }

    $authProvider.facebook(angular.extend({}, commonConfig, {
        clientId: 'YOUR FB APP ID HERE',
        url: 'http://localhost:3000/auth/facebook',
        responseType: 'token'
    }));

This moves us to the controllers. In the controllers we have access to a $auth service which is provided by Satellizer. The $auth service then provides a authenticate(string) function. So we have:
 
$auth.authenticate(provider)
        .then(function() {n
             // Success login
        })
        .catch(function(response) {
             // Error in login
        });
};

You can easily add this to a ng-click handler. And this is where we encounter the "Given URL is not allowed" error. What's happening is that when we call $auth.authenticate(), it will try to open a FB login page based on the url value we configured in the $authProvider.facebook() call instead we get the error page instead of the login form.

Fortunately, for me the fix was easy. I just didn't configure the settings in the FB developer app page correctly. It isn't enough to just configure the Basic Section in the Settings page. You need to open the Advance Section and also configure the Valid OAuth redirect URIs values also. So if you add the http://localhost value in the textfield, it should fix the "Given URL is not allowed" error.