Category Archives: Uncategorized

How to install wxpython

In this post we will go over the topic of easy way to install wxpython. The following command will install wxpython easily in python3.

pip install wxpython

Python 2

Older versions of wxpython can be installed by downloading binaries (for windows) from sourceforge . The binaries are available for both Windows and MacOS.

Linux

The pip install command should work on linux also. However, if you are stuck on old linux vesions. You can try installing wxpython using your distro’s package manager like apt-get or yum. You can search for exact version and package name available on your platform using the following commands for debian variants.

apt-cache search wxpython

┌──(kali㉿kali)-[~]
└─$ apt-cache search wxpython
gnumed-client - medical practice management - Client
psychopy - environment for creating psychology stimuli in Python
pyscanfcs - scientific tool for perpendicular line scanning FCS
python3-genx - differential evolution algorithm for fitting
python3-opengl - Python bindings to OpenGL (Python 3)
python3-pyface - traits-capable windowing framework
python3-squaremap - wxPython control to display hierarchic data as nested squares
python3-wxgtk-media4.0 - Python 3 interface to the wxWidgets Cross-platform C++ GUI toolkit (wx.media)
python3-wxgtk-webview4.0 - Python 3 interface to the wxWidgets Cross-platform C++ GUI toolkit (wx.html2)
python3-wxgtk4.0 - Python 3 interface to the wxWidgets Cross-platform C++ GUI toolkit
soundgrain - Graphical interface to control granular sound synthesis modules
wxglade - GUI designer written in Python with wxPython
wxpython-tools - Tools from the wxPython distribution

Successful installation

Use the following command to check if the installation is successful or not.

PS C:\Users\godson> python
Python 3.8.6 (tags/v3.8.6:db45529, Sep 23 2020, 15:52:53) [MSC v.1927 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import wx
>>> wx.version()
'4.1.1 msw (phoenix) wxWidgets 3.1.5'
>>>

As shown above it should print current version of wxpython installed if the installation is successful.

A more extensive tutorial is available here

TabLayout Example using ViewPager and Fragments in Android

If you are using the latest android application then you have noticed that now days android is following a design pattern. This is material design and it came with Android Lollipop (5.0). Though we can still use this design pattern for the older versions (>4.0) by using the support libraries. One of the component of material design is TabLayout. So in this TablLayout Example we will see how we can implement it in our android application.

What is TabLayout ?

Android TabLayout provides horizontal layout to display tabs. We can display more screens in a single screen using tabs. User can swipe the tabs quickly as you can see in the image below.

Creating a new project and add necessary libraries

Open Android Studio and create a new project. I have created DemoTabLayout.

After create a new project, First of all we have to need include design libraries in the dependencies section of our build.gradle file so include this libraries in your build.gradle file by below line.

implementation 'com.android.support:design:28.0.0'

Remove action bar from style

Now since we will be using Android Toolbar and TabLayout classes to show tabs, lets remove the action bar from layout by using styles,

Go to style.xml file and change the parent of theme which you are using in your app.Change parent with “Theme.AppCompat.Light.NoActionBar”. So now your style file will look like below code

<resources>
  <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
     <item name="colorPrimary">#3F51B5</item>
     <item name="colorPrimaryDark">#303F9F</item>
     <item name="colorAccent">#FF4081</item>
  </style>

</resources>

Creating fragments

We are creating an application which will have three tabs, So let’s define three fragment and their layouts.

First Fragment

package com.vikas.demotablayout;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
class tab1 extends Fragment {
   @Override
   public View onCreateView(LayoutInflater inflater, ViewGroup container,
               Bundle savedInstanceState) {
           return inflater.inflate(R.layout.fragment_tab1, container, false);
         }
   }

It’s layout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
     
    <TextView
      android:id="@+id/textView"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_centerInParent="true"
      android:text="Tab 1"
      android:textAppearance="?android:attr/textAppearanceLarge"/>

 </RelativeLayout>

 

Second Fragment

package com.vikas.demotablayout;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;


public class Tab2 extends Fragment {
   
   @Override
   public View onCreateView(LayoutInflater inflater, ViewGroup container,
               Bundle savedInstanceState) {
          return inflater.inflate(R.layout.fragment_tab2, container, false);
	}
   }

it’s layout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
	<TextView
          android:id="@+id/textView"
	  android:layout_width="wrap_content"
 	  android:layout_height="wrap_content"
          android:layout_centerInParent="true"
	  android:text="Tab 2"
          android:textAppearance="?android:attr/textAppearanceLarge"/>
</RelativeLayout>

Third Fragment

package com.vikas.demotablayout;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class Tab2 extends Fragment {


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

	 return inflater.inflate(R.layout.fragment_tab3, container, false);
      }

}

its layout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical">
     <TextView
        android:id="@+id/textView"
	android:layout_width="wrap_content"
        android:layout_height="wrap_content"
	android:layout_centerInParent="true"
        android:text="Tab 2"
	android:textAppearance="?android:attr/textAppearanceLarge"/>
</RelativeLayout>

Now we will define a view pager adapter to create tab swipe functionality.

package com.vikas.demotablayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;

public class PagerAdapter extends FragmentStatePagerAdapter {

    int mNumOfTabs;
    public PagerAdapter(FragmentManager fm, int NumOfTabs) {
     	super(fm);
	this.mNumOfTabs = NumOfTabs;
    }
    @Override
    public Fragment getItem(int position) {
       switch (position) {
	  case 0:
            tab1 tab1 = new tab1();
            return tab1;
          case 1:
            Tab2 tab2 = new Tab2();
            return tab2;
          case 2:
            Tab3 tab3 = new Tab3();
            return tab3;
          default:
            return null;
        }
    }
    @Override
    public int getCount() {
        return mNumOfTabs;
    }
}

Now we will create an Activity named MainActivity which will hold the tabs . This Activity will have two part first is code file and second is layout file. layout file code given below

<RelativeLayout
        android:id="@+id/main_layout"
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
	xmlns:tools="http://schemas.android.com/tools"
	android:layout_width="match_parent"
	android:layout_height="match_parent"
	tools:context=".MainActivity">
	<android.support.v7.widget.Toolbar
	    android:id="@+id/toolbar"
	    android:layout_width="match_parent"
	    android:layout_height="wrap_content"
	    android:layout_alignParentTop="true"
	    android:background="?attr/colorPrimary"
	    android:elevation="6dp"
	    android:minHeight="?attr/actionBarSize"
	    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
	    app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
	<android.support.design.widget.TabLayout
	    android:id="@+id/tab_layout"
	    android:layout_width="match_parent"
	    android:layout_height="wrap_content"
	    android:layout_below="@+id/toolbar"
	    android:background="?attr/colorPrimary"
	    android:elevation="6dp"
	    android:minHeight="?attr/actionBarSize"
	    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
	<android.support.v4.view.ViewPager
	    android:id="@+id/pager"
	    android:layout_width="match_parent"
	    android:layout_height="fill_parent"
	    android:layout_below="@id/tab_layout"/>
</RelativeLayout>

We can see above that here we add a Toolbar, second is Tablayout and third thing is Viewpager. Toolbar is for showing application name and menu icon. TabLayout is for showing Tabs and viewpager is for holding fragments. Now we write code for attach this layout with fragments in MainActivity code file. Code is given below:

package com.vikas.demotablayout;
import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;

public class MainActivity extends AppCompatActivity {

   @Override
   protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
	TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
	tabLayout.addTab(tabLayout.newTab().setText("Tab 1"));
        tabLayout.addTab(tabLayout.newTab().setText("Tab 2"));
        tabLayout.addTab(tabLayout.newTab().setText("Tab 3"));
        tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
        final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
        final PagerAdapter adapter = new PagerAdapter
                (getSupportFragmentManager(), tabLayout.getTabCount());
        viewPager.setAdapter(adapter);
        viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));

        tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
          @Override
          public void onTabSelected(TabLayout.Tab tab) {
	          viewPager.setCurrentItem(tab.getPosition());
	  }
          @Override
          public void onTabUnselected(TabLayout.Tab tab) {
	  }
          @Override
          public void onTabReselected(TabLayout.Tab tab) {
          }
        });
     }

     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
	    getMenuInflater().inflate(R.menu.menu_main, menu);
	    return true;
     }

}

That’s all, Now you can run your project.

Happy coding…

jQuery Ajax File Upload with Progress Bar

File upload should always have a progress bar. It is a feature that most of the developers ignore. It should be seen as part of the functionality. The users cannot sit in the dark and keep guessing about the background progress.

When the user requests the server to perform some operation, it is good to show them about the progress. It is a good UI/UX behaviour. The progress bar is one of the best ways to show the status of the in-progress operation. In this example, let us learn to create a progress bar using jQuery while uploading a file via AJAX.

A file input option is used to choose the file and the file binaries are posted to the server via AJAX. After sending the file upload request to the server, the AJAX script initializes jQuery animation to show the file upload progress bar. The progress bar will highlight the progressing percentage with jQuery animation. The jQuery Form plugin is used in this example code to handle the AJAX image upload with progressive status.

HTML Form with File Upload

The landing page will show a HTML form with the file input. Users will choose the file and post the file data by submitting the form via AJAX. The jQuery and jQuery Form library is included at the beginning of the script. A minimal jQuery validation script is added to check if the image file had been chosen before submitting the form.

<!DOCTYPE html>

<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">

<link rel="stylesheet" type="text/css" href="style.css">
https://code.jquery.com/jquery-3.3.1.min.js
http://jquery.form.min.js
http://uploadFile.js

</head>
<body>
    <h1>jQuery Ajax Image Upload with Animating Progress Bar</h1>
    <div class="form-container">
        <form action="uploadFile.php" id="uploadForm" name="frmupload"
            method="post" enctype="multipart/form-data">
            <input type="file" id="uploadImage" name="uploadImage" /> <input
                id="submitButton" type="submit" name='btnSubmit'
                value="Submit Image" />

        </form>
        <div class='progress' id="progressDivId">
            <div class='progress-bar' id='progressBar'></div>
            <div class='percent' id='percent'>0%</div>
        </div>
        <div style="height: 10px;"></div>
        <div id='outputImage'></div>
    </div>
</body>
</html>

AJAX Form Submit to Request Server File Upload with Progress bar

The jQuery form library is used to submit the form via AJAX with an animated progress bar. The ajaxForm() function is used to submit the image file binaries to the PHP. The progress of the image upload is shown with a progress bar in the uploadProgress callback function. Also, the jQuery animate() method is called to create the progressing effect on the progress bar element.

$(document).ready(function () {
    $('#submitButton').click(function () {
    	    $('#uploadForm').ajaxForm({
    	        target: '#outputImage',
    	        url: 'uploadFile.php',
    	        beforeSubmit: function () {
    	        	  $("#outputImage").hide();
    	        	   if($("#uploadImage").val() == "") {
    	        		   $("#outputImage").show();
    	        		   $("#outputImage").html("<div class='error'>Choose a file to upload.</div>");
                    return false; 
                }
    	            $("#progressDivId").css("display", "block");
    	            var percentValue = '0%';

    	            $('#progressBar').width(percentValue);
    	            $('#percent').html(percentValue);
    	        },
    	        uploadProgress: function (event, position, total, percentComplete) {

    	            var percentValue = percentComplete + '%';
    	            $("#progressBar").animate({
    	                width: '' + percentValue + ''
    	            }, {
    	                duration: 5000,
    	                easing: "linear",
    	                step: function (x) {
                        percentText = Math.round(x * 100 / percentComplete);
    	                    $("#percent").text(percentText + "%");
                        if(percentText == "100") {
                        	   $("#outputImage").show();
                        }
    	                }
    	            });
    	        },
    	        error: function (response, status, e) {
    	            alert('Oops something went.');
    	        },
    	        
    	        complete: function (xhr) {
    	            if (xhr.responseText && xhr.responseText != "error")
    	            {
    	            	  $("#outputImage").html(xhr.responseText);
    	            }
    	            else{  
    	               	$("#outputImage").show();
        	            	$("#outputImage").html("<div class='error'>Problem in uploading file.</div>");
        	            	$("#progressBar").stop();
    	            }
    	        }
    	    });
    });
});

 

VOIP In Matrix JS SDK

This module outlines how two users in a room can set up a Voice over IP (VoIP) call to each other. Voice and video calls are built upon the WebRTC 1.0 standard. Call signalling is achieved by sending message events to the room. In this version of the spec, only two-party communication is supported (e.g. between two peers, or between a peer and a multi-point conferencing unit). This means that clients MUST only send call events to rooms with exactly two participants.

For a complete overview of Matrix Javascript SDK configuration, please go to our Matrix Javascript SDK.

Matrix Javascript SDK

Establish a call

This method is call by the caller when they wish to establish a call.

matrixCall = matrixcs.createNewMatrixCall(
        MATRIX_CLIENT_OBJ, ROOM_ID
);

For voice call

matrixCall.placeVoiceCall();
matrixCall.setRemoteAudioElement(document.getElementById("remote-audio"));

For video call

matrixCall.placeVideoCall(
    document.getElementById("remote-video"),
    document.getElementById("local-video")
);

Incoming call event for callee

client.on("Call.incoming", function(c) {
    console.log("Call ringing");
    console.log("Incoming call");
});

Callee answer the call

This method is call by the callee when they wish to answer the call.

call.answer();

Hangup the call

Method call by either party to signal their termination of the call. This can be sent either once the call has has been established or before to abort the call.

call.hangup();

Examples

<html>
<head>
<title>VoIP Test</title>
http://lib/matrix.js
http://call.js
</head>
<body>
	You can place and receive calls with this example. Make sure to edit the
    constants in <code>call.js</code> first.
    <div id="config"></div>
    <div id="result"></div>
    <button id="call">Place Call</button>
    <button id="answer">Answer Call</button>
    <button id="hangup">Hangup Call</button>
    <div id="videoBackground">
        <div id="videoContainer">
            <video id="remote"></video>
        </div>
    </div>
    <div id="videoBackground">
        <div id="videoContainer">
            <video id="local"></video>
        </div>
    </div>
</body>
</html>
console.log("Loading browser sdk");
var BASE_URL = "https://matrix.org";
var TOKEN = "accesstokengoeshere";
var USER_ID = "@username:localhost";
var ROOM_ID = "!room:id";


var client = matrixcs.createClient({
    baseUrl: BASE_URL,
    accessToken: TOKEN,
    userId: USER_ID
});
var call;

function disableButtons(place, answer, hangup) {
    document.getElementById("hangup").disabled = hangup;
    document.getElementById("answer").disabled = answer;
    document.getElementById("call").disabled = place;
}

function addListeners(call) {
    var lastError = "";
    call.on("hangup", function() {
        disableButtons(false, true, true);
        document.getElementById("result").innerHTML = (
            "<p>Call ended. Last error: "+lastError+"</p>"
        );
    });
    call.on("error", function(err) {
        lastError = err.message;
        call.hangup();
        disableButtons(false, true, true);
    });
}

window.onload = function() {
    document.getElementById("result").innerHTML = "<p>Please wait. Syncing...</p>";
    document.getElementById("config").innerHTML = "<p>" +
        "Homeserver: <code>"+BASE_URL+"</code><br/>"+
        "Room: <code>"+ROOM_ID+"</code><br/>"+
        "User: <code>"+USER_ID+"</code><br/>"+
        "</p>";
    disableButtons(true, true, true);
};

client.on("sync", function(state, prevState, data) {
    switch (state) {
        case "PREPARED":
          syncComplete();
        break;
   }
});

function syncComplete() {
    document.getElementById("result").innerHTML = "<p>Ready for calls.</p>";
    disableButtons(false, true, true);

    document.getElementById("call").onclick = function() {
        console.log("Placing call...");
        call = matrixcs.createNewMatrixCall(
            client, ROOM_ID
        );
        console.log("Call => %s", call);
        addListeners(call);
        call.placeVideoCall(
            document.getElementById("remote"),
            document.getElementById("local")
        );
        document.getElementById("result").innerHTML = "<p>Placed call.</p>";
        disableButtons(true, true, false);
    };

    document.getElementById("hangup").onclick = function() {
        console.log("Hanging up call...");
        console.log("Call => %s", call);
        call.hangup();
        document.getElementById("result").innerHTML = "<p>Hungup call.</p>";
    };

    document.getElementById("answer").onclick = function() {
        console.log("Answering call...");
        console.log("Call => %s", call);
        call.answer();
        disableButtons(true, true, false);
        document.getElementById("result").innerHTML = "<p>Answered call.</p>";
    };

    client.on("Call.incoming", function(c) {
        console.log("Call ringing");
        disableButtons(true, false, false);
        document.getElementById("result").innerHTML = "<p>Incoming call...</p>";
        call = c;
        addListeners(call);
    });
}
client.startClient();

 

React Quickstart Tutorial

React is a JavaScript library created by Facebook.
ReactJS is a tool for building UI components.

Adding React to an HTML Page

This quickstart tutorial will add React to a page like this:

Example

<!DOCTYPE html>
<html lang="en">
<title>Test React</title>

<!-- Load React API -->
https://unpkg.com/react@16/umd/react.production.min.js
<!-- Load React DOM-->
https://unpkg.com/react-dom@16/umd/react-dom.production.min.js
<!-- Load Babel Compiler -->
https://unpkg.com/babel-standalone@6.15.0/babel.min.js

<body>


    //  JSX Babel code goes here


</body>
</html>

What is Babel?

Babel is a JavaScript compiler that can translate markup or programming languages into JavaScript.

With Babel, you can use the newest features of JavaScript (ES6 – ECMAScript 2015).

Babel is available for different conversions. React uses Babel to convert JSX into JavaScript.

Please note that is needed for using Babel.


What is JSX?

JSX stands for JavaScript XML.
JSX is an XML/HTML like extension to JavaScript.

Example

const element = <h1>Hello World!</h1>

As you can see above, JSX is not JavaScript nor HTML.

JSX is a XML syntax extension to JavaScript that also comes with the full power of ES6 (ECMAScript 2015).

Just like HTML, JSX tags can have a tag names, attributes, and children. If an attribute is wrapped in curly braces, the value is a JavaScript expression.

Note that JSX does not use quotes around the HTML text string.

React DOM Render

The method ReactDom.render() is used to render (display) HTML elements:

Example

Hello World!
ReactDOM.render( <h1>Hello React!</h1>, document.getElementById('id01'));

JSX Expressions

Expressions can be used in JSX by wrapping them in curly {} braces.

Example

Hello World!
const name = 'John Doe'; ReactDOM.render( <h1>Hello {name}!</h1>, document.getElementById('id01'));

React Elements

React applications are usually built around a single HTML element.

React developers often call this the root node (root element):

React elements look like this:

const element = <h1>Hello React!</h1>

Elements are rendered (displayed) with the ReactDOM.render() method:

ReactDOM.render(element, document.getElementById('root'));

React elements are immutable. They cannot be changed.

The only way to change a React element is to render a new element every time:

Example

function tick() {
    const element = (<h1>{new Date().toLocaleTimeString()}</h1>);
    ReactDOM.render(element, document.getElementById('root'));
}
setInterval(tick, 1000);

React Components

React components are JavaScript functions.

This example creates a React component named “Welcome”:

Example

function Welcome() {
    return <h1>Hello React!</h1>;
}
ReactDOM.render(<Welcome />, document.getElementById('root'));

React can also use ES6 classes to create components.

This example creates a React component named Welcome with a render method:

Example

class Welcome extends React.Component {
    render() { return(<h1>Hello React!</h1>); }
}
ReactDOM.render(<Welcome />, document.getElementById('root'));

React Component Properties

This example creates a React component named “Welcome” with property arguments:

Example

function Welcome(props) {
    return <h1>Hello {props.name}!</h1>;
}
ReactDOM.render(<Welcome name="John Doe"/>, document.getElementById('root'));

React can also use ES6 classes to create components.

This example also creates a React component named “Welcome” with property arguments:

Example

class Welcome extends React.Component {
    render() { return(<h1>Hello {this.props.name}</h1>); }
}
ReactDOM.render(<Welcome name="John Doe"/>, document.getElementById('root'));

 JSX Compiler

The examples on this page compiles JSX in the browser.

For production code, the compilation should be done separately.


Create React Application

Facebook has created a Create React Application with everything you need to build a React app.

It is a a development server that uses Webpack to compile React, JSX, and ES6, auto-prefix CSS files.

The Create React App uses ESLint to test and warn about mistakes in the code.

To create a Create React App run the following code on your terminal:

Example

npx create-react-app react-tutorial

Make sure you have Node.js 5.2 or higher. Otherwise you must install npx:

Example

npm i npx

Start one folder up from where you want your application to stay:

Example

C:\Users\myUser>npx create-react-app react-tutorial

Success Result:

npx: installed 63 in 10.359s
Creating a new React app in C:\Users\myUser\react-tutorial.
Installing packages. This might take a couple of minutes.
Installing react, react-dom, and react-scripts...
+ react-dom@16.5.2
+ react@16.5.2
+ react-scripts@2.0.4
added 1732 packages from 664 contributors and audited 31900 packages in 355.501s
found 0 vulnerabilities+ react@16.5.2

Success! Created react-tutorial at C:\Users\myUser\react-tutorial
Inside that directory, you can run several commands:

npm start
Starts the development server.

npm run build
Bundles the app into static files for production.

npm test
Starts the test runner.

npm run eject
Removes this tool and copies build dependencies, configuration files
and scripts into the app directory. If you do this, you can't go back!

We suggest that you begin by typing:

cd react-tutorial
npm start

Matrix Javascript SDK

Matrix Client-Server r0 SDK for JavaScript. This SDK can be run in a browser or in Node.js.

Quickstart

In a browser

Download either the full or minified version from https://github.com/matrix-org/matrix-js-sdk/releases/latest and add that as a <script> to your page. There will be a global variable matrixcs attached to window through which you can access the SDK. See below for how to include libolm to enable end-to-end-encryption.

Please check the working browser example for more information.

In Node.js

Ensure you have the latest LTS version of Node.js installed.

Using yarn instead of npm is recommended. Please see the Yarn install guide if you do not have it already.

yarn add matrix-js-sdk

var sdk = require("matrix-js-sdk");
var client = sdk.createClient("https://matrix.org");
client.publicRooms(function(err, data) {
    console.log("Public Rooms: %s", JSON.stringify(data));
});

See below for how to include libolm to enable end-to-end-encryption. Please check the Node.js terminal app for a more complex example.

To start the client:

await client.startClient({initialSyncLimit: 10});

You can perform a call to /sync to get the current state of the client:

client.once('sync', function(state, prevState, res) {
    if(state === 'PREPARED') {
        console.log("prepared");
    } else {
        console.log(state);
        process.exit(1);
    }
});

To send a message:

var content = {
    "body": "message text",
    "msgtype": "m.text"
};
client.sendEvent("roomId", "m.room.message", content, "", (err, res) => {
    console.log(err);
});

To listen for message events:

client.on("Room.timeline", function(event, room, toStartOfTimeline) {
  if (event.getType() !== "m.room.message") {
    return; // only use messages
  }
  console.log(event.event.content.body);
});

By default, the matrix-js-sdk client uses the MemoryStore to store events as they are received. For example to iterate through the currently stored timeline for a room:

Object.keys(client.store.rooms).forEach((roomId) => {
  client.getRoom(roomId).timeline.forEach(t => {
      console.log(t.event);
  });
});

What does this SDK do?

This SDK provides a full object model around the Matrix Client-Server API and emits events for incoming data and state changes. Aside from wrapping the HTTP API, it:

  • Handles syncing (via /initialSync and /events)
  • Handles the generation of “friendly” room and member names.
  • Handles historical RoomMember information (e.g. display names).
  • Manages room member state across multiple events (e.g. it handles typing, power levels and membership changes).
  • Exposes high-level objects like Rooms, RoomState, RoomMembers and Users which can be listened to for things like name changes, new messages, membership changes, presence changes, and more.
  • Handle “local echo” of messages sent using the SDK. This means that messages that have just been sent will appear in the timeline as ‘sending’, until it completes. This is beneficial because it prevents there being a gap between hitting the send button and having the “remote echo” arrive.
  • Mark messages which failed to send as not sent.
  • Automatically retry requests to send messages due to network errors.
  • Automatically retry requests to send messages due to rate limiting errors.
  • Handle queueing of messages.
  • Handles pagination.
  • Handle assigning push actions for events.
  • Handles room initial sync on accepting invites.
  • Handles WebRTC calling.

Later versions of the SDK will:

  • Expose a RoomSummary which would be suitable for a recents page.
  • Provide different pluggable storage layers (e.g. local storage, database-backed)

 Usage

 Conventions

 Emitted events

The SDK will emit events using an EventEmitter. It also emits object models (e.g. Rooms, RoomMembers) when they are updated.

// Listen for low-level MatrixEvents
client.on("event", function(event) {
    console.log(event.getType());
});

// Listen for typing changes
client.on("RoomMember.typing", function(event, member) {
    if (member.typing) {
      console.log(member.name + " is typing...");
    }
    else {
      console.log(member.name + " stopped typing.");
    }
});

// start the client to setup the connection to the server
client.startClient();

Promises and Callbacks

Most of the methods in the SDK are asynchronous: they do not directly return a result, but instead return a Promise which will be fulfilled in the future.

The typical usage is something like:

matrixClient.someMethod(arg1, arg2).done(function(result) {
    ...
});

Alternatively, if you have a Node.js-style callback(err, result) function, you can pass the result of the promise into it with something like:

matrixClient.someMethod(arg1, arg2).nodeify(callback);

The main thing to note is that it is an error to discard the result of a promise-returning function, as that will cause exceptions to go unobserved. If you have nothing better to do with the result, just call .done() on it. See http://documentup.com/kriskowal/q/#the-end for more information.

Methods which return a promise show this in their documentation.

Many methods in the SDK support both Node.js-style callbacks and Promises, via an optional callback argument. The callback support is now deprecated: new methods do not include a callback argument, and in the future it may be removed from existing methods.

Examples

This section provides some useful code snippets which demonstrate the core functionality of the SDK. These examples assume the SDK is setup like this:

var sdk = require("matrix-js-sdk");
var myUserId = "@example:localhost";
var myAccessToken = "QGV4YW1wbGU6bG9jYWxob3N0.qPEvLuYfNBjxikiCjP";
var matrixClient = sdk.createClient({
    baseUrl: "http://localhost:8008",
    accessToken: myAccessToken,
    userId: myUserId
});

Automatically join rooms when invited

matrixClient.on("RoomMember.membership", function(event, member) {
    if (member.membership === "invite" && member.userId === myUserId) {
        matrixClient.joinRoom(member.roomId).done(function() {
           console.log("Auto-joined %s", member.roomId);
        });
    }
});

matrixClient.startClient();

Print out messages for all rooms

matrixClient.on("Room.timeline", function(event, room, toStartOfTimeline) {
    if (toStartOfTimeline) {
        return; // don't print paginated results
    }
    if (event.getType() !== "m.room.message") {
        return; // only print messages
    }
    console.log(
        // the room name will update with m.room.name events automatically
        "(%s) %s :: %s", room.name, event.getSender(), event.getContent().body
    );
});

matrixClient.startClient();

Output:

(My Room) @megan:localhost :: Hello world
(My Room) @megan:localhost :: how are you?
(My Room) @example:localhost :: I am good
(My Room) @example:localhost :: change the room name
(My New Room) @megan:localhost :: done

Print out membership lists whenever they are changed

matrixClient.on("RoomState.members", function(event, state, member) {
    var room = matrixClient.getRoom(state.roomId);
    if (!room) {
       return;
    }
    var memberList = state.getMembers();
    console.log(room.name);
    console.log(Array(room.name.length + 1).join("="));  // underline
    for (var i = 0; i < memberList.length; i++) {
       console.log(
       "(%s) %s",
           memberList[i].membership,
           memberList[i].name
       );
    }
});

matrixClient.startClient();

Output:

My Room
=======
(join) @example:localhost
(leave) @alice:localhost
(join) Bob
(invite) @charlie:localhost

API Reference

A hosted reference can be found at http://matrix-org.github.io/matrix-js-sdk/index.html

This SDK uses JSDoc3 style comments. You can manually build and host the API reference from the source files like this:

$ yarn gendoc
$ cd .jsdoc
$ python -m SimpleHTTPServer 8005

Then visit http://localhost:8005 to see the API docs.

End-to-end encryption support

The SDK supports end-to-end encryption via the Olm and Megolm protocols, using libolm. It is left up to the application to make libolm available, via the Olm global.

It is also necessry to call matrixClient.initCrypto() after creating a new MatrixClient (but before calling matrixClient.startClient()) to initialise the crypto layer.

If the Olm global is not available, the SDK will show a warning, as shown below; initCrypto() will also fail.

Unable to load crypto module: crypto will be disabled: Error: global.Olm is not defined

If the crypto layer is not (successfully) initialised, the SDK will continue to work for unencrypted rooms, but it will not support the E2E parts of the Matrix specification.

To provide the Olm library in a browser application:

To provide the Olm library in a node.js application:

  • yarn add https://packages.matrix.org/npm/olm/olm-3.0.0.tgz (replace the URL with the latest version you want to use from https://packages.matrix.org/npm/olm/)
  • global.Olm = require('olm'); before loading matrix-js-sdk.

If you want to package Olm as dependency for your node.js application, you can use yarn add https://packages.matrix.org/npm/olm/olm-3.0.0.tgz. If your application also works without e2e crypto enabled, add --optional to mark it as an optional dependency.

Contributing

This section is for people who want to modify the SDK. If you just want to use this SDK, skip this section.

First, you need to pull in the right build tools:

$ yarn install

Building

To build a browser version from scratch when developing::

$ yarn build

To constantly do builds when files are modified (using watchify)::

$ yarn watch

To run tests (Jasmine)::

$ yarn test

To run linting:

$ yarn lint

Fusebill AJAX Transparent Redirect

To facilitate PCI compliant credit card collections Fusebill provides a AJAX Transparent Redirect endpoint which you can use to securely capture customer’s credit cards. If you are adding the first payment method on a customer, it will be set to the default payment method automatically.

This API action is authenticated with a separate Public API Key. If you do not have that key, please contact Fusebill Support. The Public Key can only be used to authenticate the Transparent Redirect action.

Google reCAPTCHA required.

Fusebill leverages reCAPTCHA technology to ensure payment method data captured is provided by a human and to protect against bots and scripting.

We use Google reCAPTCHA V2 in order to accomplish this.
https://developers.google.com/recaptcha/intro
The basic workflow for how this is accomplished is as follows:

  • Using Fusebill’s public site key, the client is presented with a captcha widget.
  • The user then verifies that they are human, starting with a check box. The user may be presented with additional verification steps such as an image recognition task.
  • The captcha widget then verifies with Google that the user is human, and returns a response token.
  • That response token is then sent to Fusebill with the payment method data for our system to validate and verify.
Fusebill Environment
reCAPTCHA Public Site Key

Staging (stg-payments.subscriptionplatform.com)

6LcI_GwUAAAAAJZu0VvB68DdxNxb5ZcBIwAX7RVj

Sandbox and Production (payments.subscriptionplatform.com)

6LfVtGwUAAAAALHn9Ycaig9801f6lrPmouzuKF11

Create Credit Card Payment Method

Field Name
Details
Required
Type

CustomerID

This is the Fusebill customer ID of the customer you wish to add the card to

Yes

Number

PublicAPIKey

This is your public API key.
This is found in fusebill account under Settings > Integrations > Transparent Redirect.

Yes

String

CardNumber

This is the credit card number.

Yes

Number

FirstName

 

The first name of the cardholder.

Yes

String

LastName

The last name of the card holder.

Yes

String

ExpirationMonth

Expiration month on the credit card.

Yes

Number

ExpirationYear

Expiration on the credit card.

Yes

Number

CVV

The credit card verification number.

Yes

Number

recaptcha

Recaptcha token response.

Yes

String

riskToken

WePay Risk token

No+

String

clientIp

Client/Customer IP address

No+

String

email

Customer Email address

No+

String

address1

First line of payment method address.

No*

String

address2

Second line of payment method address.

No*

String

city

City of the payment method

No*

String

stateId

State ID of the Payment method.
These can be found by performing a GET to v1/countries

No*

Number

countryId

Country ID of the payment method.
These can be found by performing a GET to v1/countries

No*

Number

postalZip

PostalZip of the payment method

No*

String

paymentCollectOptions

Object that allows specifying an amount to collect when creating the card.

Only works through Json
{
"collectionAmount": 1.0
}

No

Object

+ Denotes a field required for Fusebill Payments API Risk Fields
* Denotes fields required for AVS and may be required by your account’s Gateway. These fields are also required if using Fusebill Payments accounts as AVS is mandatory.

Notes:- Address information can optionally be captured as well.

Sample Code

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
	<head>
		<title>AJAX Transparent Redirect</title>
		http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js
		
		
		
		
      var verifyCallback = function(response) {
        document.getElementById("mySubmit").disabled = false;
        $('input#recaptcha_token').val(response);
      };
      var expCallback = function () {
        document.getElementById("mySubmit").disabled = true;
        grecaptcha.reset();
      };
      var onloadCallback = function() {
        grecaptcha.render('exampleWithCallback', {
          'sitekey': '',
          'callback': verifyCallback,
          'expired-callback': expCallback
        });
      };
      
			function AJAXTransparentRedirect() {                                 
				var dataString = 'CustomerId='+ $('input#CustomerId').val() + 
						'&PublicApiKey=' + $('input#PublicApiKey').val() + 
						'&SuccessUri='+$('input#SuccessUri').val() +
						'&FailUri='+$('input#FailUri').val() + 
						'&CardNumber='+$('input#CardNumber').val() + 
						'&FirstName='+$('input#FirstName').val() + 
						'&LastName='+$('input#LastName').val() + 
						'&ExpirationMonth='+$('input#ExpirationMonth').val() + 
						'&ExpirationYear='+$('input#ExpirationYear').val() + 
						'&makeDefault='+$('input#MakeDefault').val() + 
						'&Cvv='+$('input#Cvv').val() +
						'&recaptcha=' + $('input#recaptcha_token').val();
				alert(dataString);

				//Set up the request
				var request = $.ajax({
					type: "POST",
					url: "https://stg-payments.subscriptionplatform.com/api/paymentsv2/",                   
					data: dataString 
				});

				//Set up the callback functions
				request.done(function (msg) {
					//$('#response').append("

success

"); alert("success"); //document.location.replace = ''; }); request.fail(function (jqXHR) { // $('#response').append("

failure

"); alert(parseAndBuildErrorMessage(jqXHR)); //document.location.replace = ''; expCallback(); }); } function htmlEscape(msg) { return document.createElement('span') .appendChild(document.createTextNode(msg)) .parentNode .innerHTML; } function buildErrorMessage (errors) { if (errors.length == 0) { return ""; } var message; if (errors.length > 1) { message = "
    "; for (var i = 0; i " + htmlEscape(errors[i].Value) + ""; } } message += "
"; } else { var internalErrors = errors[0].Value; internalErrors = internalErrors.split("\r\n"); if (internalErrors.length > 1) { message = "
    "; for (var i = 0; i " + htmlEscape(internalErrors[i]) + ""; } message += "
"; } } else { message = htmlEscape(errors[0].Value); } } return message; } function parseAndBuildErrorMessage (xhr) { if (xhr.status >= 500) return "An error occurred, please try again"; else return buildErrorMessage(xhr.responseJSON.Errors); } </head> <body> <form id="allfields"> <fieldset> <div> <label for="CustomerId">Customer Id</label> <input autofocus="autofocus" id="CustomerId" name="CustomerId" type="text" value="your customer id here" /> </div> <div> <label for="PublicApiKey">Public Api Key</label> <input id="PublicApiKey" name="PublicApiKey" type="text" value="your key here" /> </div> <div> <label for="CardNumber">Card number</label> <input id="CardNumber" name="CardNumber" type="text" value="4111111111111111" /> </div> <div> <label for="FirstName">First name</label> <input id="FirstName" name="FirstName" type="text" value="John" /> </div> <div> <label for="LastName">Last name</label> <input id="LastName" name="LastName" type="text" value="Doe" /> </div> <div> <label for="ExpirationMonth">Expiry month</label> <input id="ExpirationMonth" name="ExpirationMonth" type="text" value="12" /> </div> <div> <label for="ExpirationYear">Expiry year</label> <input id="ExpirationYear" name="ExpirationYear" type="text" value="20" /> </div> <div> <label for="Cvv">CVV</label> <input id="Cvv" name="Cvv" type="text" value="123" /> </div> <input id="MakeDefault" name="MakeDefault" type="hidden" value="true" /> <div class="g-recaptcha" id="exampleWithCallback"></div> <input id="recaptcha_token" name="recaptcha_token" type="hidden" /> <fieldset> </form> <input type="button" onCLick="AJAXTransparentRedirect();" value="Submit Card" id="mySubmit" disabled /> <div id="response"/> </body> </html> https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit

Sample Response

{
    "maskedCardNumber" : "************1111",
    "cardType" : "Visa",
    "expirationMonth" : 10,
    "expirationYear" : 23,
    "customerId" : 50975,
    "firstName" : "a",
    "lastName" : "a",
    "address1" : null,
    "address2" : null,
    "countryId" : null,
    "country" : "",
    "stateId" : null,
    "state" : "",
    "city" : null,
    "postalZip" : null,
    "makeDefault" : true,
    "id" : 5933,
    "uri" : null
}

Fusebill Payments

When using Fusebill Payments as your gateway processing account, some additional processing and data is required.

These are the ClientIP and a Risk token.

Additional information is available here.

Fusebill Test Gateways

Available here.

Task Notification Bot for slack with Django

Slack is a great platform for team collaboration not just that it also has one of the best API interfaces to build Chatbots.

In this post, I will walk you through building a minimal Slack Bot with Django backend. The idea is to set up a Slack Bot that will notify event when greeted through a backend.

Before we start let us understand the Slack bots life cycle:

  • If you are new to Slack, It’s a messaging platform focused on team collaboration. Slack lets you create custom applications, including bots (sort of Messaging Platform as a Service). You will run the application back end to process business logic in your own server.
  • To start with, you need to be part of the Slack team and have admin privilege to create a new Slack App. If you are not part of a Slack team you may create one.
  • GIve the name of your company or team.

  • Enter Channel Name.
  • Click on See your channel in slack
  • We will create a Slack App for the Slack team then we will add a Bot User to the app.
  • We will create a Django based backend web application to post the messages into slack.
  • After setting up the Slack App and have the backend ready to notified events.

Create a Slack App

Start by creating a Slack app here, click Create App. Then proceed with app creation, give it a name and select the Slack team.

Then you will be taken to App configuration where you need do following to get our Bot up and running.

  1. Create a Bot User
  2. Install Slack App to your Team

Create a BOT User

On the left pane click on Bot User then choose a user name for the Bot and set “Always Show My Bot as Online” slider to on. Click on Add Bot User to create our shipment bot.

Install Slack App to Team

Now on the left pane click Install App and install the app to your Slack team.

Once installed you will get Bot User OAuth Access Token, note down this token we will need it later while configuring Django app. This token is the passphrase for our Bot to interact with the Slack Team.

Slack Client Credentials

Also, note down the App Credentials from Basic Information on the left pane. These credentials let us talk to Slack API, so every time we send a message to Slack we should send our Client ID(CLIENT_ID) & Client Secret(CLIENT_SECRET) to identify ourselves to Slack. Similarly, we can verify if an incoming message is sent by Slack checking if the Verification Token (VERIFICATION_TOKEN) in the message is the same as the one in App Credentials.

Now we should have four key values with us.

  1. Client ID — SLACK_CLIENT_ID/li>
  2. Client Secret — SLACK_CLIENT_SECRET
  3. Verification Token — SLACK_VERIFICATION_TOKEN
  4. Bot User Token — SLACK_BOT_USER_TOKEN

Environment Setup

Let us create a new virtual environment “venv” for our project with python version 3.6.x and activate the virtual environment.

virtualenv venv –python=python3.6

You need to activate the virtual environment before installation of other dependencies.

source venv/bin/activate

Now let’s install required packages

pip install django
pip install slacker
pip install slacker-log-handler

Create a Django Application

django-admin startproject shipment_portal
cd shipment
django-admin startapp shipment

Configure Django Settings

we need to add our own application shipment as a dependency. Add the line mentioned below in the file slack/settings.py

# slack/settings.py

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'shipment', # <== add this line
]

Then add following configurations in slack_bot/settings.py with your authentication keys from Slack.

# slack/settings.py

# SLACK API Configurations
# ----------------------------------------------
# use your keys
SLACK_CLIENT_ID = '20xxxxxxxxxx.20xxxxxxxxxx'
SLACK_CLIENT_SECRET = 'd29fe85a95c9xxxxxxxxxxxxxxxxxxxxx'
SLACK_VERIFICATION_TOKEN = 'xpxxxxxxxxxxxxxxxxxxxxxxxxx'
SLACK_BOT_USER_TOKEN = 'xoxb-xxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxx'

Now start the Django development server

python manage.py runserver

Once the server is started it will print something similar to this

Performing system checks…
System check identified no issues (0 silenced).
You have 13 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run ‘python manage.py migrate’ to apply them.
July 03, 2017–17:30:32
Django version 1.11.3, using settings ‘shipment_portal.settings’
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Ignore the migration warnings and open the URL in your browser.

Create an API endpoint

Now that we have our app server up and running we need to create an endpoint for Slack to send event messages. We will create an API view with Django as follows:

Shipment/view.py

class ShipmentCreate(LoginRequiredMixin, View):

def post(self, request, *args, **kwargs):
try:
user = request.user.id
===============
Your code goes here............
===============
response = {
'status': 200,
'type': '+OK',
'message': 'Shipment created',
}
message = 'Shipment created by' + user
send_notification(message, channel='#general')

except Exception as error:
response = {
'status': 500,
'type': '-ERR',
'message': 'Internal Server Error',
}
return JsonResponse(response, status=response.get('status'))

Configure Django Routes

If you are new to web applications, routing is the way to tell web server which functions to invoke when an URL is hit with a request. When the URL is hit with a request message the corresponding function will be invoked, passing the requester message as a parameter to the function.
Add following lines in shipment/urls.py to tie shipment API class to http://localhost:8000/shipment/

from .views import *
from django.conf.urls import url
urlpatterns = [
 url(r'^shipment/$', Shipment.as_view(), name='shipment'),
 ]

slackapi.py

Functions written in slackapi.py are used to post notification/messages to slack.

import os
from datetime import datetime
from slacker import Slacker
from django.conf import settings
slack = Slacker(settings.SLACK_SECRET_KEY)
TEST_CHANNEL = os.environ.get('TEST_SLACK_CHANNEL', None)
channel_details = {
"#general": {
"username": 'shipment-' + settings.ENVIRON,
"icon_url": None,
"icon_emoji": ":email:"
},
"@Jeenal": {},
}
def post_to_slack(message, channel, username=None, icon_url=None, icon_emoji=None):
try:
channel = TEST_CHANNEL or channel
channel_info = channel_details.get(channel, dict())
slack.chat.post_message(
channel=channel,
text=message,
username=username or channel_info.get("username"),
icon_url=icon_url or ((not icon_emoji) and channel_info.get("icon_url")) or None,
icon_emoji=icon_emoji or ((not icon_url) and channel_info.get("icon_emoji")) or None,
as_user=False
)
except Exception as e:
slack_logger.error('Error post message to slack\n', exc_info=True)

def send_notification(message, channel):
try:
post_to_slack(message, channel)
except Exception as e:
slack_logger.error('Error send notification to slack\n', exc_info=True)

 

 

 

Network namespaces – part 2

How to run OpenVPN tunnel inside a network namespace

Linux network namespaces can be used to control which processes should be tunneled by OpenVPN.

First create an –up and –down script for OpenVPN. This script will create the VPN tunnel interface inside a network namespace called vpn, instead of the default namespace.

cat > netns-up << EOF
#!/bin/sh
case $script_type in
        up)
                ip netns add vpn
                ip netns exec vpn ip link set dev lo up
                mkdir -p /etc/netns/vpn
                echo "nameserver 8.8.8.8" > /etc/netns/vpn/resolv.conf
                ip link set dev "$1" up netns vpn mtu "$2"
                ip netns exec vpn ip addr add dev "$1" \
                        "$4/${ifconfig_netmask:-30}" \
                        ${ifconfig_broadcast:+broadcast "$ifconfig_broadcast"}
                test -n "$ifconfig_ipv6_local" && \
          ip netns exec vpn ip addr add dev "$1" \
                        "$ifconfig_ipv6_local"/112
                ;;
        route-up)
                ip netns exec vpn ip route add default via "$route_vpn_gateway"
                test -n "$ifconfig_ipv6_remote" && \
          ip netns exec vpn ip route add default via \
                        "$ifconfig_ipv6_remote"
                ;;
        down)
                ip netns delete vpn
                ;;
esac
EOF

Then start OpenVPN and tell it to use our –up script instead of executing ifconfig and route.

openvpn --ifconfig-noexec --route-noexec --up netns-up --route-up netns-up --down netns-up

Now you can start programs to be tunneled like this:

ip netns exec vpn command

Or start a separate shell

ip netns exec vpn command