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

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

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


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

    Вступление


    Я опишу, как сделать динамическую обложку, отображающую текущее время и последнего подписчика. Любой другой функционал делается не сложнее — чуть больше строк кода и доступ к 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":"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 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 нет аналогичной возможности обновлять обложку.
    Поделиться публикацией
    Похожие публикации
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 44
    • 0
      название студии в студию!
      • +5
        Зачем? Я думаю, что Хабр не площадка ни для рекламы, ни для антирекламы :)
        Студия своё еще получит, ибо есть клиенты, которые собрались даже в суд подавать, а я помогу собрать материалы.
        И в целом, статья нацелена на то, чтобы больше людей увидели, что эта тема довольно проста в реализации и тоже могли заняться этим.
        Больше конкурентов — выше качество рынка :)
      • 0
        Неплохо)
        while (true) {
            Thread.sleep(1000*60);
            ...
        }
        
        • +2
          Я написал, что это примитивнейшний способ и всего лишь пример :)
        • +4
          Пипец… Шестизначные суммы возможность динамически формировать и обновлять картиночки в социальной сети. Я явно не тем занимаюсь.
          • +1
            Вы не поверите, но я тоже этим не занимался, пока не увидел ценники. И крайне сильно был удивлён, осознавая сложность работы и понимая несоизмеримость цен :)
            • +1
              Ради интереса спросил у гугла стоимость подобного — от 1000 до 5000 т.р. Вы в какой валюте 6 знаков увидели?
              • 0
                1 000, 00 :)
                А на самом деле, пока предложеняи мало, находятся люди какие хотят заработать много.
                • +2
                  vlanko, ещё до введения API для обложки, гулял скрипт за чуть большей ценник, чем ваш «шестизнак» выше.

                  Я тоже было запилил даже услугу на фрилансе, но интереса к ней не наблюдал. К тому же «конкуренты», уже через месяц-полтора реализовали подобный функционал прикрутив админку с виджетами и прочими плюшками.
                  Чего бы не придумал, а это уже кто-то сделал)

                  Agel_Nash так то, «5000 т.р.» это уже даже чуть больше чем шестизнак ;)
                • 0
                  Опять же повторюсь, что Хабр не место для рекламы, и если вы не нашли таких ценников, это не значит, что их нет :)
                  • +1
                    5000 т.р — это 7 знаков, если считать в рублях ;)
                    • 0
                      а почему пробел не считается за знак?
                • +2
                  А в чем проблема, если клиент платит? Тут почитай, все такие честные, только себе в убыток работают. А вот то, что киданул исполнителей, это плохо.
                  • +1
                    Никто не говорит о проблемах. Просто, я считаю, что стоит уделять одинаково внимания и клиентам, которые платят большие суммы, и клиентам, которые заказывают что-то простенькое по небольшой цене. А также, конечно, насчёт исполнителей это уже вообще другой вопрос.
                • 0

                  Обновляется ли обложка без перезагрузки страницы браузера?

                  • 0
                    Нет, конечно. Ни ВКонтакте, ни где либо еще, где есть возможность установить обложку, такого нет. В фейсбуке того хуже — вообще нельзя менять обложки через API.
                    • 0
                      Ясно, спасибо. А насколько часто можно загружать новую обложку, есть ограничения со стороны ВК?
                      • 0
                        Нет ограничений, можете хоть каждые 5 секунд обновлять.
                        • 0
                          There can be maximum 3 requests to API methods per second from a client. © dev vk
                  • 0
                    т.е. по сути мы пишем сервис/программу которая будет переодически делать на статический урл запрос с новыми данными? шестизначные суммы? Ну там наверно еще обертку для удобного пользования делают (админку), и аггрегатор информации которая рендерится в картинку, а это уже тянет на пару тыщ долларов.

                    На правах того, что это туториал, задам вопрос:
                    https://api.vk.com/method/photos.saveOwnerCoverPhoto?hash=HASH&photo=PHOTO&access_token=ACCESS_TOKEN&v=5.65

                    Как выглядит параметр PHOTO? Это кодированное содержание файла, это url ссылка, это путь к файлу на диске? Немного не ясно. Полный пример был бы полезен.
                    • 0
                      Шестизначные суммы «студия» брала за крупные проекты с крупными клиентами вроде каналов, банков и проч. Никакой админки там не было.

                      Насчёт вопроса по параметрам — все это подробно описано в документации ВК :)
                      Конкретно параметр PHOTO — просто набор символов, возможно, хэшированная строка.
                      • 0
                        Дополнил материал.
                        А урл может быть статическим, может быть не статическим, мы просто каждый раз его получаем.
                        Да, всё проще некуда: просто обрабатываем картиночку самыми примитивными способами и с помощью парочки GET-запросов загружаем её как обложку. Задача проще некуда и реализуема, наверное, на любом языке программирования.
                        • 0
                          А, вот теперь я понял где пробел.
                          Теперь отправляем на наш upload_url отправляем POST-запрос с полем photo в формате multipart/form-data, точно также, как и с любыми документами.
                          На правах того, что это туториал:) хотелось бы пример запроса.
                          • 0
                            Пример проще некуда: в качестве адреса, на который будет отправлен запрос, выступает наш upload_url, а телом POST-запроса будет наипростейший json:
                            {"photo":"...."}

                            Только не стоит забывать про multipart/form-data формат. Повторюсь: более подробно я описывал в другой статье, да и в интернете немало информации на эту тему :)
                        • +1
                          Шестизначные суммы «студия» брала за крупные проекты с крупными клиентами вроде каналов, банков и проч.

                          Товар стоит столько, сколько за него готовы заплатить. Каналы, банки и проч., на свои услуги не устанавливают минимально возможные наценки, которые позволяли бы им только зарплату сотрудникам выдавать. Отдельные цены для физ. лиц, отдельные цены для юр. лиц, зарплата не больше средней по городу и т. д. Так зачем я, банку, с миллиардной годовой прибылью, буду выставлять счет на 10 т.р., когда они могут позволить себе миллион?
                          • 0
                            Откаты? Не может быть!
                            • 0
                              Товар стоит столько, сколько за него готовы заплатить.

                              С этим никто не спорит. Просто забавляет сам факт того, что обновление картиночки в соцсети стоит как несколько средних зарплат по стране. При том, что зачастую, как раз у крупных клиентов, эти обложки работали всего несколько дней.
                        • 0
                          lxsmkv писал в другой статье, на которую привёл ссылку, да и информации на эту тему предостаточно — не вижу смысла дублировать здесь велосипедный код :)
                          • 0

                            Я так и не понял, что тут динамического.


                            Я могу точно так же свой аватар менять, слушая всякие коллбэки

                            • 0
                              Да, но динамические аватары, насколько я знаю, никого не интересуют :)
                              А обложка — самый заметный элемент, и она это первое, что бросается в глаза.
                              Поэтому и админов интересует, и люди обычные зачастую клюют и хотят на ней оказаться.
                              • 0
                                Ее сразу же проматывают даже не смотря на нее.
                                • 0
                                  Не всегда. С чего бы тогда подобные акции собирали по несколько десятков тысяч комментариев за один вечер? :)
                              • 0
                                А это кстати крутая идея. Только что можно выводить на аватар, чтобы это реально было интересно? Минимальная идея это менять фоточки, типа разные эмоции.
                                • 0
                                  и каждый раз после такого у всех друзей будет в ленте «пользователь обновил фотографию на странице»?
                                  • 0
                                    Нет, это же на собственную стену добавляется и не обязательно постить. Я лично всегда фото у себя обновляю без этой хрени.
                                    • 0
                                      вот только сейчас проверил — обновил аватарку. она появилась в ленте друзей
                                      • 0

                                        Ну, вроде как, если обновлять через API отменить такое поведение нельзя.

                                • +1
                                  я так понял студия эта называется лайв ковер :) не ожидал такого от них
                                  • 0

                                    Недавно СТС проводили такую рекламную кампанию, но у них все провалилось из-за того, что при каждом обновлении они вылезали в ленте. PeterSamokhin, подскажи, починили ли это сейчас? Или все также уведомление сыпется каждый раз?

                                    • +1
                                      Так вот для СТС это и делала та самая студия. Починили или нет — не знаю, ту обложку делал не я, а связи со студией я разорвал.
                                      А какое уведомление появлялось в ленте? Если обновлять только обложку, в ленте не будет ничего, это проверено. Видимо, рекламная кампания предусматривала что-то ещё, что и появлялось в ленте: добавление фотографий в альбом и отправка их в комментариях, и так далее. Подобные вещи тоже практиковались, да, и когда фотографии добавляются в альбом, в ленте это появляется.
                                    • 0
                                      Может дать ссылку на какую-нибудь такую группу? Хочется вживую увидеть.
                                      • 0
                                        Снова увидел комментарий, хотел ответить. Но вспомнил — ответил Вам в личные сообщения :)
                                        • 0
                                          Похоже, таки ответили, но потом исправили =)

                                      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.