Создаём динамическую обложку ВКонтакте

в 15:33, , рубрики: java, Вконтакте, Вконтакте API, обработка изображений, Программирование

В последнее время всё большую популярность обретают различные интерактивные способы завлечь аудиторию и привлечь к себе больше внимания. Тут и боты для социальных сетей и мессенджеров, и другие решения, придающие «уникальности».
Среди них можно выделить и динамические обложки для сообществ, официально поддерживать которые ВКонтакте начали в марте.
Почему я решил написать эту небольшую статью? Хотя ажиотаж вокруг этой темы и спал, всё равно она остаётся довольно популярной, находятся как «клиенты», готовые платить очень большие деньги, так и желающие научиться это делать самому.
Я работал с одной «студией», которая берет шестизначные суммы за эту работу, при этом кидая своих разработчиков и мелких клиентов.
Так вот, чтобы в этой сфере не было монополии, и все увидели, насколько легко это делается, я и решил написать статью.

Создаём динамическую обложку ВКонтакте - 1
На примере моего пустого сообщества-песочницы

Вступление

Я опишу, как сделать динамическую обложку, отображающую текущее время и последнего подписчика. Любой другой функционал делается не сложнее — чуть больше строк кода и доступ к API других сервисов.

Что нам понадобится? Всего лишь подготовленный фон для обложки и access_token для группы с правами доступа к фотографиям. Привожу пример на Java, но сделать это можно и любым другим способом.

Статья рассчитана на более-менее опытных читателей — расписывать, как отправить GET запрос или авторизоваться в ВК через API я не стану.

Приступаем

Для начала реализуем транслирование новых подписчиков на обложку.
Логика примерно следующая: получаем запрос от Callback API, берём оттуда id пользователя, по нему берём имя и аватар, накладываем на имеющийся фон и загружаем в ВК. Проще некуда.
Поехали.

Обрабатываем запрос от Callback API

Выглядеть этот запрос будет примерно так:

{
  "type": "group_join",
  "object": {
    "user_id": XXXXXXXX,
    "join_type": "join"
  },
  "group_id": XXXXXXXX
}

Парсить JSON, я думаю, все умеют. Отсюда нам нужен только id пользователя, и по нему мы уже получаем имя, фамилию и ссылку на фотографию.

Достаточно сделать такой GET запрос:

https://api.vk.com/method/users.get?user_ids=XXXXXXXX&fields=photo_max_orig&v=5.65

В ответ мы получим:

{
  "response": [
    {
      "id": XXXXXXXX,
      "first_name": "имя",
      "last_name": "фамилия",
      "photo_max_orig": "https://pp.userapi.com//..."
    }
  ]
}

Всё, у нас есть вся необходимая информация, осталось добавить это на обложку и загрузить её.

Обрабатываем изображение

Предположим, что вы заранее нашли изображение для фона и знаете, по каким координатам должно располагаться то, что вы хотите добавить на обложку. Все эти мелкие подробности опустим и перейдём к коду:

// Фоновое изображение и аватар пользователя
BufferedImage background_image = ImageIO.read(new File("/some/folder/bg.png")),
              user_avatar = ImageIO.read(new URL("https://..."));

// Результат - отдельное изображение
BufferedImage result = new BufferedImage(background_image.getWidth(), background_image.getHeight(), BufferedImage.TYPE_INT_ARGB);

// В качестве "холста" берём наше новое изображение
Graphics2D g = (Graphics2D) result.getGraphics();

// Рисуем фон
g.drawImage(background_image, 0, 0, null);

// Рисуем аватар подписчика
g.drawImage(user_avatar, x_avatar, y_avatar, width, height, null);

// Подписываем имя подписчика
g.drawString(user_name, x_name, y_name);

// Записываем результат на диск
ImageIO.write(result, "PNG", new File("some/folder/result.png"));

Хочу заметить, что лучше использовать сразу уменьшенное изображение, иначе, если просто указать ширину и высоту результата, как указано в примере кода выше, то вместо аватара пользователя вы можете увидеть три пикселя.
Я не стал приводить простыни кода, помогающие на Java нормально уменьшать изображение и делать CircleCrop по центру, это легко пишется собственноручно либо спокойно гуглится. Также, настройку шрифтов и прочие мелкие моменты я тоже опустил.

В принципе, всё — мы получили готовую обложку, осталось только загрузить её. Просто, не правда ли?

Загружаем обложку

Всё делается очень просто и подробно описано в документации к API.

Получаем сервер для загрузки обложки, отправив GET-запрос:

https://api.vk.com/method/photos.getOwnerCoverPhotoUploadServer?group_id=XXXXXXXX&crop_x=0&crop_y=0&crop_x2=1590&crop_y2=400&access_token=ACCESS_TOKEN&v=5.64

Где ACCESS_TOKEN — токен с правами доступа к фотографиям группы.

Из ответа берём upload_url:

{
    "response": {
        "upload_url": "https://..."
    }
}

Теперь отправляем на наш upload_url отправляем POST-запрос с полем photo в формате multipart/form-data, точно также, как и с любыми документами. Я уже освещал этот вопрос в другой статье.

В ответ мы получим следующее:

{
  "hash": "...",
  "photo": "..."
}

Всё, осталось сделать один GET-запрос и обложка засияет в сообществе:

https://api.vk.com/method/photos.saveOwnerCoverPhoto?hash=HASH&photo=HASH&access_token=ACCESS_TOKEN&v=5.65

Где HASH и PHOTO получены из предыдущего пункта, а токен всё тот же.

Готово, динамическая обложка заработала.

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

Ранее мы не зря сохраняли результат обработки в отдельный файл. Теперь мы сможем делать «многослойную» обложку, не теряя предыдущую информацию.

Например, вот так можно транслировать текущее время на обложку:

while (true) {
    // Спим минуту
    Thread.sleep(1000*60);

    // Берём текущее время в формате "20:25"
    String current_tine = new SimpleDateFormat("H:m").format(new Date());

    // Рисуем!
    BufferedImage result = ImageIO.read(new File("some/folder/result.png"));
    Graphics2D g = (Graphics2D) result.getGraphics();

    g.drawString(current_tine, x_time, y_time);

    // Можно перезаписать изображение, или сразу его загружать
    // Или делать что душе угодно 
    ImageIO.write(result, "PNG", new File("some/folder/result.png");
}

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

Буду рад, если статья не окажется бесполезной. Всё же, видел немало вопросов на эту тему, и желающих тоже достаточно.
Правда, жаль, что у Facebook нет аналогичной возможности обновлять обложку.

Автор: Пётр Самохин

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js