Почему я решил написать эту небольшую статью? Хотя ажиотаж вокруг этой темы и спал, всё равно она остаётся довольно популярной, находятся как «клиенты», готовые платить очень большие деньги, так и желающие научиться это делать самому. Я работал с одной «студией», которая берет шестизначные суммы за эту работу, при этом кидая своих разработчиков и мелких клиентов. Так вот, чтобы в этой сфере не было монополии, и все увидели, насколько легко это делается, я и решил написать статью.
На примере моего пустого сообщества-песочницы
Вступление
Я опишу, как сделать динамическую обложку, отображающую текущее время и последнего подписчика. Любой другой функционал делается не сложнее — чуть больше строк кода и доступ к 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 нет аналогичной возможности обновлять обложку.
P.S. В ответ на комментарии. Картинка в начале — просто демонстрация. Сообщество является моим полигоном для тестов и на постоянной основе там не работает ничего.
Комментарии (44)
Assargin
11.06.2017 23:14+4Пипец… Шестизначные суммы возможность динамически формировать и обновлять картиночки в социальной сети. Я явно не тем занимаюсь.
PeterSamokhin
11.06.2017 23:28+1Вы не поверите, но я тоже этим не занимался, пока не увидел ценники. И крайне сильно был удивлён, осознавая сложность работы и понимая несоизмеримость цен :)
Agel_Nash
12.06.2017 04:34+1Ради интереса спросил у гугла стоимость подобного — от 1000 до 5000 т.р. Вы в какой валюте 6 знаков увидели?
vlanko
12.06.2017 08:511 000, 00 :)
А на самом деле, пока предложеняи мало, находятся люди какие хотят заработать много.Sliworez
12.06.2017 11:51+2vlanko, ещё до введения API для обложки, гулял скрипт за чуть большей ценник, чем ваш «шестизнак» выше.
Я тоже было запилил даже услугу на фрилансе, но интереса к ней не наблюдал. К тому же «конкуренты», уже через месяц-полтора реализовали подобный функционал прикрутив админку с виджетами и прочими плюшками.
Чего бы не придумал, а это уже кто-то сделал)
Agel_Nash так то, «5000 т.р.» это уже даже чуть больше чем шестизнак ;)
PeterSamokhin
12.06.2017 15:27Опять же повторюсь, что Хабр не место для рекламы, и если вы не нашли таких ценников, это не значит, что их нет :)
Sergiy
12.06.2017 12:51+2А в чем проблема, если клиент платит? Тут почитай, все такие честные, только себе в убыток работают. А вот то, что киданул исполнителей, это плохо.
PeterSamokhin
12.06.2017 15:26+1Никто не говорит о проблемах. Просто, я считаю, что стоит уделять одинаково внимания и клиентам, которые платят большие суммы, и клиентам, которые заказывают что-то простенькое по небольшой цене. А также, конечно, насчёт исполнителей это уже вообще другой вопрос.
AlexUsov
11.06.2017 23:46Обновляется ли обложка без перезагрузки страницы браузера?
PeterSamokhin
11.06.2017 23:47Нет, конечно. Ни ВКонтакте, ни где либо еще, где есть возможность установить обложку, такого нет. В фейсбуке того хуже — вообще нельзя менять обложки через API.
AlexUsov
12.06.2017 10:42Ясно, спасибо. А насколько часто можно загружать новую обложку, есть ограничения со стороны ВК?
lxsmkv
12.06.2017 02:21т.е. по сути мы пишем сервис/программу которая будет переодически делать на статический урл запрос с новыми данными? шестизначные суммы? Ну там наверно еще обертку для удобного пользования делают (админку), и аггрегатор информации которая рендерится в картинку, а это уже тянет на пару тыщ долларов.
На правах того, что это туториал, задам вопрос:
https://api.vk.com/method/photos.saveOwnerCoverPhoto?hash=HASH&photo=PHOTO&access_token=ACCESS_TOKEN&v=5.65
Как выглядит параметр PHOTO? Это кодированное содержание файла, это url ссылка, это путь к файлу на диске? Немного не ясно. Полный пример был бы полезен.PeterSamokhin
12.06.2017 02:36Шестизначные суммы «студия» брала за крупные проекты с крупными клиентами вроде каналов, банков и проч. Никакой админки там не было.
Насчёт вопроса по параметрам — все это подробно описано в документации ВК :)
Конкретно параметр PHOTO — просто набор символов, возможно, хэшированная строка.PeterSamokhin
12.06.2017 02:50Дополнил материал.
А урл может быть статическим, может быть не статическим, мы просто каждый раз его получаем.
Да, всё проще некуда: просто обрабатываем картиночку самыми примитивными способами и с помощью парочки GET-запросов загружаем её как обложку. Задача проще некуда и реализуема, наверное, на любом языке программирования.lxsmkv
12.06.2017 03:14А, вот теперь я понял где пробел.
Теперь отправляем на наш upload_url отправляем POST-запрос с полем photo в формате multipart/form-data, точно также, как и с любыми документами.
На правах того, что это туториал:) хотелось бы пример запроса.PeterSamokhin
12.06.2017 15:31Пример проще некуда: в качестве адреса, на который будет отправлен запрос, выступает наш upload_url, а телом POST-запроса будет наипростейший json:
{"photo":"...."}
Только не стоит забывать про multipart/form-data формат. Повторюсь: более подробно я описывал в другой статье, да и в интернете немало информации на эту тему :)
tasty_brains
12.06.2017 11:52+1Шестизначные суммы «студия» брала за крупные проекты с крупными клиентами вроде каналов, банков и проч.
Товар стоит столько, сколько за него готовы заплатить. Каналы, банки и проч., на свои услуги не устанавливают минимально возможные наценки, которые позволяли бы им только зарплату сотрудникам выдавать. Отдельные цены для физ. лиц, отдельные цены для юр. лиц, зарплата не больше средней по городу и т. д. Так зачем я, банку, с миллиардной годовой прибылью, буду выставлять счет на 10 т.р., когда они могут позволить себе миллион?PeterSamokhin
12.06.2017 15:21Товар стоит столько, сколько за него готовы заплатить.
С этим никто не спорит. Просто забавляет сам факт того, что обновление картиночки в соцсети стоит как несколько средних зарплат по стране. При том, что зачастую, как раз у крупных клиентов, эти обложки работали всего несколько дней.
PeterSamokhin
12.06.2017 03:27lxsmkv писал в другой статье, на которую привёл ссылку, да и информации на эту тему предостаточно — не вижу смысла дублировать здесь велосипедный код :)
Virviil
12.06.2017 08:26Я так и не понял, что тут динамического.
Я могу точно так же свой аватар менять, слушая всякие коллбэки
PeterSamokhin
12.06.2017 09:03Да, но динамические аватары, насколько я знаю, никого не интересуют :)
А обложка — самый заметный элемент, и она это первое, что бросается в глаза.
Поэтому и админов интересует, и люди обычные зачастую клюют и хотят на ней оказаться.lpwaterhouse
12.06.2017 11:49Ее сразу же проматывают даже не смотря на нее.
PeterSamokhin
12.06.2017 15:22Не всегда. С чего бы тогда подобные акции собирали по несколько десятков тысяч комментариев за один вечер? :)
Dromok
12.06.2017 12:31А это кстати крутая идея. Только что можно выводить на аватар, чтобы это реально было интересно? Минимальная идея это менять фоточки, типа разные эмоции.
StallinHrusch
12.06.2017 14:41и каждый раз после такого у всех друзей будет в ленте «пользователь обновил фотографию на странице»?
Dromok
12.06.2017 14:44Нет, это же на собственную стену добавляется и не обязательно постить. Я лично всегда фото у себя обновляю без этой хрени.
StallinHrusch
12.06.2017 15:04вот только сейчас проверил — обновил аватарку. она появилась в ленте друзей
mannaro
12.06.2017 15:10Недавно СТС проводили такую рекламную кампанию, но у них все провалилось из-за того, что при каждом обновлении они вылезали в ленте. PeterSamokhin, подскажи, починили ли это сейчас? Или все также уведомление сыпется каждый раз?
PeterSamokhin
12.06.2017 15:16+1Так вот для СТС это и делала та самая студия. Починили или нет — не знаю, ту обложку делал не я, а связи со студией я разорвал.
А какое уведомление появлялось в ленте? Если обновлять только обложку, в ленте не будет ничего, это проверено. Видимо, рекламная кампания предусматривала что-то ещё, что и появлялось в ленте: добавление фотографий в альбом и отправка их в комментариях, и так далее. Подобные вещи тоже практиковались, да, и когда фотографии добавляются в альбом, в ленте это появляется.
perfect_genius
13.06.2017 14:03Может дать ссылку на какую-нибудь такую группу? Хочется вживую увидеть.
PeterSamokhin
16.06.2017 00:07Снова увидел комментарий, хотел ответить. Но вспомнил — ответил Вам в личные сообщения :)
zxweed
название студии в студию!
PeterSamokhin
Зачем? Я думаю, что Хабр не площадка ни для рекламы, ни для антирекламы :)
Студия своё еще получит, ибо есть клиенты, которые собрались даже в суд подавать, а я помогу собрать материалы.
И в целом, статья нацелена на то, чтобы больше людей увидели, что эта тема довольно проста в реализации и тоже могли заняться этим.
Больше конкурентов — выше качество рынка :)