Thursday, January 7, 2016

Checking "Star Wars - The Force Awakens" tickets availability with Azure WebJobs, scriptcs and SendGrid

This user story is quite simple: there is a guy (me) who likes Star Wars. This guy wants to buy the best tickets available in an IMAX Cinema. The premiere was not so long ago, so a day after the showtimes are updated, the best seats are booked. This guy (also me) is quite lazy, so he doesn't like to check the showtimes manually.

Hm... let's do it like pro developers using cutting-edge technologies!

How the booking system works?

There is this whole UI for selecting seats and so on, however there is one interesting request which I can use to check showtimes. It look like this:
POST http://www.cinema-city.pl/scheduleInfoRows HTTP/1.1
Host: www.cinema-city.pl
Connection: keep-alive
Content-Length: 52
Accept: */*
Origin: http://www.cinema-city.pl
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: http://www.cinema-city.pl/imax
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8
Cookie: bla bla bla

locationId=1010304&date=09%2F01%2F2016&venueTypeId=2

When there is a picture show on that date it returns an HTML table with links for booking, otherwise an empty HTML table.

scriptcs to make the job done

I've written a simple scriptcs which will make a POST with appropriate headers and check if a HTML link opening tag is in the response. If that's the case, I send an email using fresh, free SendGrid account.
using System.Net;
using System.Net.Mail;
using SendGrid;

public void SendMeEmail()
{
 var myMail = new SendGridMessage();
 myMail.From = new MailAddress("Yoda@gmail.com");
 myMail.AddTo("me@gmail.com");
 myMail.Subject = "StarWars tickets are available!!";
 myMail.Text = "Go to CinemaCity IMAX to book them.";

 var credentials = new NetworkCredential("user-sendgrid@azure.com", "sendgrid-password");
 var transportWeb = new Web(credentials);
 transportWeb.DeliverAsync(myMail).Wait();
}

var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("Host", "www.cinema-city.pl");
httpClient.DefaultRequestHeaders.Add("X-Requested-With", "XMLHttpRequest");
httpClient.DefaultRequestHeaders.Add("Referer", "http://www.cinema-city.pl/imax");
httpClient.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36");

var content = new StringContent(@"locationId=1010304&date=09%2F01%2F2016&venueTypeId=2", Encoding.UTF8, @"application/x-www-form-urlencoded");
var response = httpClient.PostAsync("http://www.cinema-city.pl/scheduleInfoRows", content).Result;
var responseAsString = response.Content.ReadAsStringAsync().Result;

var isMovieAvailable = responseAsString.Contains("<a");
if(isMovieAvailable)
{
 Console.WriteLine("Movie is available, sending email");
 SendMeEmail();
 Console.WriteLine("Movie is available, email sent");
}
else
{
 Console.WriteLine("Movie is not available.");
}

Evironment setup is quite simple:
  • create a new SendGrid account
  • download scriptcs as zip (link) and unzip it to a folder StarWarsCheck
  • save the code as checkmovie.csx to folder StarWarsCheck
  • update checkmovie.csx with your SendGrid credentials
  • add reference to Sendgrid dll's by invoking scriptcs.exe -Install Sendgrid
  • now you can run the script locally. In a console write: scriptcs.exe checkmovie.csx
If you are interested on other options how one can prepare a standalone, portable scriptcs scripts - check my question on StackOverflow: How to run scriptcs without installation? Make portable/standalone scriptcs (csx)

Note: of course, once showtimes are updated, I will get email every hour. But that's good, isn't it? There is a chance I won't miss it.

Create an Azure WebJob to run scriptcs file every hour

You can use Azure WebJobs by simply uploading a .zip file with the job and configuring how it should be scheduled in Azure. The job entry point is based on naming convention. According to the documentation, the recommended script file to have in your job directory is: run.cmd. Therefore, my run.cmd look like this:
call scriptcs.exe checkmovie.csx

Next, pack whole StarWarsCheck folder as a zip file and upload it as Azure WebJob. Instructions are here.

Effects

It started with...

But then...

The email arrived without problems:

However, most importantly, I've booked the best seats for my friends & me:

Summary

It was fun, easy and profitable to play with Azure WebJobs and scriptcs. I liked the scriptcs sleekness and Azure WebJobs simplicity. For sure I'll use them for something else in the future.

3 comments:

  1. Your english is a little broken. Apart from that, good read.

    ReplyDelete
    Replies
    1. Thanks. Please, feel free to correct my mistakes.

      Delete
  2. What about scraping RyanAir website ?:D

    ReplyDelete