вторник, 12 сентября 2017 г.

Google скрипт и динамическая обложка VK

По мотивам статьи на habrahabr.ru

Динамические обложки VK в основном требуют размещения скриптов на отдельном сервере, на котором они запускаются средствами cron. И для этого необходимо каждый месяц вносить абонентскую плату.

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

Получаем ссылку на загрузку обложки

function coverUrlGET() {
  
   var url = 'https://api.vk.com/method/photos.getOwnerCoverPhotoUploadServer?group_id=XXXXXXXX&crop_x=0&crop_y=0&crop_x2=1590&crop_y2=400&access_token=YYYYYYYY&v=5.64';
  
  var options =
      {
        "method"  : "GET",   
        "followRedirects" : true,
        "muteHttpExceptions": true
      };
    
  var result = UrlFetchApp.fetch(url, options);
  
  if (result.getResponseCode() == 200) {
    
    var params = JSON.parse(result.getContentText());
    return params.response.upload_url;
    
  }  
}

XXXXXXXX-id группы, YYYYYYYYYYYY - токен группы (сообщества)


Т.о. мы получили ссылку для загрузки нашей будущей обложки, но самой обложки пока нет. Для рисования логично было бы использовать Google рисунки, но для них пока нет описания методов работы через скрипты.:) 
Работать будем с помощью презентаций google. Для этого необходимо включить использование  Google Slides API и Drive API в скрипте.
Необходимо создать презентацию и задать ей размеры совпадающие с размерами обложки VK. Задаём фоновую картинку, которая не будет меняться.

Добавляем текстовое поле для вставки аватарки пользователя и ещё одно для фамилии и имени.


Получаем последнего подписчика:


function getLastUser() {

   var url = 'https://api.vk.com/method/groups.getMembers?group_id=XXXXXXXX&sort=time_desc&count=1&fields=photo_200_orig&access_token=YYYYYYYYYY&v=5.64';

  var options =
      {
        "method"  : "GET",
        "followRedirects" : true,
        "muteHttpExceptions": true
      };
 
  var result = UrlFetchApp.fetch(url, options);
 
  
 var jresult= JSON.parse(result.getContentText());
 var surname = jresult.response.items[0].last_name;
 var name = jresult.response.items[0].first_name;
 var photoU = jresult.response.items[0].photo_200_orig;

  return surname+';'+name+';'+photoU;

}

XXXXXXXX-id группы, YYYYYYYYYYYY - токен группы (сообщества)

Вставляем данные в презентацию и получаем ссылку на скачивание слайда в виде jpeg файла

function getSlideJpeg() {
    
  var templateId='ID вашей презентации'
  
   var preID = DriveApp.getFileById(templateId).makeCopy().getId();

  var lastUser=getLastUser().split(';')

var reqs = [    

  {"replaceAllShapesWithImage": {

  "imageUrl": lastUser[2],

  "replaceMethod": "CENTER_CROP",
  "containsText": {
           "text": "User",
           "matchCase": "True",
               }
  },},

  ];


  var response = Slides.Presentations.batchUpdate({'requests': reqs},preID);


  var pre = Slides.Presentations.get(preID);

  var page = pre.slides[0].objectId
  var pageElementId = pre.slides[0].pageElements[2].objectId;
  
  var requests = [{

    "deleteText": {

      "objectId": pageElementId,
     
    }
                  },{
    "insertText": {
      "objectId": pageElementId2,
      "text": lastUser[0]+' '+lastUser[1],
      "insertionIndex": 0
    }
  }];
   
Slides.Presentations.batchUpdate({'requests': requests}, preID);
  
  return 'https://docs.google.com/presentation/d/'+preID+'/export/jpeg?id='+preID+'&pageid='+page+';'+preID
}

Как сказано здесь ссылкаполе должно содержать изображение в формате multipart/form-data. Делаем:

function setCoverPOST() {
  var urlpp=getSlideJpeg()
  var urljpg = urlpp.split(';')[0];

  var boundary = "labnol";
  var blob = convert(urljpg).getBlob();
  DriveApp.removeFile(DriveApp.getFileById(urlpp.split(';')[1]));
   var requestBody = Utilities.newBlob(
    "--"+boundary+"\r\n"
       + "Content-Disposition: form-data; name=\"file\"; filename=\""+blob.getName()+"\"\r\n"
  + "Content-Type: " + blob.getContentType()+"\r\n\r\n").getBytes()
  .concat(blob.getBytes())
  .concat(Utilities.newBlob("\r\n--"+boundary+"--\r\n").getBytes());
   var options = {
    method: "post",
    contentType: "multipart/form-data; boundary="+boundary,
    payload: requestBody,
    muteHttpExceptions: true,
  };

  var request = UrlFetchApp.fetch(coverUrlGET(), options);
  return request.getContentText();
  

}

function convert(urlp){
  
  var options =
      {
         "headers": {
           "Authorization": 'Bearer ' + ScriptApp.getOAuthToken()
         },
   
        "method"  : "GET",   
        "followRedirects" : true,
        "muteHttpExceptions": true
      };
    
  var result = UrlFetchApp.fetch(urlp, options);

 return result;
}

Ну, а теперь функция собирающая всё это вместе

function putCoverVK(){
  
  var postAnswer=JSON.parse(setCoverPOST());
  
   var url = 'https://api.vk.com/method/photos.saveOwnerCoverPhoto?hash='+postAnswer.hash+'&photo='+postAnswer.photo+'&access_token=YYYYYYYYYYYYYYYY&v=5.65';
  
  var options =
      {
        "method"  : "GET",   
        "followRedirects" : true,
        "muteHttpExceptions": true
      };
    
  var result = UrlFetchApp.fetch(url, options);
  
  if (result.getResponseCode() == 200) {
    
    var params = JSON.parse(result.getContentText());

    
  }  
  

YYYYYYYYYYYYYYYY - токен группы. 

Через глобальные переменные код можно местами упростить, сделать красивее. Триггер на час нужно ставить именно на последнюю функцию. 
Конечно, добавив ещё текстовых полей можно работать и с погодой (данные в Интернете брать есть откуда), и со временем.  

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

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

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