Cloud Answering Machine App now available in Spanish, German, and French

August 16, 2018 Leave a comment

1024

Our Cloud Answering Machine App, version 1.5, available via the iOS App store is now available in Spanish, German and French. It will automatically detect your phone language, and will switch the user interface to your preferred language.  Version 1.6, which is currently in review, will add support for Japanese, Korean and Portuguese

It also supports 32 new counties for provisioning phone numbers – which are :

Georgia
Kenya
United Arab Emirates
Bolivia
Belarus
Colombia
Philippines
Thailand
Barbados
Benin
Grenada
Ghana
Guinea
Jamaica
Trinidad and Tobago
Tanzania
Uganda
Cayman Islands
Guatemala
Algeria
Namibia
Ecuador
Tunisia
Vietnam
Mali
Bosnia and Herzegovina
Mauritius
Botswana
Macau
Singapore
Serbia

The App is also available for android, windows phone, and the web at https://www.cloudansweringmachine.com/

Advertisements
Categories: Uncategorized

UK Car Valuation #API available for free

August 15, 2018 Leave a comment

your-car-valuation

We’re now offering our UK car valuation API for free, all you need is a valid account on our website. You can access this API via the following endpoint

https://www.regcheck.org.uk/api/bespokeapi.asmx?op=CheckPrice

Where you pass the vehicle reg number, mileage and your username, and it will return data in the format (Prices are in GBP);

<Description>
Peugeot 208 (2015-) 5Dr Hatchback 1.2 PureTech SS 110 EU6 GT Line EAT Auto6
</Description>
<Price>9240</Price>
</Valuation>
The mileage of any given car can be estimated from the latest MOT report, which can be accessed via the following url;
Categories: Uncategorized

Self Updating ASP.NET website using #Octokit and #GitHub

August 15, 2018 Leave a comment

octokit-dotnet_2

Deploying a website with every check-in is quite a risky buisness, but it’s great for testing, so that your testers can be sure that they are looking at the very latest build of your website.

So, if you are using GitHub as your source control, then you can use Github’s Webhook system to trigger your website to download the latest version of itself from Github, effectively self-updating.

So, if you want to skip to the end, just check out our Github repo at https://github.com/infiniteloopltd/AutoBuild and the corresponding test website at http://autobuild.webtropy.com The website is set to automatically download content from Github on every push.

First, set up a webhook. Go to the repo, and click Settings > WebHooks > Add Webhook

webhook

Set up the payload url to point to your website, plus “github.aspx”, and keep the other settings as default.

Next, Add the following three Nuget packages to your project;

Install-Package Octokit

Install-Package SharpZipLib

Install-Package Newtonsoft.Json

and then the corresponding using statements;

using Octokit; // Install-Package Octokit
using System;
using System.Configuration;
using System.IO;
using ICSharpCode.SharpZipLib.GZip; // Install-Package SharpZipLib
using ICSharpCode.SharpZipLib.Tar; // Install-Package SharpZipLib
using System.Threading;
using Newtonsoft.Json.Linq; // Install-Package Newtonsoft.Json

Now, I’ve kept my settings in my web.config, as follows;

<add key=”GITHUB_USERNAME” value=”infiniteloopltd”/>
<add key=”GITHUB_PASSWORD” value=”xxxxxx”/>
<add key=”GITHUB_REPO” value=”AutoBuild”/>
<add key=”DEPLOY_PATH” value=”C:\temp\”/>

And, I’ve set up some public variables as follows

protected GitHubClient client = new GitHubClient(new ProductHeaderValue(“Autobuild”));
string username = ConfigurationManager.AppSettings[“GITHUB_USERNAME”];
string password = ConfigurationManager.AppSettings[“GITHUB_PASSWORD”];
string repository = ConfigurationManager.AppSettings[“GITHUB_REPO”];
string output = ConfigurationManager.AppSettings[“DEPLOY_PATH”];

The ProductHeaderValue seems arbirary, but I’ve called it AutoBuild.

Now, the magic happens when I start using Octokit;

private bool DownloadArchive(string expectedCommit)
{
var tDownload = client.Repository.Content.GetArchive(username, repository);
var bArchive = tDownload.Result;
var stream = new MemoryStream(bArchive);
Stream gzipStream = new GZipInputStream(stream);
Stream gzipStream2 = new GZipInputStream(stream);
TarInputStream tarIn = new TarInputStream(gzipStream);
TarEntry tarEntry;
var strRoot = “”;
while ((tarEntry = tarIn.GetNextEntry()) != null)
{
string name = tarEntry.Name.Replace(‘/’, Path.DirectorySeparatorChar);
if (strRoot == “”)
{
strRoot = name;
if (!strRoot.Contains(expectedCommit)) return false;
}
if (tarEntry.IsDirectory)
continue;
if (Path.IsPathRooted(name))
name = name.Substring(Path.GetPathRoot(name).Length);
name = name.Replace(strRoot, “”);
string outName = Path.Combine(output, name);
string directoryName = Path.GetDirectoryName(outName);
Directory.CreateDirectory(directoryName);
FileStream outStr = new FileStream(outName, System.IO.FileMode.Create);
tarIn.CopyEntryContents(outStr);
outStr.Close();
}
tarIn.Close();
gzipStream.Close();
stream.Close();
return true;
}

What happens here, is that I request the latest archive of my repo from GitHub, which is in TAR.GZ format. What that actually means is that it is a TAR container of files, that has been compressed into a GZip stream.

I unzip the byte array, and pass it into a TarInputStream from SharpZipLib. GitHub wraps all your files into a folder that’s named

infiniteloopltd-AutoBuild-51d1c48\

i.e. {username}-{repo}-{commit}, this means that each file needs to be extracted one by one, since this wrapper folder needs to be removed.

However, the wrapper folder comes in very handy later on.

Now, that’s where everything is nice and sensible, then it gets ugly….

Unfortunately, if you call GetArchive too soon after the webhook is called, then you get the previous commit, and that’s useless, your files don’t update.

So, therefore, I need to read the parameters sent to the webhook to ensure that the commit I am expecting matches the one in the Archive, luckily, there is plenty of data sent to the webhook by github in Json format as follows;

{
  "ref": "refs\/heads\/master",
  "before": "b75dcf060de3710bfd7c054e4869397cc75380ba",
  "after": "90d9567997f96203853e071500136a16b1335c3a",
  "created": false,
  ....

The first 7 chars of this commit guid match the code shown on the website

guid

… and also match the code contained in the wrapper folder, which allows you match the archive with the code. And if it doesn’t match, I just wait 5 seconds and try again.

So my Page_Load is defined as (With some logging)

protected void Page_Load(object sender, EventArgs e)
{
var strLog = “Started at ” + DateTime.Now;
client.Credentials = new Credentials(username, password);
var strJsonPayload = Request.Form[“Payload”];
string strExpectedCommit = “”;
if (!string.IsNullOrEmpty(strJsonPayload))
{
strLog += “\nGitHub payload ” + strJsonPayload;
var jPayload = JObject.Parse(strJsonPayload);
strExpectedCommit = jPayload[“after”].ToString().Substring(0, 7);
strLog += “\nExpected Commit ” + strExpectedCommit;
}
for(int i=0;i<10;i++)
{
var blnOK = DownloadArchive(strExpectedCommit);
if (blnOK) break;
Thread.Sleep(TimeSpan.FromSeconds(5));
strLog += “\nRetry ” + i;
}
File.WriteAllText(output + “buildlog.txt”, strLog);
}

Et Voila … every time you push a code change to GitHub. github calls this webhook, which downloads a zip of the code, and deploys it ontop of itself, creating a self-updating website! 🙂

 

 

Categories: Uncategorized

#internationalising an #Angular web app

August 9, 2018 Leave a comment

1_15CYVZdpsxir8KLdxEZytg

This perhaps is not the best way to internationalize (i.e. make available in multiple languages) an Angular web app, but it works well for me, both as a Web app, or as part of a Cordova / Phonegap app.

In App.js, I define the following “Constant”

angular.module(‘app’, [‘ionic’, …. ])

.constant(‘translations’, {

‘en’ :

{

‘Register’ : ‘Register’,

‘Login’ : ‘Login’,

},

‘es’ :

{

‘Register’ : ‘Registrar’,

‘Login’ : ‘Iniciar sesión’,

},

current : function()

{

lang = ‘en’;

if (navigator.languages != undefined) lang = navigator.languages[0]; else lang = navigator.language;

if (lang.indexOf(“es”) != -1 ) return this.es;

return this.en; // default en

}

})

Which effectively defines two languages “en” (English) and “es” (Spanish), and defines two variables, or strings within it “Login” and “Register”, you can see how the translation differs between English and Spanish. You can of course define more words, and more languages, this demo is just making a basic case.

Now, in order to use this in a controller, you pass it in as follows;

.controller(‘loginCtrl’, [‘translations’,‘$scope’, …..

function (translations, $scope, …) {

$scope.translations = translations.current();

Then you can refer to the translation in the template html as follows;

<a  class=“button” ng-click=“login()”>{{ translations.Login }}</a>

Or in code as follows;

alert($scope.translations.Login);

This, once again is going to be used in version 1.5 of our iOS app for CloudAnsweringMachine.com

Categories: Uncategorized

Send #Whatsapp message with WhatsApp #API

August 9, 2018 Leave a comment

Screen Shot 2018-08-09 at 10.08.32

The WhatsApp Business API is open for applications, which you can sign up for via https://www.facebook.com/business/m/whatsapp/business-api – and it looks like they are working with Twilio to create a webhook layer on top of this.

But, there are some simple things you can do today, for example, if you want to encourage your users to send you a WhatsApp message from your app or website, then you can add a link to;

https://api.whatsapp.com/send?phone=<your number>&text=hello

It’s important to remember that whatsapp is not typically used from the desktop, so if you want this to work, and your user is on a desktop browser, then it is better to show a QR code for the URL above – that they can scan with their phone, rather than sending them directly to this url.

Once this API is in general release, it’ll be a new feature that we’ll add to https://www.cloudansweringmachine.com

Categories: Uncategorized

Mistakes that can render your #CloudFlare protection obsolete

August 7, 2018 Leave a comment

download

Cloudflare is a service that can help keep your website safe from DDOS attacks, by taking the load of the attack without affecting your underlying server too badly.

However, assuming that your website is being specifically targeted, then it is obvious for an attacker to spot that your website is behind cloudflare, by simply checking the NS records on your domain. – So an attacker will look to find your underlying webserver, and attack it directly, rather than a “front door” attack via Cloudflare.

So, the first step, as a domain owner, is to make sure that your underlying werserver is not published anywhere on the web. Since, if you can find it – you can bet an attacker will too.

A first search is here: http://www.crimeflare.org:82/cfs.html – Scroll to the foot of the page, and enter your domain – if it’s there, make sure you change your IP address of your server, or ask the owner of this website to remove your listing from his database.

Next, check for historic A records of your domain here; https://securitytrails.com/domain/<your domain>/history/a – and make sure the IP address of the server you used before you moved to cloudFlare is no longer your production IP address.

In short, the general tip is – that if you used the same server IP before moving to CloudFlare, as you do now, – change it. Otherwise an attacker can bypass your CloudFlare protection.

 

Categories: Uncategorized

New #API to determine the current #Insurer of a vehicle in #Italy

August 3, 2018 Leave a comment

images

If you are looking to implement a system that can determine if a car is insured in Italy, and to find its current insurer, then here is an API that solves this for you;

You can also find the current insurer of a car in Italy, by calling the following API; CheckInsuranceStatusItaly at http://www.targa.co.it/api/bespokeapi.asmx , passing the number plate and your username from www.targa.co.it

The response is in XML as follows;

<InsuranceDetails xmlns:xsd=”http://www.w3.org/2001/XMLSchema&#8221; xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance&#8221; xmlns=”http://Regcheck.org.uk/”&gt;

<Company>GENERALI ITALIA</Company>

<Expiry>2019-01-03T00:00:00</Expiry>

<IsInsured>true</IsInsured>

</InsuranceDetails>

Categories: Uncategorized