Synload Development

Development Blog

Nathaniel Davidson, Web Developer

Annoyed by too many tabs? - 2013-12-21

Annoyed by too many tabs open in chrome? fix that by saving a window for later. This chrome extension will save all the tabs urls to the synload server. This is stored and accessible only by a unique key that is generated on the client side, this includes encryption of the urls. Even if there is a security breach there will be no possibility to link it back to you or to find out what urls you stored.

This is a development build and is still in the testing phase.

Download Chrome Extension

Coded in [ Javascript, PHP, MySQL, JSON ]

Synchronized Video Player - 2013-9-14

So there are many issues that relate to video playback for groups of people. As this is a problem that I have encountered several times, a low cost solution was needed. Using websockets as a medium between the other members of the group. It does this by keeping track of each group members progress in the video.

The main issue is how to handle the group timings, should the entire group have the power to tell others to slow down, or to speed up. This would cause several issues some of which are security based. You would have people being able to join a group then forcing people to constantly pause/play, or load other videos. So another solution which was ultimately chosen, a leader based group video player. There would be one leader of a session. The leader controls the groups video players, both manually and automatically. The group members are sent commands to keep up with the leader which are play/pause/seek/loading new videos. This technique keeps the group members synced and watching together within 2 seconds in video progress from the leader ( bandwidth issues can impact the sync % ). When a leader has left the group, the new leader is chosen from the remaining group members in order of who connected.

Link will go here for the video player

Coded in [ PHP, JAVA, Javascript, Websockets, Ajax ]

Paypal REST API Class - 2013-4-28

<?php
class PayPal{
    private $auth;
    private $options;
    private $tData;
    private $m;
    public function __construct($clientID,$secret,$options){
        $this->auth=$clientID.":".$secret;
        $this->grabToken();
        $this->options = $options;
        $this->m = new Memcached();
        $this->m->addServers(array(
            array('127.0.0.1',11211),
        ));
    }
    private function grabToken(){
        $tokenReq = curl_init();
        $postData="grant_type=client_credentials";
        curl_setopt($tokenReq, CURLOPT_URL, 
            "https://api.sandbox.paypal".
            ".com/v1/oauth2/token"
        ); 
        curl_setopt($tokenReq, CURLOPT_PORT , 443); 
        curl_setopt($tokenReq, CURLOPT_VERBOSE, 0); 
        curl_setopt($tokenReq, CURLOPT_HEADER, 0); 
        curl_setopt($tokenReq, CURLOPT_FOLLOWLOCATION, true); 
        curl_setopt($tokenReq, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
        curl_setopt($tokenReq, CURLOPT_RETURNTRANSFER, 1); 
        curl_setopt($tokenReq, CURLOPT_HTTPHEADER, array(
                "Accept: application/json",
                "Accept-Language: en_US",
                "Content-length: ".strlen($postData)
            )
        ); 
        curl_setopt($tokenReq, CURLOPT_USERPWD, $this->auth);
        curl_setopt($tokenReq, CURLOPT_POST,true); 
        curl_setopt($tokenReq, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
        curl_setopt($tokenReq, CURLOPT_SSL_VERIFYHOST, 0); 
        curl_setopt($tokenReq, CURLOPT_SSL_VERIFYPEER, 0); 
        curl_setopt($tokenReq, CURLOPT_POSTFIELDS,$postData); 
        $this->tData = json_decode(curl_exec($tokenReq)); 
        curl_close($tokenReq);
    }
    private function request($uri,$postData){
        $postData = json_encode($postData);
        $tokenReq = curl_init();
        curl_setopt($tokenReq, CURLOPT_URL, "https://api.sandbox.paypal.com".$uri); 
        curl_setopt($tokenReq, CURLOPT_PORT , 443); 
        curl_setopt($tokenReq, CURLOPT_VERBOSE, 0); 
        curl_setopt($tokenReq, CURLOPT_HEADER, 0); 
        curl_setopt($tokenReq, CURLOPT_FOLLOWLOCATION, true); 
        curl_setopt($tokenReq, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
        curl_setopt($tokenReq, CURLOPT_RETURNTRANSFER, 1); 
        if(strlen($postData)!=0){
            curl_setopt($tokenReq, CURLOPT_POST,true);
            curl_setopt($tokenReq, CURLOPT_HTTPHEADER, array(
                "Content-Type: application/json",
                "Accept-Language: en_US",
                "Authorization:Bearer ".$this->tData->access_token,
                "Content-length: ".strlen($postData)
                )
            );
            curl_setopt($tokenReq, CURLOPT_POSTFIELDS,$postData); 
        }else{
            curl_setopt($tokenReq, CURLOPT_HTTPHEADER, array(
                    "Content-Type: application/json",
                    "Accept-Language: en_US",
                    "Authorization:Bearer ".$this->tData->access_token
                )
            ); 
            curl_setopt($curl_handle, CURLOPT_HTTPGET, TRUE);
        }
        curl_setopt($tokenReq, CURLOPT_SSL_VERIFYHOST, 0); 
        curl_setopt($tokenReq, CURLOPT_SSL_VERIFYPEER, 0); 
        return json_decode(curl_exec($tokenReq)); 
        curl_close($tokenReq);
    } 
    public function createPayment($price,$description){
        $f=[
            "intent"=>"sale",
            "payer"=>[
                "payment_method"=>"paypal"
            ],
            "redirect_urls"=>[
                "return_url"=>$this->options['return'],
                "cancel_url"=>$this->options['cancel']
            ],
            "transactions"=>[
                [
                    "amount"=>[
                        "total"=>$price,
                        "currency"=>"USD"
                    ],
                    "description"=>$description
                ]
            ]
        ];
        $data = $this->request("/v1/payments/payment/",$f);
        if (
            preg_match(
                '%^https://www\.sandbox\.paypal\.com/'.
                'cgi-bin/webscr\?cmd=_express-checkout&token=(.*?)$%',
                $data->links[1]->href, 
                $regs
            )
        ){
            $this->m->delete($regs[1]);
            $this->m->add($regs[1],$data->id,600);
        }
        return [ $data->links[1]->href, $data ];
    }
    public function checkPayment(){
        $f=["payer_id" => ($_GET['PayerID']) ];
        $req = $this->request("/v1/payments/payment/".$this->m->get($_GET['token'])."/execute/",$f);
        $return_class =  new $this->options['dataClass'];
        $return_class->payment([ 
            "state" => $req->state, 
            "stateSale" => $req->transactions[0]->related_resources[0]->sale->state, 
            "id" => $req->id, 
            "payer" => $req->payer, 
            "txn" => $req->transactions[0]->related_resources[0]->sale->id,
            "raw" => $req
        ]);
    }
    public function IPN(){
        $return_class =  new $this->options['dataClass'];
        $return_class->paymentIPN($_POST);
    }
}
	


Youtube Downloading Script - 2013-03-13

Oh man youtube downloading is a pain, well if you know a bit of PHP then this trouble is a thing of the past.
<?php
function cmp($a, $b)
{
    if ($a['itag'] == $b['itag'])
    {
        return 0;
    }
    return ($a['itag'] > $b['itag']) ? -1 : 1;
}
class YoutubeDownload
{
    private $youtubeInfo = array();
    public $youtubeArrayInfo = array();
    /*
    $url variable is the youtube url,
    then the video ID is parsed out and 
    the video info is retrieved. 
    */
    public function fetch($url)
    {
        if (preg_match('/v=([_0-9a-zA-Z]+)/m', $url, $videoID))
        {
            $this->youtubeInfo = explode("&",file_get_contents("http://www.youtube.com/get_video_info?video_id=".$videoID[1]."&fmt=47"));
            $this->parse();
        }
        else
        {
            $this->error( "Url not a youtube link!" );
            return array(
                "error" => "Not proper youtube video URL",
                "code" => 1
            );
        }
    }
    private function parse()
    {
        foreach( $this->youtubeInfo as $arr )
        {
            $entry = explode("=",$arr);
            $this->youtubeArrayInfo[ ( $entry[0] ) ] = urldecode($entry[1]);
            
        }
        $this->youtubeArrayInfo['streams'] = array();
        $tmpMap = explode(",",$this->youtubeArrayInfo['url_encoded_fmt_stream_map']);
        foreach($tmpMap as $tmps)
        {
            $tmpEntry = array();
            $vMap = explode("&",$tmps);
            foreach($vMap as $vs)
            {
                $entry = explode("=",$vs);
                $tmpEntry[($entry[0])] = urldecode($entry[1]);
            }
            $this->youtubeArrayInfo['streams'][] = $tmpEntry;
        }
        usort($this->youtubeArrayInfo['streams'], "cmp");
    }
    private function getHighestQuality()
    {
        $bestQuality = array();
        foreach( $this->youtubeArrayInfo['streams'] as $stream )
        {
            if ( preg_match( '/hd1080/m', $stream['quality'] ) )
            {
                $bestQuality = $stream;
            }
        }
        if( count( $bestQuality) == 0 )
        {
            foreach( $this->youtubeArrayInfo['streams'] as $stream )
            {
                if ( $stream['itag']>46 && $stream['itag']<48 )
                {
                    $bestQuality = $stream;
                }
            }
        }
        return $bestQuality;
    }
    public function download($saveToFile)
    {
        $stream = $this->getHighestQuality();
        $url = $stream['url']."&signature=".$stream['sig'];
        if ($file = fopen($url, 'rb'))
        {
            $fp = fopen($saveToFile, 'w');
            while(!feof($file) && (connection_status()==0))
            {
                fwrite($fp, fread($file, 1024*8));
            }
            fclose($file);
            fclose($fp);
        }
        
    }
    private function error($error)
    {
        trigger_error($error, E_USER_ERROR);
    }
}
$n = new YoutubeDownload();
$n->fetch("http://www.youtube.com/watch?v=ngxD7IIslg8&list=UUOlqMzbUH_dOtwU_mJn-nsg&index=1");
$n->download("cookies.webm");

Oh Hello There! - 2012-10-21

So here we are, another developers blog.. This blog will contain updates on my personal projects and discovery. This will include code snippets and links + tutorials on how to accomplish specific tasks on the internet without having to go through the annoying bits yourself. I will be providing tools soon that will make setting up linux servers a lot simpler.