Nikola Brežnjak blog - Tackling software development with a dose of humor
  • Home
  • Daily Thoughts
  • Ionic
  • Stack Overflow
  • Books
  • About me
Home
Daily Thoughts
Ionic
Stack Overflow
Books
About me
  • Home
  • Daily Thoughts
  • Ionic
  • Stack Overflow
  • Books
  • About me
Nikola Brežnjak blog - Tackling software development with a dose of humor
CodeProject, NodeJS

Using CasperJS on Webfaction to automatically send emails with attached images via Gmail

Why?

Recently I had to make a script which runs once per week and gathers images of an admin interface (login required) and sends it to its manager by email for quick overview. This is great because it saves the manager’s time as he doesn’t have to login to the website and click through all of the graphs and wait for them to load, instead he gets a weekly (YMMV) summary. The site was hosted on Webfaction, which, as it turns out, is a cool web host (haven’t come across it before) because it allows you to compile source code and run custom binaries.

How?

The task of automatically logging in the admin dashboard and taking screenshots  proved to be an excellent job for CasperJS, an open source navigation scripting & testing utility written in Javascript for the PhantomJS WebKit headless browser.

Installation

In order to run CasperJS scripts, you need to have NodeJS installed. Installing NodeJS on Webfaction is as straightforward as it can get, as it’s done via their control panel in the Applications tab, as shown on the illustration below:
webfactionNodeInstall

It’s useful to put NodeJS executable in your path because then you can run node from any folder. You can do this by going to your NodeJS application’s bin directory and execute the following command:

export PATH=$PATH:$PWD/bin/

Installing CasperJS is easy via npm (Node package manager):

npm install -g casperjs

However,  in order for CasperJS to work, you need to install PhantomJS and you can do it by cloning it from its GitHub repository and running the build.sh script:

mkdir -p $HOME/src

cd $HOME/src

git clone git://github.com/ariya/phantomjs.git && cd phantomjs

git checkout 1.5

./build.sh

cp $HOME/src/phantomjs/bin/phantomjs $HOME/bin

To test if PhantomJS has been successfully installed you can run:

phantomjs --version

To have the binaries in my path every time I log in I added this alias to my .bashrc:

alias nodeset="export PATH=$PATH:/home/webapp/node/bin:/home/webapp/bin"

and my .bash_profile looks like this:

# User specific environment and startup programs
PATH=$PATH:$HOME/bin
export PATH
nodeset

CasperJS script for automatically saving images

var casper = require("casper").create({
	verbose: false,
	logLevel: 'debug'
});

var url = "http://your-app.com/", 
	saveDir = "/home/app/savedImages";

casper.start(url, function() {
	this.fill('form#fm_login', {
        'username':    'username',
        'password':    'password',
    });

    this.echo("I filled the form");
});

casper.then(function(){
	this.click('#btn_login');
	this.echo("I'm, logging in");
});

//first graph fetch
casper.thenOpen("http://your-app.com/graph_1", function(){
    this.wait(3000, function() {
        this.echo("I've waited for 3 seconds for the graphs to load.");

        casper.then(function(){
            var fileName = saveDir + '/graph_1.png';
            this.viewport(1920, 1080);
            this.captureSelector(fileName, '#page_content');
            this.echo('first snapshot taken');
        });
    }); 
});

casper.run(function() {
    this.echo('done').exit();
});

First I initialize casper and set few variables (url, saveDir – note that it has to be full path). Then I start casper by visiting the passed in url and fill the login form by using caspers fill() function. After that I click on the login button and woila – I’m logged in. After that I open up the link with the graph and wait 3 seconds for the graph to load, and then I save the selected area by using the captureSelector() function and a CSS selector of the area I want to save.

NodeJS script for automatically sending email with attachment via Gmail SMTP

This node script uses nodemailer which can be installed using npm:

node install -g nodemailer

This script uses Gmail SMTP (if you want to test it make sure to enter correct Gmail account credentials), but nodemailer offers many more options for sending the email. The simple email sending script is here:

var nodemailer = require("nodemailer");
var rootFolder = "/home/app/savedImages/";
// create reusable transport method (opens pool of SMTP connections)
var smtpTransport = nodemailer.createTransport("SMTP",{
    service: "Gmail",
    auth: {
        user: "[email protected]",
        pass: "your.gmail.pass"
    }
});

// setup e-mail data with unicode symbols
var mailOptions = {
    from: "Automatic Graph Sender <[email protected]>", // sender address
    to: "[email protected]", // list of receivers
    subject: "Automatic Graph Sender", // Subject line
    text: "Hello, I'm Roboty, an automatic report sending robot. You will find your files in attachment. I wish you a great day! Bye, Roboty", // plaintext body
    html: "Hello,<br/><br/>I'm Roboty, an automatic report sending robot. You will find your files in attachment.<br/><br/>I wish you a great day!<br/><br/>Bye,<br/>Roboty",
    attachments: [
        { filePath: rootFolder + "graph_1.png"},
        { filePath: rootFolder + "graph_2.png"},
        //add as many as you wish
    ]
}

// send mail with defined transport object
smtpTransport.sendMail(mailOptions, function(error, response){
    if(error){
        console.log(error);
    }else{
        console.log("Message sent: " + response.message);
    }

    // if you don't want to use this transport object anymore, uncomment following line
    smtpTransport.close(); // shut down the connection pool, no more messages
});

 

Cron jobs

The following script will run every day at exactly 19:50h. I added the PHANTOMJS_EXECUTABLE needed by CasperJS executable, then I wrote the path to CasperJS and the script that we want to execute and finally I redirected all the output to the temporary file for later inspection if needed.

50 19 * * * PHANTOMJS_EXECUTABLE=/home/app/bin/phantomjs /home/app/node/bin/casperjs /home/app/casper/saveImages.js > /tmp/outputCheck.txt

Mailing script runs 5 minutes after the image gathering script and also outputs everything to the temporary file used in some other success status checking script.

55 19 * * * /home/emtool/webapps/node/bin/node /home/emtool/my_folder/casper/mail.node.js > /tmp/emailOut.txt

Hope this proved useful to someone, and hit me with comments or questions you may have.

CodeProject

CodeProject, PHP

Simple caching with Cache_Lite without having to install it through PEAR

Sooner or later everyone has to make use of some kind of caching of their content. Below is the simplest possible code demonstration on how to implement caching with Cache_Lite (download Cache_Lite standalone PHP class file which you can just include to your project without having to install it through PEAR):

require_once('Cache_Lite.php');
$cache = new Cache_Lite(	
  array(
    'cacheDir' => "cache/",
    'lifeTime' => 20 //seconds
  )
);

$req = "file.txt";
if($data = $cache->get($req)) {
  echo "Result from cache: " . $data;
}
else {
  $data = file_get_contents($req); // this is usually a DB call!
  $cache->save($data);
  echo "Result not from cache: " . $data;
}

So, first you require the class file, make a new instance by setting a caching directory and cache lifetime. For demonstration purposes I’m outputing the contents of file.txt but of course in a real use case scenario that would be some result of a database query or sth like that.

Simply, to get the data from cache (if it exists) you have to call the get() function on the Cache_Lite object, and to save it, well, use save() function and you’re all done.

CodeProject, PHP

Using prepared statements in PHP with MySqli

So, as most of you know PHP 5.5.x has deprecated the original MySQL extension, and instead we should be using  MySQLi or PDO_MySQL extensions. Here I will show you how to use MySQLi to query the database. I will cover the basic SELECT statement with and without prepared statements, and will show you the benefits of using mysqlnd driver.

For example purposes say we have a repository class where we keep our cars:

class CarRepository {
	private static $_host;
	private static $_database;
	private static $_user;
	private static $_password;
	private static $_mysqli;

	private static $_initialized = false;

    // this is a fix because static classes in php do not call contructor automatically
    //http://stackoverflow.com/questions/468642/is-it-possible-to-create-static-classes-in-php-like-in-c
    private static function initialize() {
        if (self::$_initialized)
            return;

        $credientials = CredentialsManager::GetCredentials();

        self::$_host = $credientials['host'];
        self::$_database = $credientials['database'];
        self::$_user = $credientials['user'];
        self::$_password = $credientials['pass'];        

        self::$_initialized = true;
    }

    private static function openConnection() {
        self::$_mysqli = new mysqli(self::$_host, self::$_user, self::$_password, self::$_database);
        if (self::$_mysqli->connect_errno) {
            echo "Failed to connect to MySQL: " . self::$_mysqli->connect_error;
            return false;
        }       

        return true;
    }

As you can see in the code the initialize() function is used because static classes in PHP don’t call contructor automatically. The CredentialsManager class may look like this:

class CredentialsManager {
    private static $_Host;
    private static $_Database;
    private static $_User;
    private static $_Pass;

    public static function GetCredentials() {
        CredentialsManager::GetLocalHostCredentials();

        return array(
            'host' => CredentialsManager::$_Host,
            'database' => CredentialsManager::$_Database,
            'user' => CredentialsManager::$_User,
            'pass' => CredentialsManager::$_Pass
        );    
    }

    private static function GetLocalHostCredentials() {
        CredentialsManager::$_Host = "localhost";
        CredentialsManager::$_Database = "database";
        CredentialsManager::$_User = "username";
        CredentialsManager::$_Pass = "password";
    }
}

The openConnection() function in the CarRepository class opens the connection to the database and stores it in the private $_mysqli variable. Note that this is the object oriented style of opening the connection, and that there is also a procedural style.

Finally, lets query the database for some data:

public static function GetCarOfTheDay() {
	self::initialize();

    if (self::openConnection()) {
    	$carObj = self::$_mysqli->query("SELECT * FROM cars WHERE car_of_the_day=true ORDER BY position LIMIT 1");

    	$car = self::makeObjects($carObj);

		return $car;
    }
    else
    	return false;
}

So, simply we just call the query method on the $_mysqli object with the SQL query and we get mysqli_result object:

object(mysqli_result)#3 (5) {
    ["current_field"]=> int(0) 
    ["field_count"]=> int(21) 
    ["lengths"]=> NULL 
    ["num_rows"]=> int(1) 
    ["type"]=> int(0)
}

I send this object into another function which then returns a Car object for me:

$car = self::makeObjects($carObj);

Lets keep it simple and say the makeObjects looks like this:

public static function makeObjects($carObj){
	require_once("Car.php");
	$cars = array();

	while ($row = $carObj->fetch_assoc()) {
		$car = new Car();

		$row = $carObj->fetch_assoc();

		$car->Id = $row["id"];
		$car->Make = $row["make"];
		$car->Year = $row["year"];

	}

 	if (count($cars) > 1)
 		return $cars;
 	else
 		return $cars[0];
}

Function returns only one Car object if there is only one or an array of Car objects if there are more results. Fetching more cars would look like this (basically the same call!):

public static function GetAllCars() {
	self::initialize();

    if (self::openConnection()) {
    	$carObjs = self::$_mysqli->query("SELECT * FROM cars");

    	$cars = self::makeObjects($carObjs);

		return $cars;
    }
    else
    	return false;
}

You can use queries like this when there are no parameters going into your SQL queries like the ones shown above, but what if you would like to query the database for a car by its id? Naturally, you would make a function like getCarById($id) with the $id as a parameter. Now, you may try to this along these lines:

public static function GetCarById($id) {
	self::initialize();

	if (self::openConnection()) {
		$carsObj = self::$_mysqli->query("SELECT * FROM cars WHERE id=" . $id);		
	}
	else 
		return false;
}

and though this would work, you would actually be exposing your self to a potential SQL injection attack. And sure, one could argue that you could escape the $id variable and whatnot, but that’s just not the way how it’s done these days. You can learn more about it on this post on StackOverflow, but basically what they say is that you should be using prepared statements.

The following code  shows how to query the database using prepared statements in mysqli (the function echoes the car’s make and year from the cars table):

public static function GetCarMakesById($id) {
	self::initialize();

	if (self::openConnection()) {
		$stmt = self::$_mysqli->prepare("SELECT make, year FROM cars WHERE id=?");

		$stmt->bind_param("i", $id);

		$stmt->execute();

		$stmt->bind_result($make, $year);

        $stmt->fetch();   

        printf("%s - %s\n", $make, $year);
	}
	else 
		return "oh noez";
}

So, here we put the query in the prepare() method of the mysqli object, and you may notice the ? instead of the actual parameter. That’s just the way how these prepared statements are written in mysqli. Then you tell it which parameter actually comes in place of ? and itself then makes sure it’s properly escaped, etc. The i in bind_param() method is for “integer”, s is for “string”, d is for “double”, b is for blob (read more about it here).

After that you have to call execute() and then bind_result() which binds/stores the result from the database query to variables set in it (in our case $make and $year) once you call the fetch() method.

Another example of fetching the data where we have more rows:

public static function GetCarMakesPerYear($year) {
	self::initialize();

	if (self::openConnection()) {
		$stmt = self::$_mysqli->prepare("SELECT make FROM cars WHERE year=?");

		$stmt->bind_param("i", $year);

		$stmt->execute();

		$stmt->bind_result($make);

        while ($stmt->fetch()) {
            printf("%s\n", $make);
        }
	}
	else 
		return false;
}

The code above would print out all the makes of a certain year. Now, up to this point all was great and I was pretty happy how things work, but then, I had to make a select like:

SELECT * FROM cars;

and now I was in trouble. After extensive googling I found out that I basically have two options:

  • use the get_result() function on the mysqli object or
  • list all the fields in the bind_result() and use fetch

At this point I immediately thought, now why would anyone not want to use get_result? [This would particularly help me because then I could just query the db with get_result() and just send that object to makeObjects() and thus using the same exact code – no duplication]

Right, so, the problem was that in order to use get_result() function on the mysqli object you would have to have mysqlnd driver installed (You can learn more on these few links). So, since I had PHP 5.3 and I tried updating with yum install php-mysqlnd I got into trouble. I even posted this question on StackOverflow. The solution I used in the end, as I outline it on SO, was to update PHP to 5.4 and force install php54-mysqlnd-5.4.17-1.ius.el6.x86_64 package.

In order to test if you have mysqlnd support you can run this code:

$mysqlnd = function_exists('mysqli_fetch_all');

if ($mysqlnd) {
    echo 'mysqlnd enabled!';
}
else {
	echo "nope";
}

Finally, with this all set I’m now able to use fetch_all() function like this:

public static function GetCarById($id){            
	self::initialize();

if (self::openConnection()) {
    $stmt = self::$_mysqli->prepare("SELECT * FROM car WHERE id=?");
    $stmt->bind_param("i", $id);

    $stmt->execute();

    $carObj = $stmt->get_result();

    $car = self::makeObjects($carObj);

    return $car;
}
else 
    return false;
}

To use the LIKE in prepared statements you have to “prepare” your variable before, like this:

$stmt = self::$_mysqli->prepare("SELECT * FROM car WHERE make LIKE ?");
$make .= '%';
$stmt->bind_param("s", $make);

Wohoo, happy coding!
Link to this article on CodeProject

CodeProject, PHP

Building a really simple PHP templating engine

Recently I had to make use of templates in PHP, and as a lot of people on StackOverflow ([1], [2]) suggested “you don’t need another templating engine like Smarty on top of PHP,  as PHP itself is a templating engine”.

So, I ended up making a simple function which looks like this:

function getTemplate($file, $variables = NULL){
    if (! is_null($variables))
    extract($variables);

    include(TEMPLATES_FOLDER . $file);	
}

TEMPLATES_FOLDER is a PHP constant which is defined in the config.php file like this:

if ( !defined('ABSPATH') )
	define('ABSPATH', dirname(__FILE__) . '/');

define("TEMPLATES_FOLDER", ABSPATH . "templates/");

So, for example a template may look like this:

<!-- Navigation START -->
<div class="navigation">
	<div class="welcome">Hi, <?=$user;?></div>
	<div class="nav">
		<ul>
			<li><a href="home.php" class="<? echo (isset($currentHome) ? 'current' : '') ?>">Home</a></li>
	        <li><a href="members.php" class="<? echo (isset($currentMembers) ? 'current' : '')  ?>">Members</a></li>
		</ul>
	</div>

	<div class="clear"></div>
</div>
<!-- Navigation START -->

Here you can see the usage of ternary if operator:

echo (isset($currentHome) ? 'current' : '')

And a way to call this template from a home.php file would be:

<? getTemplate("navigation.php", array("user" => getUser(), "currentHome" => true) ); ?>

So the getTemplate() function loads the navigation.php file and passes it its variables “user” and “currentHome” which are then in the getTemplate() function extracted by using the extract() function and echoed out. The currentHome variable is set  when called from the home.php file so that a template “knows” to set the “current” class to that element.

Templating engines have their pros and cons, and since I didn’t need much leverage on the templating this proved to serve me just fine.

What do you use for your template management in PHP?
Link to this article on CodeProject

CodeProject, Projects

Carcassonne scoring board application

tl;dr:

The link to the application and the link to source code on GitHub.

Welcome

First of all – hi all!, this is my first post so go easy on me 🙂

I would like to give my thanks to James Clear, whose post pushed me to finally put this blog idea up and running. He has some great posts on his blog, which you may want to check out.

The story (rather short one)

Since I’m a big fan of Carcassonne board game and I happen to come accross this unique project on the web, I just had to make one for myself… It proved to be great for Carcassonne scoring, and just recently we started using it to track scores in Qwirkle board game.

Here are some pictures of how my version of the electronic carcassonne scoring board looks like:

Web application

The idea for a web app came naturally since the electronic counter was too cumbersome to carry around. I wanted to see what “the cool kids use” these days in web development so I went to try Yeoman with Angular generator.

Below is the image of the application on iPhone and you you can see how it looks like on your device by visitng the link: http://carcassonne-scoring-board.com

How to use this project?

First you have to clone it with git, and then run npm install and bower install in the cloned folder for all the dependencies to install themselves:

git clone https://github.com/Hitman666/carcassonne-scoring-board.git
cd carcassonne-scoring-board
npm install
bower install

To test my application run

grunt server

and you should see the application open up in your browser.

What I liked

  • because of this whole Yeoman development process I liked the thing that with only few commands you have the application scaffolded out for you and you don’t have to go and install all the scripts by downloading to your computer first
  • pushing to git only takes the crucial parts of your code and not the whole dependency folders (bower_components and node_modules) which are rarely small in size – imagine, you only need to push to the repository stuff that are crucial to the application, other stuff you keep locally, and it of course is way more convenient to clone (or later push for that matter) a 1MB project than say 20MB – everyone who wants to run your project clones it and installs the needed dependencies with two simple commands (npm install and bower install)
  • while writing the application you can have grunt server “turned on” and every change you make to your files it automatically reloads the page (also its running sass to css translation so you’re covered there also)
  • developing with the Yeoman workflow is just a bliss once you get a hang of it (and it actually doesn’t have a steep learning curve) – you’ll appreciate the fact that with one command you can make your code ready for deploying (minimize, concat, optimize images, etc…)
  • since I only scratched Angulars surface, I can say I liked the data binding, the ng-repeat directive and basically the general speed-up in dev process because of this. Anyways, you can take a look at this post for more info on why Angular rocks

Conclusion

Since this project was done while I was learning (still am) Angular.js, there is a lot space for improvement (especially code structure and logic), that’s why I encourage you to give suggestions on best (better) Angular practices, or even help out on GitHub. Btw, the code on GitHub is free to use, I didn’t put any restrictions on it so feel free to fork it, improve it, alter it to suit your needs. 

The icons are from The IconFactory, and the font is Lindsay Becker in case you’re wondering.

Oh and, I would love to hear what do you think about this and for which game you used it to track scores?

Link to this article on CodeProject

Page 51 of 51« First...102030«48495051

Recent posts

  • Discipline is also a talent
  • Play for the fun of it
  • The importance of failing
  • A fresh start
  • Perseverance

Categories

  • Android (3)
  • Books (114)
    • Programming (22)
  • CodeProject (35)
  • Daily Thoughts (77)
  • Go (3)
  • iOS (5)
  • JavaScript (127)
    • Angular (4)
    • Angular 2 (3)
    • Ionic (61)
    • Ionic2 (2)
    • Ionic3 (8)
    • MEAN (3)
    • NodeJS (27)
    • Phaser (1)
    • React (1)
    • Three.js (1)
    • Vue.js (2)
  • Leadership (1)
  • Meetups (8)
  • Miscellaneou$ (77)
    • Breaking News (8)
    • CodeSchool (2)
    • Hacker Games (3)
    • Pluralsight (7)
    • Projects (2)
    • Sublime Text (2)
  • PHP (6)
  • Quick tips (40)
  • Servers (8)
    • Heroku (1)
    • Linux (3)
  • Stack Overflow (81)
  • Unity3D (9)
  • Windows (8)
    • C# (2)
    • WPF (3)
  • Wordpress (2)

"There's no short-term solution for a long-term result." ~ Greg Plitt

"Everything around you that you call life was made up by people that were no smarter than you." ~ S. Jobs

"Hard work beats talent when talent doesn't work hard." ~ Tim Notke

© since 2016 - Nikola Brežnjak