Google рдлрд╝реЙрд░реНрдо рдХрд╛ рдирд┐рд░реНрдпрд╛рдд рдХрд░реЗрдВ + REST API (рдкрд╛рдпрдерди) рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ Google рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ



рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рджреЛ Google рдкреНрд░рдкрддреНрд░, рдкреНрд░рддреНрдпреЗрдХ рдореЗрдВ 75 рдкреНрд░рд╢реНрди, 5 рд╡реНрдпрд╡рд╕рд╛рдп рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╣реИрдВ рдЬрд┐рдиреНрд╣реЛрдВрдиреЗ рдЗрди рд░реВрдкреЛрдВ рдХреЛ рд╕рдХреНрд░рд┐рдп рд░реВрдк рд╕реЗ рд╕рдВрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рд╣реИ, рдФрд░ JSON рдХреЛ рдлрд╝реЙрд░реНрдо рдирд┐рд░реНрдпрд╛рдд рдХрд░рдиреЗ рд╡рд╛рд▓реА рдПрдХ Google рд╕реНрдХреНрд░рд┐рдкреНрдЯ рднреА рд╣реИред рдРрд╕рд╛ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЗрд╕реЗ рд╣рд░ рдмрд╛рд░ рдЕрдкрдиреЗ рд╣рд╛рдереЛрдВ рд╕реЗ рдЪрд▓рд╛рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реЛрдЧрд╛, рд▓реЗрдХрд┐рди рдПрдХ рдмрд╛рд░ рдЬрдм рдЖрдк рдЕрдкрдиреЗ рдХрд╛рдо рдХреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЗрд╕ рд╢реМрдХ рдХреЛ рдЕрдВрдд рддрдХ рдЬрд╛рдПрдВред

рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рджрд╕реНрддрд╛рд╡реЗрдЬ рдореЗрдВ, рд╢реИрддрд╛рди рдЕрдкрдиреЗ рдкреИрд░ рдХреЛ рддреЛрдбрд╝ рджреЗрдЧрд╛, рдЗрд╕рд▓рд┐рдП рдмрд┐рд▓реНрд▓реА рдХреЗ рдиреАрдЪреЗ рд╣рдо рдкрд╛рдпрдерди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ REST API рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ Google Apps рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЗ рджреВрд░рд╕реНрде рдбрд╛рдЙрдирд▓реЛрдб рдФрд░ рд▓реЙрдиреНрдЪ рдкрд░ рдХрд░реАрдм рд╕реЗ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВрдЧреЗред

рдкрд░рд┐рдЪрдп


рдбреЙрдХреНрдЯрд░ рдирд┐рдпрд░ рдореЗрдВ, рд╣рдо рдЪреИрдЯ рдмреЙрдЯреНрд╕ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рд╡рд┐рдХрд╕рд┐рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рдЬрд┐рд╕рдореЗрдВ рдкрд░рд┐рджреГрд╢реНрдпреЛрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП Google рд░реВрдкреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рддрджрдиреБрд╕рд╛рд░, рдореИрдВ рдПрдХ рдмрдЯрди рдХреЗ рдХреНрд▓рд┐рдХ рдкрд░ рдкреНрд░рдкрддреНрд░реЛрдВ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛, рдПрдХ JSON рдЬрд┐рд╕рдореЗрдВ рдиреЛрдбреНрд╕ (рдкреНрд░рдкрддреНрд░ рдмрд┐рдВрджреБ) рд╣реИрдВ рдФрд░ рдЙрдирд╕реЗ рдореЗрдЯрд╛рдбреЗрдЯрд╛ (рдиреЛрдбреНрд╕ рдХреЗ рдмреАрдЪ рд╕рдВрдХреНрд░рдордг, рдиреЛрдбреНрд╕ рдХреЗ рдкреНрд░рдХрд╛рд░, рдЙрдирдХрд╛ рдирд╛рдо)ред рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрдЪреНрдЫрд╛ рд╕рд░рд▓ рд╣реИ, рд▓реЗрдХрд┐рди Google рдЗрд╕ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЖрдкрдХреЛ рдЕрдкрдиреЗ рд╣рд╛рдереЛрдВ рд╕реЗ рдЗрд╕ "рдирд┐рд░реНрдпрд╛рддрдХ" рдХреЛ рдЗрдХрдЯреНрдард╛ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдЗрд╕реЗ рдмрдирд╛рдиреЗ рдХреЗ рдЪрд░рдгреЛрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред

рдХрджрдо 1. Google Apps рд╕реНрдХреНрд░рд┐рдкреНрдЯ


Google рдиреЗ рдЕрдкрдиреА рд╕реЗрд╡рд╛рдУрдВ (рд╢реАрдЯреНрд╕, рдбреЙрдХреНрд╕, рдлрд╝реЙрд░реНрдо) рдХреЗ рд╕рд╛рде Google Apps рд╕реНрдХреНрд░рд┐рдкреНрдЯ - Google рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рд▓рд┐рдЦреА рдЧрдИ рд╕реНрдХреНрд░рд┐рдкреНрдЯ (.gs) рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдмрд╛рддрдЪреАрдд рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдкреНрд░рджрд╛рди рдХреА рд╣реИред рдпрд╣ рд▓реЗрдЦ Google рд╕реНрдХреНрд░рд┐рдкреНрдЯ рднрд╛рд╖рд╛ рдХреА рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдкреНрд░рджрд╛рди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдПрдХ рддреИрдпрд╛рд░ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рджреВрдВрдЧрд╛ рдЬреЛ рдореМрдЬреВрджрд╛ Google рдлреЙрд░реНрдо рд╕реЗ JSON рдмрдирд╛рддрд╛ рд╣реИред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛрдб рд╕реНрдЯреАрд╡рди рд╢реНрдореЗрдЯреНрдЬрд╝ рдХреЛ рдПрдХ рдЖрдзрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдЧрд┐рдЯрдм рд╕реЗ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рдореИрдВ рдЙрдирдХреЗ рдкреНрд░рддрд┐ рдЖрднрд╛рд░ рд╡реНрдпрдХреНрдд рдХрд░рддрд╛ рд╣реВрдВред

рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛрдб
// Steven Schmatz // Humanitas Labs // 13 October, 2016. // Roman Shekhovtsov // dr-telemed.ru // Autumn 2019 // Nikita Orekhov // dr-telemed.ru // Autumn 2019 /** * Converts the given form URL into a JSON object. */ function main() { form_url = "<YOUR_FORM_URL>" var form = FormApp.openByUrl(form_url); var items = form.getItems(); var result = { "metadata": getFormMetadata(form), "items": items.map(itemToObject), "count": items.length }; // sendEmail("<YOUR_EMAIL>", result) return result; } /** If we want to receive data by email * Sends JSON as text to recipient email * @param recipient: String * @param result: JSON */ function sendEmail(recipient, json_file){ var subject = "google form json import" var body = JSON.stringify(json_file); Logger.log(body); MailApp.sendEmail(recipient, subject, body); } /** * Returns the form metadata object for the given Form object. * @param form: Form * @returns (Object) object of form metadata. */ function getFormMetadata(form) { return { "title": form.getTitle(), "id": form.getId(), "description": form.getDescription(), "publishedUrl": form.getPublishedUrl(), "editorEmails": form.getEditors().map(function(user) { return user.getEmail() }), "count": form.getItems().length, "confirmationMessage": form.getConfirmationMessage(), "customClosedFormMessage": form.getCustomClosedFormMessage() }; } /** * Returns an Object for a given Item. * @param item: Item * @returns (Object) object for the given item. */ function itemToObject(item) { var data = {}; data.type = item.getType().toString(); // Downcast items to access type-specific properties var itemTypeConstructorName = snakeCaseToCamelCase("AS_" + item.getType().toString() + "_ITEM"); var typedItem = item[itemTypeConstructorName](); // Keys with a prefix of "get" have "get" stripped var getKeysRaw = Object.keys(typedItem).filter(function(s) {return s.indexOf("get") == 0}); getKeysRaw.map(function(getKey) { var propName = getKey[3].toLowerCase() + getKey.substr(4); // Image data, choices, and type come in the form of objects / enums if (["image", "choices", "type", "alignment"].indexOf(propName) != -1) {return}; // Skip feedback-related keys if ("getFeedbackForIncorrect".equals(getKey) || "getFeedbackForCorrect".equals(getKey) || "getGeneralFeedback".equals(getKey)) {return}; var propValue = typedItem[getKey](); data[propName] = propValue; }); // Bool keys are included as-is var boolKeys = Object.keys(typedItem).filter(function(s) { return (s.indexOf("is") == 0) || (s.indexOf("has") == 0) || (s.indexOf("includes") == 0); }); boolKeys.map(function(boolKey) { var propName = boolKey; var propValue = typedItem[boolKey](); data[propName] = propValue; }); // Handle image data and list choices switch (item.getType()) { case FormApp.ItemType.LIST: case FormApp.ItemType.CHECKBOX: data.choices = typedItem.getChoices().map(function(choice) { return choice.getValue() }); case FormApp.ItemType.MULTIPLE_CHOICE: data.choices = typedItem.getChoices().map(function(choice) { gotoPage = choice.getGotoPage() if (gotoPage == null) return choice.getValue() else return { "value": choice.getValue(), "gotoPage":choice.getGotoPage().getId() }; }); break; case FormApp.ItemType.IMAGE: data.alignment = typedItem.getAlignment().toString(); if (item.getType() == FormApp.ItemType.VIDEO) { return; } var imageBlob = typedItem.getImage(); data.imageBlob = { "dataAsString": "", //imageBlob.getDataAsString(), - BLOB too big "name": imageBlob.getName(), "isGoogleType": imageBlob.isGoogleType() }; break; case FormApp.ItemType.PAGE_BREAK: data.pageNavigationType = typedItem.getPageNavigationType().toString(); break; default: break; } // Have to do this because for some reason Google Scripts API doesn't have a // native VIDEO type if (item.getType().toString() === "VIDEO") { data.alignment = typedItem.getAlignment().toString(); } return data; } /** * Converts a SNAKE_CASE string to a camelCase string. * @param s: string in snake_case * @returns (string) the camelCase version of that string */ function snakeCaseToCamelCase(s) { return s.toLowerCase().replace(/(\_\w)/g, function(m) {return m[1].toUpperCase();}); } 


рдХреЛрдб рдореЗрдВ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИ:

  • getFormMetadata рдлрд╝рдВрдХреНрд╢рди - рдлреЙрд░реНрдо рдореЗрдЯрд╛рдбрд╛рдЯрд╛ рдХреЗ рд╕рд╛рде JSON рджреЗрддрд╛ рд╣реИ
  • itemToObject рдлрд╝рдВрдХреНрд╢рди - рдЖрд╡рд╢реНрдпрдХ рдлрд╝реАрд▓реНрдб рдХреЗ рд╕рд╛рде JSON рдХреЗ рд▓рд┐рдП form.item рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рд░реВрдкрд╛рдВрддрд░рд┐рдд рдХрд░рддрд╛ рд╣реИ
  • sendEmail рдлрд╝рдВрдХреНрд╢рди - рдкрд╛рда рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдореЗрд▓ рдкрд░ рдПрдХ JSON рдлрд╝рд╛рдЗрд▓ рднреЗрдЬрддрд╛ рд╣реИ
  • рдореБрдЦреНрдп рдХрд╛рд░реНрдп - рдкрд░рд┐рдгрд╛рдореА JSON рджреЗрддрд╛ рд╣реИ
  • рдореБрдЦреНрдп рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ form_url рдЪрд░ рд╣рдорд╛рд░реЗ Google рдлрд╝реЙрд░реНрдо рдХрд╛ рдкрддрд╛ рд╣реИ

STEP 2. рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдирд╛


рдлрд┐рд▓рд╣рд╛рд▓, рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЗ рдкреНрд░рджрд░реНрд╢рди рдХреА рдЬрд╛рдБрдЪ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИ:

  1. рдЕрдкрдиреА рдЦреБрдж рдХреА рдРрдк рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдмрдирд╛рдПрдВ
  2. рдЗрд╕рдореЗрдВ рдХреЛрдб рдХреЙрдкреА рдХрд░реЗрдВ
  3. <your_FORM_URL> рдХреЗ рдмрдЬрд╛рдп рд╣рдо рдЕрдкрдиреЗ рдкреНрд░рдкрддреНрд░ docs.google.com/forms/d/FORM_IDENTIFICATOR/edit рдХреЗ рдкрддреЗ рдХрд╛ рд╕реНрдерд╛рди рд▓реЗрддреЗ рд╣реИрдВ
  4. рдореБрдЦреНрдп рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдХреЙрд▓ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдХреЙрд▓ рдХрд░реЗрдВ
  5. <Your_EMAIL> рдХреЗ рдмрдЬрд╛рдп рд╣рдо рдЙрд╕ рдИрдореЗрд▓ рдкрддреЗ рдХреЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рд╕реЗ рд╣рдо JSON рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ
  6. рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛ рдмрдЪрд╛рдУ
  7. рдореБрдЦреНрдп рдХрд╛рд░реНрдп рдЪрд▓рд╛рдПрдБ
  8. рдпрджрд┐ рдпрд╣ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдкрд╣рд▓рд╛ рд░рди рд╣реИ, рддреЛ рд╕рд┐рд╕реНрдЯрдо рдЖрдкрдХреЛ рдЕрдкрдиреЗ рдкрддреЗ рд╕реЗ рдИрдореЗрд▓ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реВрдЪрд┐рдд рдХрд░реЗрдЧрд╛ред рдбрд░реЗрдВ рдирд╣реАрдВред рдпрд╣ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдорд╛рдирдХ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рд╣реИред "рд╕рдореАрдХреНрд╖рд╛ рдЕрдиреБрдорддрд┐рдпрд╛рдВ" рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЬрд╛рдПрдВ -> рдЕрдкрдирд╛ рдЦрд╛рддрд╛ рдЪреБрдиреЗрдВ -> "рдЙрдиреНрдирдд" -> "PROJECT_NAME рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдкрд░ рдЬрд╛рдПрдВ (рдЕрд╕реБрд░рдХреНрд╖рд┐рдд)" -> "рдЕрдиреБрдорддрд┐ рджреЗрдВ"
  9. рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рдиреЗ рдХрд╛ рдЗрдВрддрдЬрд╛рд░ рд╣реИ
  10. рдореЗрд▓рдмреЙрдХреНрд╕ рдореЗрдВ рджреЗрдЦреЗрдВ рдФрд░ рдЯреЗрдХреНрд╕реНрдЯ рдлреЙрд░реНрдо рдореЗрдВ JSON рдлрд╝рд╛рдЗрд▓ рджреЗрдЦреЗрдВ

рд╕рдм рдХреБрдЫ рдареАрдХ рд╣реЛрдЧрд╛, рд▓реЗрдХрд┐рди рдкреНрд░рд╛рдкреНрдд рдбреЗрдЯрд╛ рдХреЗ рдЖрдЧреЗ рдЙрдкрдпреЛрдЧ рдореЗрдВ рдореЗрд▓ рд╕реЗ рдореИрдиреБрдЕрд▓ рдХреЙрдкреА рдХрд░рдирд╛, рдЗрд╕ рдкрд╛рда рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдирд╛ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЕрдЬрдЧрд░ рдореЗрдВ) рд╢рд╛рдорд┐рд▓ рд╣реИ рдФрд░ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдлрд╝рд╛рдЗрд▓ рдХреЛ рд╕рд╣реЗрдЬрдирд╛ рд╣реИред рдпрд╣ рдмрд╣реБрдд рдЙрддреНрдкрд╛рджрди рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рдирд╣реАрдВ рд╣реИред рд╣рдо рдЗрд╕ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЗ рд▓реЙрдиреНрдЪ рдХреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕рдХрд╛ рдкрд░рд┐рдгрд╛рдо Google Apps рд╕реНрдХреНрд░рд┐рдкреНрдЯ API рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдкрд╣рд▓реЗ рд╣рдо рдЕрдкрдиреЗ Google рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЛ рдЙрд╕реА рдХреЗ рдЕрдиреБрд╕рд╛рд░ рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВред

рдзреНрдпрд╛рди: рдХреНрдпрд╛ рд╣реЛ рд░рд╣рд╛ рд╣реИ рдпрд╣ рд╕рдордЭрдиреЗ рдХреА рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП, рдиреАрдЪреЗ рдореИрдВ рдХреЗрд╡рд▓ рджреЛ рдкреГрд╖реНрдареЛрдВ рдХрд╛ рд╕рдВрджрд░реНрдн рджреВрдВрдЧрд╛, рдЗрд╕рд▓рд┐рдП рдЙрдиреНрд╣реЗрдВ рдирд┐рдХрдЯрд╡рд░реНрддреА рдЯреИрдм рдореЗрдВ рдЦреЛрд▓рдиреЗ рдХреА рд╕рд┐рдлрд╛рд░рд┐рд╢ рдХреА рдЧрдИ рд╣реИ:

  1. рд╕реНрдХреНрд░рд┐рдкреНрдЯ / рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╕рдВрдкрд╛рджрди рдкреГрд╖реНрда - "рдкреЗрдЬ 1"
  2. Google рдХреНрд▓рд╛рдЙрдб рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдкреЗрдЬ - "рдкреЗрдЬ 2"

STEP 3. Google рдХреНрд▓рд╛рдЙрдб рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВ


рд╣рдо Google рдХреНрд▓рд╛рдЙрдб рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо (рдкреГрд╖реНрда 2) рдкрд░ рдЬрд╛рддреЗ рд╣реИрдВ, рдПрдХ рдирдИ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдмрдирд╛рддреЗ рд╣реИрдВред рдПрдХ рдирдИ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдмрдирд╛рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреА рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд╕реНрдерд┐рддрд┐ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд╣реИ, рдФрд░ рд╣рдорд╛рд░реЗ рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рд╕реНрдЯреИрдВрдбрдЖрд░реНрдЯ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЕрдзрд┐рдХ рд╡рд┐рд╡рд░рдг рдпрд╣рд╛рдВ рдкрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ (рдмрд┐рдВрджреБ 3)ред

рд╣рдо рдкреЗрдЬ 2 рдкрд░ рд▓реМрдЯрддреЗ рд╣реИрдВ, рдЯреИрдм "рдПрдкреАрдЖрдИ рдФрд░ рд╕рд░реНрд╡рд┐рд╕реЗрдЬ" рдкрд░ рдЬрд╛рддреЗ рд╣реИрдВ, рдлрд┐рд░ "рдУрдЙрде рдПрдХреНрд╕реЗрд╕ рд░рд┐рдХреНрд╡реЗрд╕реНрдЯ рд╡рд┐рдВрдбреЛ"ред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкреНрд░рдХрд╛рд░ рдХреЛ "рдмрд╛рд╣рд░реА" рдкрд░ рд╕реЗрдЯ рдХрд░реЗрдВред

рджрд┐рдЦрд╛рдИ рджреЗрдиреЗ рд╡рд╛рд▓реА рд╡рд┐рдВрдбреЛ рдореЗрдВ, "рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдирд╛рдо" рднрд░реЗрдВред

Google рдХреНрд▓рд╛рдЙрдб рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдкрд░ рд╣реЛрдо рдкреЗрдЬ рдЦреЛрд▓реЗрдВред рдмреНрд▓реЙрдХ "рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдЗрдВрдлреЙрд░реНрдореЗрд╢рди" рд╕реЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдирдВрдмрд░ рдХреЙрдкреА рдХрд░реЗрдВред

рдкреГрд╖реНрда рдкрд░ рдЬрд╛рдПрдВ 1. рдкрд╣рд▓реЗ рд╕реЗ рдмрдирд╛рдИ рдЧрдИ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЦреЛрд▓реЗрдВред рдЦреБрд▓реА рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╕рдВрдкрд╛рджрди рд╡рд┐рдВрдбреЛ рдореЗрдВ, "рд╕рдВрд╕рд╛рдзрди" -> "рдХреНрд▓рд╛рдЙрдб рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдкреНрд░реЛрдЬреЗрдХреНрдЯ" рдкрд░ рдЬрд╛рдПрдВред "рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдмрджрд▓реЗрдВ" рдлрд╝реАрд▓реНрдб рдореЗрдВ, рдкрд╣рд▓реЗ рд╕реЗ рдХреЙрдкреА рдХреА рдЧрдИ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рд╕рдВрдЦреНрдпрд╛ рджрд░реНрдЬ рдХрд░реЗрдВред рдЕрдм рдпрд╣ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдмрдирд╛рдИ рдЧрдИ рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╕реЗ рдЬреБрдбрд╝реА рд╣реИред

рдХрджрдо 4. рдкрд╛рдпрдерди рд░реЗрд╕реНрдЯ рдПрдкреАрдЖрдИ


REST API рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдХрд░рдиреЗ рдХрд╛ рд╕рдордп рдЖ рдЧрдпрд╛ рд╣реИ ред рдкрд╛рдпрдерди рднрд╛рд╖рд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред

рдРрдкреНрд╕ рд╕реНрдХреНрд░рд┐рдкреНрдЯ API рд▓реЙрдЧрд┐рди рдХрд░реЗрдВ


рдХреЛрдб рдХреЛ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рддрдХ рдкрд╣реБрдВрдЪрдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдкрд╣рд▓реА рдФрд░ рдмрд╣реБрдд рдорд╣рддреНрд╡рдкреВрд░реНрдг рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдПрдкреНрд╕ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдПрдкреАрдЖрдИ рдореЗрдВ рд▓реЙрдЧрд┐рди рд╣реИред рдУрдкрди рдкреЗрдЬ 2 -> "рдПрдкреАрдЖрдИ рдФрд░ рд╕рд░реНрд╡рд┐рд╕реЗрдЬ" -> "рдХреНрд░реЗрдбреЗрдВрд╢рд┐рдпрд▓реНрд╕" -> "рдХреНрд░реЗрдбреЗрдВрд╢рд┐рдпрд▓реНрд╕ рдмрдирд╛рдПрдВ" -> "OAuth рдХреНрд▓рд╛рдЗрдВрдЯ рдЖрдЗрдбреЗрдВрдЯрд┐рдлрд╛рдпрд░" -> "рдЕрдиреНрдп рдкреНрд░рдХрд╛рд░"ред рд╣рдо рдЕрдкрдиреЗ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рдХреЛ рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВ, рдЙрд╕рдХреЗ рдкрд╛рд╕ рдЬрд╛рддреЗ рд╣реИрдВред рдЯреИрдм "рдХреНрд░реЗрдбреЗрдВрд╢рд┐рдпрд▓реНрд╕" рдореЗрдВ рд╣реЛрдиреЗ рдХреЗ рдХрд╛рд░рдг, "рдбрд╛рдЙрдирд▓реЛрдб рдЬреЛрдВрд╕ рдлрд╛рдЗрд▓ред" рдпрд╣ Google рдореЗрдВ рдХреЛрдб рд╕реЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рддрдХ рдкрд╣реБрдВрдЪ рдХреЗ рд▓рд┐рдП рдореБрдЦреНрдп рдлрд╝рд╛рдЗрд▓ рдХреЛ рд▓реЛрдб рдХрд░реЗрдЧрд╛ред рд╣рдо рдЗрд╕ рдлрд╝рд╛рдЗрд▓ рдХреЛ рдХреНрд░реЗрдбреЗрдВрд╢рд┐рдпрд▓реНрд╕ рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рд░рдЦрддреЗ рд╣реИрдВред

рдЕрдм рдЖрдкрдХреЛ рдЗрд╕ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд╣рд┐рд╕реНрд╕реЗ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдкреАрдЖрдИ (рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдРрдкреНрд╕ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдПрдкреАрдЖрдИ) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, "API рдФрд░ рд╕реЗрд╡рд╛рдПрдБ" -> "рд▓рд╛рдЗрдмреНрд░реЗрд░реА" -> рдЦреЛрдЬ рдореЗрдВ "рдРрдкреНрд╕ рд╕реНрдХреНрд░рд┐рдкреНрдЯ API" рдЯрд╛рдЗрдк рдХрд░реЗрдВ рдФрд░ "рд╕рдХреНрд╖рдо рдХрд░реЗрдВ" рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░реЗрдВред

Google рдХреЗ рд╕рд╛рде рд╕рд╣рднрд╛рдЧрд┐рддрд╛ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдкрд╛рд╕ рдЕрдиреБрдорддрд┐рдпреЛрдВ рдХрд╛ рдПрдХ рд╕рдореВрд╣ рд╣реИ, рдЬрд┐рд╕реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рд▓реЙрдиреНрдЪ рдХрд░рддреЗ рд╕рдордп рджреЗрдирд╛ рд╣реЛрдЧрд╛ред рдпрд╣ рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдХрд┐рд╕реА рд╡рд┐рд╢реЗрд╖ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рдХрд╛рд░реНрдпреЛрдВ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддреА рд╣реИ рдФрд░ рдЖрдк рдЗрд╕реЗ "рдлрд╝рд╛рдЗрд▓" -> "рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдЧреБрдг" -> "рд╕реНрдХреЛрдкреНрд╕" рдореЗрдВ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╕рдВрдкрд╛рджрди рд╡рд┐рдВрдбреЛ рдореЗрдВ рдкреЗрдЬ 1 рдкрд░ рдЬрд╛рдХрд░ рдкрддрд╛ рд▓рдЧрд╛ рд╕рдХрддреЗ рд╣реИрдВред рдХреЛрдб рдореЗрдВ рднрд╡рд┐рд╖реНрдп рдХреЗ рд╕рдВрджрд░реНрдн рдХреЗ рд▓рд┐рдП рдЗрди рдЕрдиреБрдорддрд┐рдпреЛрдВ рдХреЛ рдмрд░рдХрд░рд╛рд░ рд░рдЦрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред

рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рд▓реЙрдЧрд┐рди рдлрд╝рдВрдХреНрд╢рди рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛:

 import pickle import os.path from googleapiclient.discovery import build from google_auth_oauthlib.flow import InstalledAppFlow from google.auth.transport.requests import Request def login(config): try: creds = None # The file token.pickle stores the user's access and refresh tokens, and is # created automatically when the authorization flow completes for the first # time. token_file = config['credentials_path'] + config['token_file'] credentials_file = config['credentials_path'] + config['credentials_file'] if os.path.exists(token_file): with open(token_file, 'rb') as token: creds = pickle.load(token) # If there are no (valid) credentials available, let the user log in. if not creds or not creds.valid: if creds and creds.expired and creds.refresh_token: creds.refresh(Request()) else: flow = InstalledAppFlow.from_client_secrets_file(credentials_file, config['SCOPES']) creds = flow.run_local_server(port=0) # Save the credentials for the next run with open(token_file, 'wb') as token: pickle.dump(creds, token) service = build('script', 'v1', credentials=creds) pprint('Login successful') return service except Exception as e: pprint(f'Login failure: {e}') return None 

рдпрд╣ рдХреЛрдб рдмреНрд▓реЙрдХ Google рдРрдк рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЗ рд╕рд╛рде рдЖрд░рдВрдн рдХрд░рдиреЗ рдХреА рдорд╛рдирдХ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рд╣реИред
рд╣рдо рдПрдХ рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдЯреЛрдХрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рд▓реЙрдЧрд┐рди рдХрд░рдХреЗ рдпрд╛ рддреЛ рдПрдХ рдирдпрд╛ рдЯреЛрдХрди рдмрдирд╛рддреЗ рд╣реИрдВ рдпрд╛ рдХрд┐рд╕реА рдореМрдЬреВрджрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред

рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП, JSON рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдИ рдЧрдИ рдереА, рдЬрд┐рд╕рдХрд╛ рдирд┐рдореНрди рд░реВрдк рд╣реИ:

 { "SCOPES": ["https://www.googleapis.com/auth/forms", "https://www.googleapis.com/auth/script.send_mail"], "credentials_path": "credentials/", "credentials_file": "google_test_project.json", "token_file": "token.pickle" } 

рдорд╣рддреНрд╡рдкреВрд░реНрдг: рдЯреЛрдХрди рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдХреЗ рд▓рд┐рдП рдЕрдиреБрдорддрд┐рдпреЛрдВ рдХреЗ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рджрд╛рдпрд░реЗ рдХреЗ рд╕рд╛рде рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, рдЕрдиреБрдорддрд┐рдпреЛрдВ рдХрд╛ рджрд╛рдпрд░рд╛ рдмрджрд▓рддреЗ рд╕рдордп, рдЖрдкрдХреЛ рдЯреЛрдХрди рдХреЛ рд╣рдЯрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рд▓реЙрдЧрд┐рди рдкрд░ рдПрдХ рдирдпрд╛ рдмрдирд╛рдирд╛ рд╣реЛрдЧрд╛ред

рд░рд┐рдореЛрдЯ рдЕрдкрдбреЗрдЯ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛрдб


рдЕрдм рд╣рдо рд╕реАрдЦреЗрдВрдЧреЗ рдХрд┐ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛрдб рдХреЛ рджреВрд░рд╕реНрде рд░реВрдк рд╕реЗ рдХреИрд╕реЗ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛рдП, рдлрд┐рд░ рдЗрд╕ рдХреЛрдб рдХреЛ рдЪрд▓рд╛рдПрдВ рдФрд░ рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╣рдо Google рд╕рдВрдкрд╛рджрдХ рдореЗрдВ рдЪрд▓рдиреЗ рд╡рд╛рд▓реЗ рдХреЛрдб рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдПрдХ рдкреНрд░рдХрдЯ рдлрд╝рд╛рдЗрд▓ рднреА рд╣реИ рдЬрд┐рд╕рдореЗрдВ рд▓реЙрдиреНрдЪ рдЕрдзрд┐рдХрд╛рд░, рдбрд┐рдкреЙрдЬрд╝рд┐рдЯ рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдЖрджрд┐ рд╢рд╛рдорд┐рд▓ рд╣реИрдВред рдЗрд╕рдХреА рд╕рдВрд░рдЪрдирд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдпрд╣рд╛рдВ рдкрд╛рдИ рдЬрд╛ рд╕рдХрддреА рд╣реИ ред
Google рджреНрд╡рд╛рд░рд╛ рдЖрдкрдХреА рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЗ рд▓рд┐рдП рдмрдирд╛рдИ рдЧрдИ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдореЗрдирд┐рдлрд╝реЗрд╕реНрдЯ рдлрд╝рд╛рдЗрд▓ рдХреЛ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП, "рджреГрд╢реНрдп" -> "рдореИрдирд┐рдлрд╝реЗрд╕реНрдЯ рдлрд╝рд╛рдЗрд▓ рджрд┐рдЦрд╛рдПрдВ" рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдкрд░ рдЬрд╛рдПрдБред рдЗрд╕ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреА рд╕реВрдЪреА рдореЗрдВ рдкреНрд░рдХрдЯ рд╣реЛрдЧрд╛ред

рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рднрд╛рд╖рдг рдмрд┐рдирд╛ рдХрд╛рд░рдг рдирд╣реАрдВ рдерд╛: рджреВрд░рд╕реНрде рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЕрдкрдбреЗрдЯрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рджреЛрдиреЛрдВ рдлрд╝рд╛рдЗрд▓реЛрдВ (* .gs) рдФрд░ рдкреНрд░рдХрдЯ (codecript.json) рдХреЗ рдХреЛрдб рдХреЛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, .gs рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдХреЛрдб рдкрдврд╝реЗрдВ рдЬрд┐рд╕реЗ рд╣рдо рддреИрдирд╛рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ:

  with open('export-google-form.gs', 'r') as f: sample_code = f.read() 

рдЕрдм рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдЙрддреНрдкрдиреНрди рдкреНрд░рдХрдЯ рдкреНрд░рддрд┐ рдХреЛ рдХреЙрдкреА рдХрд░реЗрдВ рдФрд░ рдЗрд╕реЗ рд╣рдорд╛рд░реЗ рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдереЛрдбрд╝рд╛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░реЗрдВред рдкреНрд░рд▓реЗрдЦрди рдХрд╛рдлреА рд╣рдж рддрдХ рдкреНрд░рдХрдЯ рдлрд╝рд╛рдЗрд▓ рдХреА рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЗрд╕ рдмрд┐рдВрджреБ рдкрд░ рдирд╣реАрдВ рд░рд╣реВрдВрдЧрд╛ред рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ "рдПрдХреНрд╕реНрдЯреЗрдВрд╢рди рдПрдВрдкреА" рдЕрдиреБрднрд╛рдЧ рдХреЛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдореЗрдирд┐рдлрд╝реЗрд╕реНрдЯ рдореЗрдВ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рдПрдкреАрдЖрдИ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рджреВрд░рд╕реНрде рд░реВрдк рд╕реЗ рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реИред рдЗрд╕ рдЦрдВрдб рдореЗрдВ рд╣рдо рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рдЪрдХреНрд░ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ рдЗрд╕реЗ рдЪрд▓рд╛рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рд░рдЦрддреЗ рд╣реИрдВред рдореИрдВрдиреЗ рдЙрди рд╕рднреА рдХреЗ рд▓рд┐рдП рд▓реЙрдиреНрдЪ рдХреА рдЕрдиреБрдорддрд┐ рджреА рд╣реИ рдЬрд┐рдиреНрд╣реЛрдВрдиреЗ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдкрд╛рд░рд┐рдд рдХрд░ рджрд┐рдпрд╛ рд╣реИ, рдЬреЛ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ "рдХрд┐рд╕реА рдХреЗ рднреА" рд╕реЗ рдореЗрд▓ рдЦрд╛рддреА рд╣реИ:

 MANIFEST = ''' { "timeZone": "America/New_York", "exceptionLogging": "STACKDRIVER", "executionApi": { "access": "ANYONE" } } '''.strip() 

рдЕрджреНрдпрддрди рдЕрдиреБрд░реЛрдз рдХреЗ рдореБрдЦреНрдп рднрд╛рдЧ рдореЗрдВ рдирд┐рдореНрди рд╕рдВрд░рдЪрдирд╛ рд╡рд╛рд▓реА рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреА рдПрдХ рд╕рд░рдгреА рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП:

  • рдирд╛рдо : рд╕рд░реНрд╡рд░ рдкрд░ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХреЗ рдмрд┐рдирд╛ рдмрдирд╛рдИ рдЬрд╛рдиреЗ рд╡рд╛рд▓реА рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдирд╛рдо
  • рдкреНрд░рдХрд╛рд░ : рдлрд╝рд╛рдЗрд▓ рдкреНрд░рдХрд╛рд░ (рдкреНрд░рдХрдЯ рдХреЗ рд▓рд┐рдП JSON, .gs рдХреЗ рд▓рд┐рдП SERVER_JS)
  • рд╕реНрд░реЛрдд : рдлрд╝рд╛рдЗрд▓ рдХреЛрдб

 request = { 'files': [{ 'name': 'hello', 'type': 'SERVER_JS', 'source': sample_code }, { 'name': 'appsscript', 'type': 'JSON', 'source': MANIFEST } ] } 

рдЕрдВрдд рдореЗрдВ, рдЕрдкрдбреЗрдЯ рдЕрдиреБрд░реЛрдз рдореЗрдВ рд╕реНрд╡рдпрдВ рд╢рд░реАрд░ (рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рдЕрдиреБрд░реЛрдз) рдФрд░ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЖрдИрдбреА рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдПред рдЙрддреНрддрд░рд╛рд░реНрджреНрдз рдХреЛ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╕рдВрдкрд╛рджрдХ рдореЗрдВ "рдлрд╛рдЗрд▓" -> "рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдЧреБрдг" рдкрд░ рдЬрд╛рдХрд░ рдФрд░ "рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЖрдИрдбреА" рдХреА рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░рдХреЗ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:

 script_id = 'qwertyuiopQWERTYUIOPasdfghjkl123456789zxcvbnmASDFGHJKL54' 

рд▓реЙрдЧрд┐рди рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдкреНрд░рд╛рдкреНрдд рдХреА рдЧрдИ рд╕реЗрд╡рд╛ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП, рд╣рдо рдкреНрд░реЛрдЬреЗрдХреНрдЯреНрд╕ () рдлрд╝реАрд▓реНрдб рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЕрдкрдбреЗрдЯрдХрдВрдЯреЗрдВрдЯ () рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХреЗ рдмрд╛рдж рд╣рдо рдкреНрд░рд╛рдкреНрдд HttpRequest рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП рдирд┐рд╖реНрдкрд╛рджрди () рд╡рд┐рдзрд┐ рдХрд╣рддреЗ рд╣реИрдВ:

 service.projects().updateContent( body=request, scriptId=script_id ).execute() 

рд╣рд╛рд▓рд╛рдБрдХрд┐, рдЕрднреА рдХреЗ рд▓рд┐рдП, рдХреЛрдб рдЪрд▓рд╛рдиреЗ рд╕реЗ рддреНрд░реБрдЯрд┐ рд╣реЛрдЧреА:

 "error": { "code": 403, "message": "Request had insufficient authentication scopes.", "status": "PERMISSION_DENIED" } 

рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдУрд╕реНрдкреНрд░реЗ рдореЗрдВ рдкрд░реНрдпрд╛рдкреНрдд рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рд╣реИ, рдЬрд┐рд╕реЗ рд╣рдордиреЗ рдкрд╣рд▓реЗ рд╕рдВрдХреЗрдд рджрд┐рдпрд╛ рдерд╛ред рд╣рдо рдПрдкреАрдЖрдИ рдкрд░ рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рджрд╕реНрддрд╛рд╡реЗрдЬ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рддреЗ рд╣реИрдВ, рдЕрд░реНрдерд╛рддреН рдЕрдкрдбреЗрдЯрдХреЙрдиреНрдЯреЗрдВрдЯ рд╡рд┐рдзрд┐, рдЬрд┐рд╕реЗ рд╣рдо рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рджреВрд░рд╕реНрде рд░реВрдк рд╕реЗ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рдереЗред рдкреНрд░рд▓реЗрдЦрди рдХрд╛ рдХрд╣рдирд╛ рд╣реИ рдХрд┐ рдЗрд╕ рдкрджреНрдзрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП script.projects рддрдХ рдкрд╣реБрдВрдЪ рдХреЛ рд╕рдХреНрд╖рдо рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ:

 https://www.googleapis.com/auth/script.projects 

рдЗрд╕реЗ SCOPES рдЕрдиреБрднрд╛рдЧ рдореЗрдВ рд╣рдорд╛рд░реА рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдЬреЛрдбрд╝реЗрдВред рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рдКрдкрд░ рд▓рд┐рдЦрд╛ рд╣реИ, рдЬрдм рдУрд╕реНрдкреНрд░реЗ рдмрджрд▓рддреЗ рд╣реИрдВ, рддреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдЙрддреНрдкрдиреНрди рдЯреЛрдХрди рдХреЛ рд╣рдЯрд╛рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред

рдмрд╣реБрдд рдмрдврд╝рд┐рдпрд╛! рдлрд┐рд▓рд╣рд╛рд▓, рд╣рдордиреЗ Google рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рджреВрд░рд╕реНрде рд░реВрдк рд╕реЗ рдЕрдкрдбреЗрдЯ рдХрд░рдирд╛ рд╕реАрдЦ рд▓рд┐рдпрд╛ рд╣реИред рдпрд╣ рдЗрд╕реЗ рдЪрд▓рд╛рдиреЗ рдФрд░ рдирд┐рд╖реНрдкрд╛рджрди рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдиреА рд╣реБрдИ рд╣реИред

рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд░рди


рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд▓реЙрдиреНрдЪ рдЕрдиреБрд░реЛрдз рдореЗрдВ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдФрд░ рдмреЙрдбреА рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рдВрд░рдЪрдирд╛ рдХреЗ рд╕рд╛рде рд╣реИрдВ:

  • рдлрд╝рдВрдХреНрд╢рди : рдЙрд╕ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдирд╛рдо рдЬрд┐рд╕реЗ рд╣рдо рдЪрд▓рд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ
  • рдкреИрд░рд╛рдореАрдЯрд░ : (рд╡реИрдХрд▓реНрдкрд┐рдХ) рдПрдХ рдЖрджрд┐рдо рдкреНрд░рдХрд╛рд░ рдХреЗ рдорд╛рдкрджрдВрдбреЛрдВ рдХрд╛ рдПрдХ рд╕реЗрдЯ (рд╕реНрдЯреНрд░рд┐рдВрдЧ, рд╕рд░рдгреА ...) рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкрд╛рд╕ рдХрд┐рдпрд╛ рдЧрдпрд╛
  • sessionState : (рд╡реИрдХрд▓реНрдкрд┐рдХ) рдХреЗрд╡рд▓ Android рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реИ
  • devMode : (рд╡реИрдХрд▓реНрдкрд┐рдХ) рд╕рд╣реА рд╣реИ рдпрджрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдорд╛рд▓рд┐рдХ рд╣реИ рдФрд░ рдлрд┐рд░ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг рд▓реЙрдиреНрдЪ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдЬреЛ рдХрд┐ рдПрдкреНрд╕ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдПрдкреАрдЖрдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рддреИрдирд╛рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред (рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ - рдЧрд▓рдд)

рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ Google рдлреЙрд░реНрдо рдХреЗ URL рдХреЛ рд╕рд┐рд▓рд╛рдИ рдирд╣реАрдВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо form_url рдХреЛ рдореБрдЦреНрдп рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдПрдХ рддрд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╛рд╕ рдХрд░реЗрдВрдЧреЗред

рдЪреЗрддрд╛рд╡рдиреАред рдЬрдм рд╣рдордиреЗ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛, рддреЛ рдореБрдЦреНрдп рдлрд╝рдВрдХреНрд╢рди рдиреЗ рдХреБрдЫ рднреА рд╕реНрд╡реАрдХрд╛рд░ рдирд╣реАрдВ рдХрд┐рдпрд╛, рдЗрд╕рд▓рд┐рдП рд╣рдо .gs рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдХреЛрдб рдХреА рдкрд╣рд▓реА рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХреЛ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдмрджрд▓реЗрдВрдЧреЗ:

 function main(form_url) { var form = FormApp.openByUrl(form_url); ....... 

рдЪреВрдВрдХрд┐ рд╣рдорд╛рд░рд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдПрдВрдбреНрд░реЙрдЗрдб рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ рд╣реИ рдФрд░ рд╣рдо рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЗ рдорд╛рд▓рд┐рдХ рд╣реИрдВ, рддреЛ рд╢рд░реАрд░ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛:

 body = { "function": "main", "devMode": True, "parameters": form_url } 

рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЪрд▓рд╛рдПрдБ рдФрд░ рдирд┐рд╖реНрдкрд╛рджрди рдЪрд░ рдХреЗ рдкрд░рд┐рдгрд╛рдо рдХреЛ рд▓рд┐рдЦреЗрдВ

 resp = service.scripts().run(scriptId=script_id, body=body).execute() 

рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ JSON рдлрд╝реЙрд░реНрдореЗрдЯрд┐рдВрдЧ рд╡рд╛рд▓реА рдлрд╝рд╛рдЗрд▓ рдХрд╛ рд╕рдореНрдорд╛рди рд╕рд╣реЗрдЬреЗрдВ:

 import json with open('habr_auto.json', 'w', encoding='utf-8') as f: json.dump(resp['response']['result'], f, ensure_ascii=False, indent=4) 

рдЪреЗрддрд╛рд╡рдиреАред рдЗрд╕ рддрдереНрдп рдХреЗ рдХрд╛рд░рдг рдХрд┐ script.run () рдЕрдиреБрд░реЛрдз рд╕реЙрдХреЗрдЯ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкрд░рд┐рдгрд╛рдо рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░ рд░рд╣рд╛ рд╣реИ, рдЬрдм рдирд┐рд╖реНрдкрд╛рджрди рд╕рдордп рд╕реЗ рд╕рдордп рд╕рдорд╛рдкреНрдд рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдирд┐рдореНрди рдкреНрд░рдХрд╛рд░ рдХреА рддреНрд░реБрдЯрд┐ рдЙрддреНрдкрдиреНрди рд╣реЛрдЧреА:

 socket.timeout: The read operation timed out 

рдЗрд╕ рд╡реНрдпрд╡рд╣рд╛рд░ рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВ рд╕реБрдЭрд╛рд╡ рджреЗрддрд╛ рд╣реВрдВ рдХрд┐ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ рдЦреБрд▓реЗ рд╕реЙрдХреЗрдЯ рд╕рдордп рдкрд░ рдПрдХ рд╕реАрдорд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░реЗрдВ, рдЬрд╛рд╣рд┐рд░ рд╣реИ рдХрд┐ рдЗрд╕рдХреЗ рд▓рд┐рдП рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рд╕рдорд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрдВрддрдЬрд╛рд░ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдореЗрд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, 120 рд╕реЗрдХрдВрдб рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ:

 import socket socket.setdefaulttimeout(120) 

рджреЗрдЦрд╛! Google рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рджреВрд░рд╕реНрде рдЕрджреНрдпрддрди рдФрд░ рд▓реЙрдиреНрдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рддреИрдпрд╛рд░ рд╣реИред рдЯрд░реНрдорд┐рдирд▓ рд╕реЗ рд▓реЙрдиреНрдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдиреБрдХреВрд▓рд┐рдд рдкреВрд░реНрдг рдХреЛрдб рдореЗрд░реЗ рдЬреАрдердм рдореЗрдВ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред

рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдореИрдВ рдиреАрдЪреЗ рджрд┐рдП рдЧрдП рдореБрдЦреНрдп рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдХреЛрдб рджреВрдВрдЧрд╛

login.py
 from pprint import pprint import pickle import os.path from googleapiclient.discovery import build from google_auth_oauthlib.flow import InstalledAppFlow from google.auth.transport.requests import Request def login(config): try: creds = None # The file token.pickle stores the user's access and refresh tokens, and is # created automatically when the authorization flow completes for the first # time. token_file = config['credentials_path'] + config['token_file'] credentials_file = config['credentials_path'] + config['credentials_file'] if os.path.exists(token_file): with open(token_file, 'rb') as token: creds = pickle.load(token) # If there are no (valid) credentials available, let the user log in. if not creds or not creds.valid: if creds and creds.expired and creds.refresh_token: creds.refresh(Request()) else: flow = InstalledAppFlow.from_client_secrets_file(credentials_file, config['SCOPES']) creds = flow.run_local_server(port=0) # Save the credentials for the next run with open(token_file, 'wb') as token: pickle.dump(creds, token) service = build('script', 'v1', credentials=creds) pprint('Login successful') return service except Exception as e: pprint(f'Login failure: {e}') return None 


update_script.py
 from pprint import pprint import json import sys from googleapiclient import errors from google_habr_login import login MANIFEST = ''' { "timeZone": "America/New_York", "exceptionLogging": "STACKDRIVER", "executionApi": { "access": "ANYONE" } } '''.strip() def update_project(service, script_id, script_file_name): # Read from file code we want to deploy with open(script_file_name, 'r') as f: sample_code = f.read() # Upload two files to the project request = { 'files': [{ 'name': 'hello', 'type': 'SERVER_JS', 'source': sample_code }, { 'name': 'appsscript', 'type': 'JSON', 'source': MANIFEST } ] } # Update files in the project service.projects().updateContent( body=request, scriptId=script_id ).execute() pprint('Project was successfully updated') def main(): try: args = sys.argv if len(args) != 4: raise TypeError('Wrong number of arguments. Three argument required: <config_file_name>, <script_id> and ' '<script_file_name>') config_file_name = args[1] script_id = args[2] script_file_name = args[3] with open(config_file_name, "r") as f: config = json.load(f) service = login(config) update_project(service, script_id, script_file_name) except (errors.HttpError, ) as error: # The API encountered a problem. pprint(error.content.decode('utf-8')) if __name__ == '__main__': main() 


export_form.py
 from pprint import pprint import socket import json import sys from googleapiclient import errors from google_habr_login import login socket.setdefaulttimeout(120) # Get JSON, which is returned by script def get_json(service, file_name, script_id, form_url): pprint('Exporting form...') body = { "function": "main", "devMode": True, "parameters": form_url } # Get JSON from script resp = service.scripts().run(scriptId=script_id, body=body).execute() # Write out JSON to file with open(file_name, 'w', encoding='utf-8') as f: json.dump(resp['response']['result'], f, ensure_ascii=False, indent=4) pprint('Form was successfully exported') def main(): try: args = sys.argv if len(args) != 5: raise TypeError('Wrong number of arguments. Four arguments required: <config_file_name>, ' '<result_file_name>, <script_id> and <google_form_url>') config_file_name = args[1] file_name = args[2] script_id = args[3] form_url = args[4] with open(config_file_name, "r") as f: config = json.load(f) service = login(config) get_json(service, file_name, script_id, form_url) except (errors.HttpError, ) as error: # The API encountered a problem. pprint(error.content.decode('utf-8')) if __name__ == '__main__': main() 


рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ JSON рдлрд╝рд╛рдЗрд▓ рдХреЛ рдХреНрд░реЗрдбреЗрдВрд╢рд┐рдпрд▓ рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ Google рдкрд╣реБрдВрдЪ рдХреБрдВрдЬрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдФрд░ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрд╕реА рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди JSON рдбрд╛рд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

рдлрд┐рд░, рдпрджрд┐ рд╣рдо рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рджреВрд░рд╕реНрде рд░реВрдк рд╕реЗ рдЕрдкрдбреЗрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдЯрд░реНрдорд┐рдирд▓ рдХреЙрд▓ рдореЗрдВ:

 python update_script.py <config_file_name> <script_id> <script_file_name> 

рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ:

  • config_file_name - рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди JSON рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдирд╛рдо
  • script_id - рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЖрдИрдбреА
  • script_file_name - .gs рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдирд╛рдо рдЬрд┐рд╕реЗ Google рдкрд░ рдЕрдкрд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛

рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдХреЙрд▓ рдХрд░реЗрдВ:

 python export_form.py <config_file_name> <result_file_name> <script_id> <google_form_url> 

рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ:

  • config_file_name - рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди JSON рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдирд╛рдо
  • result_file_name - JSON рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдирд╛рдо рдЬрд┐рд╕рдореЗрдВ рдлрд╝реЙрд░реНрдо рдЕрдирд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛
  • script_id - рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЖрдИрдбреА
  • google_form_url - Google рдлрд╝реЙрд░реНрдо url

рдЖрдкрдХреЗ рдзреНрдпрд╛рди рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж, рдЖрдкрдХреЗ рд╕реБрдЭрд╛рд╡реЛрдВ рдФрд░ рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдореЗрдВ :)

Source: https://habr.com/ru/post/hi485898/


All Articles