ћы в Telegram - чате. “ы с нами? :)

Ќа дн€х нам в голову пришла мысль: что получитс€, если интегрировать Asterisk и Instagram? —ценарий такой: приходит вход€щий звонок, Asterisk лезет в PHP скрипт через AGI с номером звон€щего, параллельно, скрипт рисует картинку по заранее подготовленному шаблону, на которую накладывает номер звон€щего и дату звонка, а потом через API отправл€ет публикацию в инстаграм?

≈динственный вопрос, который у нас возник (и наверн€ка у вас) Ц зачем? Ёту идею мы отложили в долгий €щик. Ќо один из наших инженеров не сдалс€, и довел до ума эту идею :) ѕредлагаем вам ознакомитьс€ с тем, как это работает Ђjust for funї и дл€ общего саморазвити€.

ƒанна€ стать€ несет в себе развлекательно Ц ознакомительный характер, и не несет полезности дл€ промышленной эксплуатации IP Ц ј“— Asterisk. » мы это хорошо понимаем :)

—оздание AGI Ц скрипта на PHP

¬с€ наша конструкцию будет состо€ть из 3 файлов:

  1. instagram.php - файл, в котором мы будем цепл€ть из AGI CallerID, обращатьс€ к скрипту, который сгенерирует картинку и отправл€ть данные в Instagram;
  2. generate_pic.php - php Ц скрипт, который сгенерирует дл€ нас картинку, с наложенным поверх номером звон€щего и датой звонка;
  3. pic.jpg - картинка Ц шаблон, на которую мы будем накладывать текст с номером и датой звон€щего;

 стати, картинка pic.jpg будет выгл€деть вот так:

 артинка дл€ интеграции Asterisk и Instagram
¬ажно!  артинка должна быть квадратной! ¬ нашем случае, это размер 600x600.

»так, а теперь сам скрипт. ¬ажные строчки кода будут растолкованы с помощью комментариев после двойного обратного слеша \:

#!/usr/bin/php -q
<?php
error_reporting(0);
require('phpagi.php'); 
$agi = new AGI(); 
$cid = $agi->request['agi_callerid']; \парсим из AGI номер звон€щего и записываем в переменную $cid;
copy(dirname( __FILE__ )."/pic.jpg", dirname( __FILE__ )."/picc.jpg"); \копируем нашу картинку шаблон в такую же, но с именем picc.jpg. ѕосле публикации она будет удалена;
$input = "http://192.168.1.2/insta/generate_pic.php?num=$cid&pic=../../home/admin/instagram/pic.jpg"; \обращаемс€ к скрипту generate_pic.php, передава€ в нем в переменной num номер звон€щего, а в переменной pic = картинку, поверх которой, будем накладывать свой текст. —крипт вернет нам картинку с наложенным текстом. ќбратите внимание на путь /home/admin/instagram/pic.jpg Ц сюда мы загрузим картинку - шаблон;
$output = dirname( __FILE__ )."/picc.jpg";
file_put_contents($output, file_get_contents($input)); \ кладем нарисованное содержимое в файл picc.jpg, который ранее создали;
$image = dirname( __FILE__ )."/picc.jpg"; 
$date = date("Y-m-d H:i:s"); \ генерируем дату звонка - т.к AGI обращаетс€ к скрипту в момент звонка, она будет точной;
$text = "¬ход€щий звонок от $date с номера $cid"; \ генерируем подпись к публикации в Instagram;
function SendRequest($url, $post, $post_data, $user_agent, $cookies) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, 'https://instagram.com/api/v1/'.$url);
    curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
 
    if($post) {
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    }
 
    if($cookies) {
        curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt');
    } else {
        curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookies.txt');
    }
 
    $response = curl_exec($ch);
    $http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
 
    return array($http, $response);
}
 
function GenerateGuid() {
    return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
        mt_rand(0, 65535),
        mt_rand(0, 65535),
        mt_rand(0, 65535),
        mt_rand(16384, 20479),
        mt_rand(32768, 49151),
        mt_rand(0, 65535),
        mt_rand(0, 65535),
        mt_rand(0, 65535));
}
 
function GenerateUserAgent() {
    $resolutions = array('720x1280', '320x480', '480x800', '1024x768', '1280x720', '768x1024', '480x320');
    $versions = array('GT-N7000', 'SM-N9000', 'GT-I9220', 'GT-I9100');
    $dpis = array('120', '160', '320', '240');
 
    $ver = $versions[array_rand($versions)];
    $dpi = $dpis[array_rand($dpis)];
    $res = $resolutions[array_rand($resolutions)];
 
    return 'Instagram 4.'.mt_rand(1,2).'.'.mt_rand(0,2).' Android ('.mt_rand(10,11).'/'.mt_rand(1,3).'.'.mt_rand(3,5).'.'.mt_rand(0,5).'; '.$dpi.'; '.$res.'; samsung; '.$ver.'; '.$ver.'; smdkc210; en_US)';
}
 
function GenerateSignature($data) {
    return hash_hmac('sha256', $data, 'b4a23f5e39b5929e0666ac5de94c89d1618a2916');
}
 
function GetPostData($filename) {
    if(!$filename) {
        echo "The image doesn't exist ".$filename;
    } else {
        $post_data = array('device_timestamp' => time(),
            'photo' => '@'.$filename);
        return $post_data;
    }
}
 
 
function sendInstagramm($filename, $caption) // пишем функцию, при вызове которой (с двум€ входными параметрами, файлом и текстом) мы будем совершать публикацию;
{
    $username = 'ваш_логин_в_инстаграм'; // укажите здесь логин от нужной учетной записи в Instagram;
    $password = 'ваш_пароль_в_инстаграм'; // укажите здесь пароль от нужной учетной записи в Instagram;
 
    $agent = GenerateUserAgent();
    $guid = GenerateGuid();
    $device_id = "android-" . $guid;
    $data = '{"device_id":"' . $device_id . '","guid":"' . $guid . '","username":"' . $username . '","password":"' . $password . '","Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"}';
    $sig = GenerateSignature($data);
    $data = 'signed_body=' . $sig . '.' . urlencode($data) . '&ig_sig_key_version=4';
    $login = SendRequest('accounts/login/', true, $data, $agent, false);
    $text = '';
 
    if (strpos($login[1], "Sorry, an error occurred while processing this request.")) {
        $text .= "Request failed, there's a chance that this proxy/ip is blocked";
        return $text;
    }
 
    if (empty($login[1])) {
        $text .= "Empty response received from the server while trying to login";
        return $text;
    }
    $obj = @json_decode($login[1], true);
 
    if (empty($obj)) {
        $text .= "Could not decode the response" ;
        return $text;
    }
    $data = GetPostData($filename);
    $post = SendRequest('media/upload/', true, $data, $agent, true);
 
    if (empty($post[1])) {
        $text .= "Empty response received from the server while trying to post the image";
        return $text;
    }
    $obj = @json_decode($post[1], true);
 
    if (empty($obj)) {
        $text .= "Could not decode the response";
        return $text;
    }
    $status = $obj['status'];
 
    if ($status != 'ok') {
        $text .= "Status isn't okay";
        return $text;
    }
 
    $media_id = $obj['media_id'];
    $device_id = "android-" . $guid;
 
    $data = (object)array(
        'device_id' => $device_id,
        'guid' => $guid,
        'media_id' => $media_id,
        'caption' => trim($caption),
        'device_timestamp' => time(),
        'source_type' => '5',
        'filter_type' => '0',
        'extra' => '{}',
        'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8',
    );
    $data = json_encode($data);
    $sig = GenerateSignature($data);
    $new_data = 'signed_body=' . $sig . '.' . urlencode($data) . '&ig_sig_key_version=4';
 
    $conf = SendRequest('media/configure/', true, $new_data, $agent, true);
	print_r ($conf);
 
    if (empty($conf[1])) {
        $text .= "Empty response received from the server while trying to configure the image";
    } else {
        if (strpos($conf[1], "login_required")) {
            $text .= "You are not logged in. There's a chance that the account is banned";
        } else {
            $obj = @json_decode($conf[1], true);
            $status = $obj['status'];
            if ($status != 'fail') {
                $text .= "Success";
            } else {
                $text .= 'Fail';
            }
        }
    }
    return $text;
}
sendInstagramm($image, $text); \ вызываем функцию постинга;
unlink(dirname( __FILE__ )."/picc.jpg"); \ удал€ем созданный в рамках скрипта файл picc.jpg - более он нам не нужен :);
?>
—качать скрипт AGI
¬ случае скачивани€, помен€йте расширение файла с .txt на .php

¬еликолепно. —охран€ем этот скрипт как Instagram.php и закидываем его в папку /var/lib/asterisk/agi-bin. «акинуть его можно с помощью WinSCP, например. ƒалее, в консоли через SSH доступ на сервер Asterisk дайте следующие команды:

dos2unix /var/lib/asterisk/agi-bin/instagram.php
chown asterisk:asterisk /var/lib/asterisk/agi-bin/instagram.php
chmod 775 /var/lib/asterisk/agi-bin/instagram.php

“еперь закидываем на сервер картинку Ц шаблон по пути /home/admin/instagram/pic.jpg, то есть так, как мы указали в скрипте и по аналогии даем права на этот файл. ѕриступаем к настройке скрипта генерации нужной нам Ђпикчиї.


√енерации картинки на PHP

Ќастало врем€ генерации картинки. –еализаци€ будет на PHP. —оздаем файл generate_pic.php и добавл€ем в него следующее содержимое (комментарии в коде):

<?php 
function writeTextOnImage($filename, $text)  \ функци€, при вызове которой, на вход мы даем 2 параметра: изображение, на которое нужно наложить текст и сам текст;
{   
    $size_img = getimagesize($filename);  
    if ($size_img[2]==2)       $src_img = imagecreatefromjpeg($filename);  
    else if ($size_img[2]==1)  $src_img = imagecreatefromgif($filename);  
    else if ($size_img[2]==3)  $src_img = imagecreatefrompng($filename);    
    $color = imagecolorallocatealpha($src_img, 0, 0, 0, 0);  
    $font_file = "2211.ttf";  //файл расширени€ .ttf  с нужным нам шрифтом;
    $img_x = imagesx($src_img); 
    $img_y = imagesy($src_img);     
    $height_font = 28;
    $angle = 0;
    $box = imagettftext($src_img, $height_font, $angle, $img_x - 500, $img_y - 350, $color, $font_file, $text);  \ здесь вы можете регулировать по оси X и Y позицию текста на картинке (смещение $img_x - 500, $img_y - 350);
    if ($size_img[2]==2)  
    {  
        header ("Content-type: image/jpeg");  
        imagejpeg($src_img);  
    }  
    else if ($size_img[2]==1)  
    {  
        header ("Content-type: image/gif");  
        imagegif($src_img);  
    }  
    else if ($size_img[2]==3)  
    {  
        header ("Content-type: image/png");  
        imagepng($src_img);  
    }  
    return true;  
} 
$pic = $_GET['pic']; \ получаем путь к картинке;
$num = $_GET['num']; \ получаем номер звон€щего
$img = "../../$pic"; \ относительный путь до картинки, на которую мы наложим текст;
$date = date("Y-m-d H:i:s"); \ генерируем дату;
writeTextOnImage($img, "«вонок от: $num\n  ƒата и врем€ звонка:\n  $date\n\n\n\n      wiki.merionet.ru");  \ вызываем функцию;
?>
—качать скрипт генерации

“еперь, создайте у себ€ на сервере Asterisk директорию /var/www/html/insta. ¬ нее вам необходимо загрузить созданный файл generate_pic.php и файл шрифта 2211.ttf, а затем дать необходимые Ђпермишныї:

¬ы можете назвать используемы файлы по своему усмотрению. ¬ажно не забыть сменить их имена в самих скриптах.
dos2unix /var/www/html/insta/generate_pic.php
chown asterisk:asterisk /var/www/html/insta/generate_pic.php
chown asterisk:asterisk /var/www/html/insta/2211.ttf
chmod 775 /var/www/html/insta/generate_pic.php
chmod 775 /var/www/html/insta/2211.ttf

¬ызов скрипта из диалплана

ќсталось самое простое Ц вызвать скрипт instagram.php из диалплана Asterisk. ƒл€ этого, нужно вставить следующую строчку:

exten => _.,n,AGI(instagram.php)

ƒа, на этом все. ѕриступаем к тестированию. Ќаш скрипт расположилс€ на вход€щем транке в тестовом контуре. ƒелаем звонок с мобильного телефона и смотрим в Instagram:

Asterisk постинг картинки в Instagram

–ассмотрим поближе, нажав на публикацию. Ќас интересует подпись:

Asterisk информаци€ о вход€щих звонках Instagram

ѕолезна ли ¬ам эта стать€?

–аз в неделю мы отправл€ем дайджест с самыми интересными стать€ми.

P.S. ≈сли укажите свою дату рождени€, то мы об€зательно ¬ас поздравим и подарим небольшой подарок :)

Ќажима€ на кнопку "ѕодписатьс€", вы даете согласие на обработку своих персональных данных