Pull to refresh

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

Reading time 5 min
Views 115K
В последнее время всё большую популярность обретают различные интерактивные способы завлечь аудиторию и привлечь к себе больше внимания. Тут и боты для социальных сетей и мессенджеров, и другие решения, придающие «уникальности». Среди них можно выделить и динамические обложки для сообществ, официально поддерживать которые ВКонтакте начали в марте.

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


На примере моего пустого сообщества-песочницы

Вступление


Я опишу, как сделать динамическую обложку, отображающую текущее время и последнего подписчика. Любой другой функционал делается не сложнее — чуть больше строк кода и доступ к 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 bg = ImageIO.read(new File("/some/folder/bg.png")),
              userAvatar = ImageIO.read(new URL("https://..."));

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

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

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

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

// Подписываем имя подписчика
g.drawString(userName, xForUserName, yForUserName);

// Записываем результат на диск
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":"402784f0ec814632ac","photo":"eyJvaWQiOi0zNzI3MzTUsMjAwIiwwLCIxNjgwLDEwNTAiLCI3OTUsNDk3Il0sImJ3YWN0Ijoib3duZXJfY292ZXIiLCJzZXJ2ZXIiOjYzODYyOSwibWlkIjoyMzE0ODUyLCc4MSwiZGF0YSI6WyJ4QUFtLXBRQUFBQUFtRUxmY0FBS3A2VEh4bU5WYmJKOG5ZQUFLcDZ2VkMtWjRVMXdmbk9BQUtwNnnMXVvUGdxYkNBQUtwN21nSGJwQlJJdnMxRhpdWM5bldkRktwQUFBS3A3R1NhdFptbFJWNlNCQUFLcDdVamJEFBS3A3NUktQnJTSHotS0hFQUFLcDhLVVRTbzA4VURpTSIsIjAsMCw3OJfc2lnIjoiNjNkNmQ5NmY1ZmI0NWFiYzdjYjZjMjliOGM5NWNhNWMifQ"}
пример от ВКонтакте

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

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

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

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

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

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

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

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

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

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

    g.drawString(now, xForTime, yForTime);

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

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

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

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

Правда, жаль, что у Facebook нет аналогичной возможности обновлять обложку.
Tags:
Hubs:
+39
Comments 46
Comments Comments 46

Articles