Все записи автора admin

PhantomJS на Windows

Для начала, почему не curl.  С ним все клево — поддержка cookie, proxy, post, get запросы, вот это все. Но никакого вам js, да  и популярные сервисы с каждым днем придумывают все новые ухищрения в пользу реальных посетителей.

Поэтому, будем эмулировать реального посетителя с помощью PhantomJS. Что это такое? Это полноценный браузер без графической оболочки. Кроме исполнения js, он умеет также делать скриншоты.

Ставим под Windows. Качаем с http://phantomjs.org/download.html, кладем в некоторую директорию, добавляем эту директорию (до exe-шника) в PATH (на win8: Панель управления\Система и безопасность\Система->  Изменить параметры, вкладка «Переменные среды»,  далее ищите PATH).

Сохраняем, открываем cmd.exe, пользуемся с помощью phantomjs.

 

В следующем посту попробуем залониться с помощью phantomjs. например, в instagram 😉

 

 

Как создать новую точку геолокации в Instagram

Казалось бы! А все не так просто, с лета 2015 года instagram убрал возможность добавлять новые геолокации через само приложение.
Но вот вам лайфхак: сделать это легко и быстро через приложение Facebook

  1. устанавливаем Facebook
  2. жмем в статусе кнопку «где я»
  3. добавляем новое место (описываем категорию, адрес, название)
  4. вуа-ля, идем в инстаграм и радуемся лайкам жизни

1 место на фотоконкурсе «Моя Казань 2015»

Не то, чтобы я тщеславна, но надо увековечить где-то память об этом мероприятии и о моей в нем победе.

Преамбула: всю весну и начало лета в Казани проходил фотоконкурс «Моя Казань» при поддержке ПроГород и Центра семьи «Казан». Принять участие мог любой желающий и в завершении конкурса жюри насчитывало более 25 тысяч работ! Бедное жюри! Этот титанический труд по выбору лучших работ проходил в несколько этапов. Завершающий этап  и награждение победителей проходили на площадке Чаши.

даю интервью в местное TV

Мои работы попали на конкурс волею случая и без моего ведома, но узнав о конкурсе, я как-то втянулась, и, внезапно для себя (соревнуясь с отличными фотографами, мастерами своего дела) взяла 1 место и главный приз!

Мое интервью для Ати-Таймс
http://ati-times.tatar-inform.ru/news/society/29385031/

Мои работы:

Мужчина, вы что, не видите, у нас подтверждение подписки?

Это не пост, это крик души.

Спасибо Почте России, инновациям, модернизации и нанотехнологиям, некоторое время назад на сайте ПР появилась e-mail-подписка на уведомления о смене статуса вашего почтового отправления.

Подписку, как полагается по всем законам этики, после ввода email-адреса, нужно подтвердить, перейдя по ссылке, которая на эту самую почту приходит. Догадываюсь, для того, чтобы злоумышленники [грозный смайлик] не смогли на вашу почту подписать другие трек-коды.

Строка подтверждения, та самая, которая приходит на почту: http://www.russianpost.ru/tracking20/ConfirmSubscription.aspx?barcode=RO017399613CN&email=email

Мужчина, вы что, не видите? Ни кода подтверждения, ни других идентифицирующих признаков. Для далеких от темы: подтвердить подписку на вашу почту я могу без всяких усилий и без вашей почты. Сама на вашу почту подписалась, сама без доступа к почте подтвердила.

Twitter REST API, app only auth

На данный момент Twitter предоставляет разработчикам API двух видов: классический (пока еще) REST и Streaming API. Не смотря на то, что платформа всяческими ограничениями переталкивает разработчиков на сторону зла Streaming API, речь в этой статье пойдет именно о REST.

Версии API у соцсервисов постоянно обновляются, все что написано ниже справедливо для TWITTER REST API v 1.1

Чтобы выполнять запросы к апишечке, нам необходим будет https, twitter application и, куда без него, OAuth Request Token.

Для начала регистрируем приложение, выбираем необходимый будущему приложению уровень доступа (чтение / чтение+публикация твитов / чтение+публикация+директ мессаджи). Далее все как всегда, получаем API Key, API Secret и гоу в ИДЕшечку, писать что-нибудь (конечно на пхп, а вы на чем хотели?)

Ах да, в твиттере есть обычная(с авторизацией пользователя) и app-only аутентификация (хотя, какая тут обычная, каждый выбирает сам). App only auth не позволяет делать разве что публикацию твиттов и DM (не от имени приложения же твиты слать, не так ли?), все остальное он умеет, если конечно показать  ему ваш токен.

Пример элементарнейшего приложения, которое генерирует токен с помощью app-only auth и получает новые статусы (твиты) из списка (list) пользователя, можно посмотреть ниже. Все, что реализует приложение, справедливо и для всех остальных методов  API. Похоже, это совсем несложно.

class TwitterWrapper{

private $consumerKey = 'YOUR API KEY';
private $consumerSecret ='YOUR API SECRET';
private $userID = (int) YOUR USER ID;
private $listID = (int) LIST ID;

private function getToken(){

// Step 1 - получение ключа подписи из consumerKey & consumerSecret
$token = sprintf("%s:%s", $this->consumerKey, $this->consumerSecret);
$base64Token = base64_encode($token);

// Step 2 - формируем запрос для получения токена
$url = "https://api.twitter.com/oauth2/token";
$headers = array(
"POST /oauth2/token HTTP/1.1",
"Host: api.twitter.com",
"User-Agent: Twitter Application-only OAuth App v.1",
"Authorization: Basic ".$base64Token,
"Content-Type: application/x-www-form-urlencoded;charset=UTF-8"
);

//формируем curl - запрос

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // возвращать ответ будем, а вдруг пригодится - для извлечения токена, например
curl_setopt($ch, CURLOPT_POSTFIELDS, "grant_type=client_credentials");

curl_setopt($ch, CURLOPT_HEADER, 1);
curl_getinfo($ch, CURLINFO_HTTP_CODE);

$retrievedHtml = curl_exec ($ch);
curl_close($ch);

$output = explode("\n", $retrievedHtml);
$token = '';
foreach($output as $line)
{
if($line != false)
{
$token = $line;
}
}
$token = json_decode($token);
return $token->{'access_token'};

}

function getListStatuses(){

$url = "https://api.twitter.com/1.1/lists/statuses.json"; // base url
$q = sprintf("?list_id=%s&user_id=%s&include_entities=%s&include_rts=true", $this->listID, $this->userID, "false");

$headers = array(
"GET /1.1/lists/statuses.json".$q." HTTP/1.1",
"Host: api.twitter.com",
"User-Agent: Twitter Application-only OAuth App v.1",
"Authorization: Bearer ".$this->getToken()
);
$ch = curl_init(); // setup a curl
curl_setopt($ch, CURLOPT_URL,$url.$q); // set url to send to
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); // set custom headers
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // return output
$retrievedHtml = curl_exec ($ch); // execute the curl
curl_close($ch); // close the curl
return $retrievedHtml;
}

}

$twitterApp = new TwitterWrapper();
$statuses = json_decode($twitterApp -> getListStatuses());

И на десерт про 15 minutes windows и лимиты на количество запросов: версия 1.1 лимитирует количество запросов, лимиты распространяются на 15-минутные интервалы и зависят от способа аутентификации (у app-only auth количество запросов по некоторым пунктам меньше). Подробнее

Instagram API, интеграция приложений с Instagram

Instagram предоставляет разработчикам богатый API, который позволяет получить доступ к любой сгенерированной пользователями информации. К сожалению, API умеет только читать, нет никакого способа загружать снимки в обход официального Android или IOS приложения. Но несмотря на read-only статус API, вы можете сделать действительно полезные и интересные приложения с помощью него. Например, вы можете получить список публикаций, привязанных к определенному географическому положению, список популярных снимков или информацию и фотоленту того или иного пользователя.

Instagram API работает по модели REST и использует OAuth 2.0 protocol, а это значит, что к нему можно обращаться с помощью любого языка, понимающего JSON. Обращение к API может происходить только используя SSL.

На момент написания статьи Instagram предоставлял библиотеки для взаимодействия API на Ruby и Python.

Некоторые функции доступны без регистрации приложения. Например, получение информации о снимке и авторе в JSON, имея ссылку на него и др.

Начало работы. Создание приложения
Чтобы обращаться к API, для начала следует создать приложение на странице разработчиков, указать название и web-адрес приложения и получить CLIENT ID.

Большинство запросов требует только указания CLIENT ID. Client_id просто связывает свой сервер, скрипт или программу с конкретным приложением. Тем не менее, некоторые запросы требуют проверки подлинности — авторизацию пользователя в вашем приложении и последующее получение access_token для совершения запроса.

 Endpoints

Endpoints это сущности, информацию о которых можно получить с помощью API. На данный момент это:

  • users — Информация о пользователе, лента пользователя
  • relationships — Отношения между пользователями
  • media -Получение ленты по id пользователя, по поисковому запросу, по геотегу
  • comments — Получение/отправка/удаление комментариев
  • Likes -Получение, отправка, удаление лайков
  • Tags — Поиск по тегам
  • Location — Поиск изображений по геолокации (указываются координаты местоположения и радиус поиска)
  • Geography — Поиск изображений по id местоположения

ПРИМЕР. Получение популярных изображений в Instagram при помощи API

<html>
  <head></head>
  <body>  
    <h1>Popular on Instagram</h1>  
    <?php
    // загрузка классов Zend
    require_once 'Zend/Loader.php';
    Zend_Loader::loadClass('Zend_Http_Client');

    // определение ключа и секретного ключа пользователя
    // доступно с консоли API Instagram
    $CLIENT_ID = 'YOUR-CLIENT-ID';
    $CLIENT_SECRET = 'YOUR-CLIENT-SECRET';

    try {
      // инициализация клиента
      $client = new Zend_Http_Client('https://api.instagram.com/v1/media/popular');
      $client->setParameterGet('client_id', $CLIENT_ID);

      // получение списка популярных изображений
      // передача запроса и декодирование ответа
      $response = $client->request();
      $result = json_decode($response->getBody());

      // отображение фотографий
      $data = $result->data;  
      if (count($data) > 0) {
        echo '<ul>';
        foreach ($data as $item) {
          echo '<li style="display: inline-block; padding: 25px"><a href="' . 
            $item->link . '"><img src="' . $item->images->thumbnail->url . 
            '" /></a> <br/>';
          echo 'By: <em>' . $item->user->username . '</em> <br/>';
          echo 'Date: ' . date ('d M Y h:i:s', $item->created_time) . '<br/>';
          echo $item->comments->count . ' comment(s). ' . $item->likes->count . 
            ' likes. </li>';
        }
        echo '</ul>';
      }

    } catch (Exception $e) {
      echo 'ERROR: ' . $e->getMessage() . print_r($client);
      exit;
    }
    ?>
  </body>
</html>

ПРИМЕР. Получение изображений по тегам

html>
  <head></head>
  <body>
    <h1>Instagram Tag Search</h1>
    <?php
    if (!isset($_POST['submit'])) {
    ?>
    <form method="post" 
      action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
      Search for:
      <input type="text" name="q" /> 
      <input type="submit" name="submit" value="Search" />      
    </form>
    <?php
    } else {
    ?>
    <h2>Search results for '<?php echo $_POST['q']; ?>'</h2>
    <?php
      require_once 'Zend/Loader.php';
      Zend_Loader::loadClass('Zend_Http_Client');

      // определение ключа и секретного ключа пользователя
      // доступно с консоли API Instagram
      $CLIENT_ID = 'YOUR-CLIENT-ID';
      $CLIENT_SECRET = 'YOUR-CLIENT-SECRET';

      try {
        // инициализация клиента
        $client = new Zend_Http_Client('https://api.instagram.com/v1/tags/search');
        $client->setParameterGet('client_id', $CLIENT_ID);
        $client->setParameterGet('q', $_POST['q']);

        // получение и отображение аналогичных меток
        $response = $client->request();
        $result = json_decode($response->getBody());
        $data = $result->data;  
        if (count($data) > 0) {
          echo '<ul>';
          foreach ($data as $item) {
            echo '<li>' . $item->name . ' (' . $item->media_count . 
              ') </li>';
          }
          echo '</ul>';
        }
      } catch (Exception $e) {
        echo 'ERROR: ' . $e->getMessage() . print_r($client);
        exit;
      }
    }  
    ?>
  </body>
</html>

ПРИМЕР. Поиск изображений по местоположению

<html>
  <head></head>
  <body>
    <h1>Instagram Photo Search by Location</h1>
    <?php
    if (!isset($_POST['submit'])) {
    ?>
    <form method="post" 
      action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
      Latitude: <input type="text" name="lat" />  
      Longitude: <input type="text" name="long" /> 
      <input type="submit" name="submit" value="Search!" />      
    </form>
    <?php
    } else {
    ?>
    <h1>Search results for 'lat:<?php echo $_POST['lat']; ?>, 
      long:<?php echo $_POST['long']; ?>'</h1>
    <?php
      require_once 'Zend/Loader.php';
      Zend_Loader::loadClass('Zend_Http_Client');

      // определение ключа и секретного ключа пользователя
      // доступно с консоли API Instagram
      $CLIENT_ID = 'YOUR-CLIENT-ID';
      $CLIENT_SECRET = 'YOUR-CLIENT-SECRET';

      try {
        // инициализация клиента
        $client = new Zend_Http_Client('https://api.instagram.com/v1/media/search');
        $client->setParameterGet('client_id', $CLIENT_ID);
        $client->setParameterGet('lat', $_POST['lat']);
        $client->setParameterGet('lng', $_POST['long']);

        // получение изображений, соответствующих указанному местоположению
        $response = $client->request();
        $result = json_decode($response->getBody());

        // отображение фотографий
        $data = $result->data;  
        if (count($data) > 0) {
          echo '<ul>';
          foreach ($data as $item) {
            echo '<li style="display: inline-block; padding: 25px"><a href="' . 
              $item->link . '"><img src="' . $item->images->thumbnail->url . 
              '" /></a> <br/>';
            echo 'By: <em>' . $item->user->username . '</em> <br/>';
            echo 'Date: ' . date ('d M Y h:i:s', $item->created_time) . '<br/>';
            echo $item->comments->count . ' comment(s). ' . $item->likes->count . 
              ' likes. </li>';
          }
          echo '</ul>';
        }

      } catch (Exception $e) {
        echo 'ERROR: ' . $e->getMessage() . print_r($client);
        exit;
      }
    }  
    ?>
  </body>
</html>

smartwatch UWatch U10

Покупка мною этих часов началась с выбора обычного браслета — фитнес-трекера, а-ля Jawbone, обладающего умным будильником. Но, благодаря интернетам, отзывам, обзорам и специализированным форумам, так вышло, идея приобретения браслета сэволюционировала до смарт-часов. Моим выбором стали UWatch U10, моделька новая, вышла перед новым годом, поэтому я одна из первых ее обладательниц на Российском рынке.

Повторюсь, изначально я хотела фитнес-трекер, но проспойлерю: за 2 дня пользования часиками ни разу не пожалела, что остановила свой выбор именно на часах, а не браслете: часы не уступают фитнес-трекеру по функционалу, есть функция умного будильника, вибромотор за счет большего корпуса мощнее, чем на браслете, и поэтому действительно будит, кроме того часики синхронизируются с телефоном и это дико удобно: все нотификации дублируются с телефона на часы и вам не придется каждый раз доставать свою лопату из кармана, чтобы проверить, есть ли у вас новые лайки. Кроме того, если в настройках синхронизации вы указали часы как гарнитуру, это позволит принимать звонки напрямую с девайса (в них есть и динамик и микрофон). Но есть один нюанс: ваш разговор услышит все ближайшее окружение, ибо динамик на часах довольно мощный.

Примерно так они выглядят:
IMG_20150111_144356

Характеристики часов:

Версия Bluetooth: Bluetooth V3.0+EDR
Протокол Bluetooth: A2DP + HFP 1.5 + HS P 1.2
Диапазон частоты: спектр на 2.4 ГГц
Диапазон передачи: 15 м
Языковая поддержка: мультиязычный (русский язык вполне корректный)
Время полной зарядки: приблизительно 2 часа
Время работы в режиме ожидания: приблизительно 180 часов
Питание: встроенный аккумулятор на 250 мАч
Размеры: 25 см х 4 см х 0,9 см
Длина кожаного браслета: 19 см
Вес: 80 грамм
Дисплей: 1,54”, 240×240
Цвета: черный, белый, серебристый.
Встроенный вибромотор

Производитель утверждает, что они водонепроницаемые, но соответствующего рейтина IP у них нет, да и резиночка, закрывающая microUSB-вход, совсем плюшевая. Руки мою без проблем, но в бассейне сниму.

Ну да ладно, меньше слов, больше фоток:

Часики обошлись деду морозу в $42 и пришли мне за 2,5 недели из Нидерландов вот в такой коробочке:

IMG_20150109_111821

В коробочке кроме часиков была инструкция, USB — microUSB шнур и железка с возложенной на нее ролью отвертки, видимо.

IMG_20150109_111936

Ремешок на часиках кожаный. На руке сидят комфортно, не мешают, не отвлекают даже ночью.

 

Производитель с часами предоставляет Android-приложение, на которое приходят данные о вашей физической активности в режиме бодрствования и сна. Кроме того, оно позволяет управлять списком приложений, push-нотификации которых нужно дублировать на часы.

Так, кстати, выглядят нотификации:

Часы умеют просматривать телефонную книгу, смс и уведомления телефона. Есть функция «Find phone», при включении которой телефон отчаянно зовет вас приятным женским голосом «I`m here!».  Также есть возможность управлять с часов телефонной камерой. Часы дистанционно включают камеру на телефоне, транслируют на экран картинку и позволяют делать снимки.

ЗЫ: 2 дня — полет нормальный. Ежели не осветила интересующие вопросы, велком в комментарии!

 

Информер Яндекс.Пробок и мой секрет успеха общения с Яндексом

Случилась необходимость поставить на рабочем проекте (информационное агентство в г. Казань) информер Яндекс.Пробок. Но вот незадача, все стандартные информеры Яндекс предоставляет лишь для 4 городов: Москва, Спб, Киев, Екб. Что поделать, пришлось писать в саппорт с предложением сделать информер еще для одного города (кстати сказать, не абы какого, а столицы Универсиады 2013 :) ). 3 месяца назад ответил мне саппорт отказом стандартной отпиской, что пожелание получено и отложено в дальний ящик.

svetofor

Пару дней назад попытала счастье еще раз, теперь уже отправив письмо сразу на 3 ящика: яндекс саппорт, pr служба и служба работы с СМИ. И что бы вы подумали, саппорт снова ответил отказом, зато руководитель отдела… международных проектов прислал xml — файл с полной инфой пробок и погоды для текущего города и (!) исходники красивых светофоров в качестве бонуса.

 

Морали в этой истории две:

1. Если вам нужен информер яндекс.пробок (или погоды) на сайт, xml файл по примеру вышеуказанного получить несложно.

2. Неожиданно приятно (хотя и банально), что у людей есть мотивация развивать свой проект, они небезразличны и  готовы идти навстречу.

Начинаем программировать под Android. Установка Eclipse и Android SDK под Windows

Подозреваю, что сабж входит в категорию одного из популярных в российских интернетах, тем не менее, позволю себе еще один баян, хотя бы потому, что хочется уже, знаете, серьезно подойти к освещению топика, максимально подробно (как для блондинок), отталкиваясь от самого начала. Как минимум, для себя. Буду рада, если пойдет на пользу еще кому-то. Все описанное ниже справедливо для windows 8, но, полагаю, в других версиях винды действа будут мало отличаться.

Итак, с чего мы начинаем разрабатывать мобильное приложение, конечно же с IDE. Рассматриваем классику — Eclipse.

Чтобы написать свой первый «Hello, World!» с расширением .apk, нам потребуется:

1) Сам Эклипс, конечно же. Eclipse Classic — качаем, ставим (напр. в C:\eclipse)
2) Java Development Kit (JDK) — качаем, ставим все по дефолту

3) Android SDK — качаем, распаковываем в C:\eclipse

Далее немного лирики.

Java Development Kit (сокращенно JDK) — бесплатно распространяемый компанией Oracle комплект разработчика приложений на  Java, включающий в себя компилятор Java(javac), стандартные библиотеки классов Java, примеры, документацию, различные утилиты и исполнительную систему Java (JRE).

В состав JDK не входит интегрированная среда разработки на Java, поэтому мы и поставили Эклипс.

Android SDK — среда разработки приложений для операционной системы Android. Программа позволяет создавать и тестировать Android-приложения, использующие камеру мобильного устройства, акселерометр, компас, данные GPS, доступ по Bluetooth, Wi-Fi, EDGE и 3G. Есть поддержка работы с мультимедийным контентом (аудио, видео, изображения в форматах MPEG4, H.264, MP3, AAC, AMR, JPG, PNG и GIF), базой данных SQLite, интегрированным браузером на движке WebKit, виртуальной машиной Dalvik, GSM телефонией и т.д.  Также пользователи Android SDK имеют возможность тестировать созданные ими приложения при помощи встроенного эмулятора.

4) Установка ADT (Android Development Tools). Ставим его прям через Эклипс. Т.е., запускаем Эклипс, далее Help ->  InstallNew Software

В диалоговом окне жмем Add  и добавляем источник для Android Development Tools: https://dl-ssl.google.com/android/eclipse/

Начинается поиск доступных плагинов, после чего мы их устанавливаем

Смотрим, что нам предлагается установить

Все ок, некст.

Итак, мы установили все необходимое для нашего первого приложения.

Добавляем на свой сайт карту «Яндекс.Пробки»

Т.к. с момента постановки задачи «разместить на сайте карту Яндекс.пробки» до ее выполнения я потеряла массу времени на чтение невозможно запутанной документации Яндекс АПИ (по поводу чего можно писать отдельный, полный ненависти пост), размещу готовый пример вызова яндекс карты со слоем пробок, дабы сэкономить тебе, мой читатель, ценное время.

Итак, сначала нужно получить АПИ-ключ

Затем подключаем в рамках <head></head>следующий код:

<script type="text/javascript" src="http://api-maps.yandex.ru/1.1/index.xml?key=ADlXcVABAAAAKYveRAIA4kE2qEF9Wp3_3asekVpo53LOCn8AAAAAAAAAAADGtjE36FFsWlWgGvjRW62CsefaoQ==&amp;modules=traffic"></script><script type="text/javascript" language="JavaScript">
var map; YMaps.jQuery(function () {
// Создание экземпляра карты и его привязка к созданному контейнеру
map = new YMaps.Map(YMaps.jQuery("#YMapsID")[0]);
// Установка для карты ее центра и масштаба
map.setCenter(new YMaps.GeoPoint(49.122442,55.798758), 12);
map.addControl(new YMaps.Zoom());
map.addControl(new YMaps.TypeControl());
map.addControl(new YMaps.SearchControl());
map.addControl(new YMaps.ToolBar());
// создание элемента управления "Пробки"
var traffic = new YMaps.Traffic.Control();
// добавление элемента управления "Пробки" на карту
map.addControl(traffic);
// включение показа пробок
traffic.show();
});

Не забудьте поменять АПИ ключ на свой и сгенерить координаты карты (здесь следует заметить, что если вы пользуетесь версией АПИ 2.*, предлагаемые яндексом координаты Х и У нужно поменять местами, о чем тоже можно добавить пару злобных строк в тот самый полный ненависти пост).

Далее вставляем контейнер для карты в тело документа

<div id="YMapsID" style="width: 710px; height: 348px;"></div>

Код страницы целиком:

var map;
YMaps.jQuery(function () {
// Создание экземпляра карты и его привязка к созданному контейнеру
map = new YMaps.Map(YMaps.jQuery("#YMapsID")[0]);
// Установка для карты ее центра и масштаба
map.setCenter(new YMaps.GeoPoint(49.122442,55.798758), 12);
map.addControl(new YMaps.Zoom());
map.addControl(new YMaps.TypeControl());
map.addControl(new YMaps.SearchControl());
map.addControl(new YMaps.ToolBar());
// создание элемента управления "Пробки"
var traffic = new YMaps.Traffic.Control();
// добавление элемента управления "Пробки" на карту
map.addControl(traffic);
// включение показа пробок
traffic.show();
});
<div id="YMapsID" style="width: 710px; height: 348px;"></div>