вторник, 8 октября 2013 г.

VKScript или развиваем экстрасенсорные способности

Изображение: Аркадий Зарубин, CC-BY-SA
http://commons.wikimedia.org/wiki/File:Шаманский_бубен.JPG

Работа с VK API - дело нелегкое, особенно когда для получения результата требуется произвести несколько обращений к API. К счастью, ВКонтакте предоставляет нам механизм позволяющий писать собственные сценарии вызова API функций и выполнять их на стороне сервера. К несчастью, его возможности очень сильно ограничены, а документация языка сценариев ограничивается двумя абзацами.

Для начала рекомендую заглянуть в официальную документацию по ссылке. Ну а тех, кто заинтересовался прошу под кат.

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

Мой код не претендует на истину в первой инстанции, а лишь демонстрирует проблемы и способы их решения. Если у вас есть более корректные варианты решения описанных проблем - пишите их в комментариях.

1. Конкатенация строк. Казалось бы, что может пойти не так? Оказывается, может. все(?) "поля" которые нам возвращают API вызовы являются массивами, поэтому нужно обращаться к индексу [0]. Иначе мы получим массив из двух элементов...


...
var user_info = API.users.get({user_ids:1});
owner_name = user_info@.first_name[0] + user_info@.last_name[0];
...

2. Добавление элемента в массив выглядит не менее оригинально:


...
var array = [];
array = array + ["new item"];
...

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


...
var photo_items = API.photos.get({album_id: 1, owner_id: 0}).items;
if (parseInt(photo_items[index].photo_2560.length) > 0)
{
    photo_list = photo_list + [photo_items[index].photo_2560];
}
...
else if (parseInt(photo_items[index].photo_75.length) > 0)
{
    photo_list = photo_list + [photo_items[index].photo_75];
}
...

Ну и напоследок полный код функции:


var owner_id = ?;
var album_id = ?;
var is_group = 0;
var owner_name;
if (owner_id < 0)
{
    is_group = 1;
    owner_name = API.groups.getById({group_id: -owner_id})@.name[0];
}
else
{
    var user_info = API.users.get({user_ids:owner_id});
    owner_name = user_info@.first_name[0] + " " + user_info@.last_name[0];
}
var album = API.photos.getAlbums({owner_id: owner_id, album_ids: album_id});
var album_name = album.items@.title[0];
var created_time = album.items@.created[0];
var updated_time = album.items@.updated[0];
var photo_list = [];
var photo_items = API.photos.get({album_id: album_id, owner_id: owner_id}).items;
var index = 0;
while (index < photo_items.length)
{
    if (parseInt(photo_items[index].photo_2560.length) > 0)
    {
        photo_list = photo_list + [photo_items[index].photo_2560];
    }
    else if (parseInt(photo_items[index].photo_1280.length) > 0)
    {
        photo_list = photo_list + [photo_items[index].photo_1280];
    }
    else if (parseInt(photo_items[index].photo_807.length) > 0)
    {
        photo_list = photo_list + [photo_items[index].photo_807];
    }
    else if (parseInt(photo_items[index].photo_604.length) > 0)
    {
        photo_list = photo_list + [photo_items[index].photo_604];
    }
    else if (parseInt(photo_items[index].photo_130.length) > 0)
    {
        photo_list = photo_list + [photo_items[index].photo_130];
    }
    else if (parseInt(photo_items[index].photo_75.length) > 0)
    {
        photo_list = photo_list + [photo_items[index].photo_75];
    }
    index = index + 1;
}

return {is_group: is_group, owner_name: owner_name, album_name: album_name,
        created_time: created_time, updated_time: updated_time, photo_list: photo_list};

Выполнить данный код с помощью средств Qt можно следующим образом:


    ...
    QString code = QString(
        "var owner_id = %1;"
        "var album_id = %2;"
        "var is_group = 0;"
        "var owner_name;"
        "if (owner_id < 0)"
        "{"
        "    is_group = 1;"
        "    owner_name = API.groups.getById({group_id: -owner_id})@.name[0];"
        "}"
        "else"
        "{"
        "    var user_info = API.users.get({user_ids:owner_id});"
        "    owner_name = user_info@.first_name[0] + \" \" + user_info@.last_name[0];"
        "}"
        "var album = API.photos.getAlbums({owner_id: owner_id, album_ids: album_id});"
        "var album_name = album.items@.title[0];"
        "var created_time = album.items@.created[0];"
        "var updated_time = album.items@.updated[0];"
        "var photo_list = [];"
        "var photo_items = API.photos.get({album_id: album_id, owner_id: owner_id}).items;"
        "var index = 0;"
        "while (index < photo_items.length)"
        "{"
        "    if (parseInt(photo_items[index].photo_2560.length) > 0)"
        "    {"
        "        photo_list = photo_list + [photo_items[index].photo_2560];"
        "    }"
        "    else if (parseInt(photo_items[index].photo_1280.length) > 0)"
        "    {"
        "        photo_list = photo_list + [photo_items[index].photo_1280];"
        "    }"
        "    else if (parseInt(photo_items[index].photo_807.length) > 0)"
        "    {"
        "        photo_list = photo_list + [photo_items[index].photo_807];"
        "    }"
        "    else if (parseInt(photo_items[index].photo_604.length) > 0)"
        "    {"
        "        photo_list = photo_list + [photo_items[index].photo_604];"
        "    }"
        "    else if (parseInt(photo_items[index].photo_130.length) > 0)"
        "    {"
        "        photo_list = photo_list + [photo_items[index].photo_130];"
        "    }"
        "    else if (parseInt(photo_items[index].photo_75.length) > 0)"
        "    {"
        "        photo_list = photo_list + [photo_items[index].photo_75];"
        "    }"
        "    index = index + 1;"
        "}"
        ""
        "return {is_group: is_group, owner_name: owner_name, album_name: album_name,"
        "        created_time: created_time, updated_time: updated_time, photo_list: photo_list};"
    ).arg(ownerId).arg(albumId);

    QUrl apiUrl = QUrl(QString("https://api.vk.com/method/execute");

    // Данная строчка нужна для того, чтобы корректно экранировать специальные символы
    apiUrl.addEncodedQueryItem(QUrl::toPercentEncoding(code), "code");

    apiUrl.addQueryItem("v", m_protocolVersion);
    apiUrl.addQueryItem("access_token", m_accessToken);

    QNetworkRequest request;
    request.setUrl(apiUrl);
    request.setRawHeader("User-Agent", "VkAgent/1.0");
    ...

}

Комментариев нет:

Отправить комментарий